Ответ
Observability (наблюдаемость) — это способность понимать внутреннее состояние системы, анализируя её внешние выходные данные. В отличие от простого мониторинга, который отслеживает заранее известные метрики, наблюдаемость позволяет задавать системе произвольные вопросы для отладки неизвестных проблем.
Она строится на трёх столпах (Three Pillars of Observability):
Логи (Logs): Записи о событиях, произошедших в системе. В Go для структурированного логирования я использую:
slog
: Стандартная библиотека, добавленная в Go 1.21.Zap
илиLogrus
: Популярные сторонние библиотеки для высокопроизводительного структурированного логирования.- Логи обычно отправляются в централизованные системы, такие как Loki или Elasticsearch.
Метрики (Metrics): Агрегированные числовые данные за определённый период времени (например, RPS, задержка, использование CPU).
- Prometheus: Стандарт де-факто для сбора метрик. Приложения на Go с помощью клиентской библиотеки
prometheus/client_golang
предоставляют HTTP-эндпоинт/metrics
, откуда Prometheus периодически собирает данные. - Grafana: Используется для визуализации метрик, собранных Prometheus.
- Prometheus: Стандарт де-факто для сбора метрик. Приложения на Go с помощью клиентской библиотеки
Трассировка (Traces): Отслеживание полного пути одного запроса через все микросервисы, которые он затрагивает. Это критически важно для отладки в распределённых системах.
- OpenTelemetry (OTel): Текущий индустриальный стандарт для сбора трассировок, метрик и логов. Он предоставляет API и SDK для инструментирования кода.
- Jaeger или Zipkin: Бэкенды для хранения и визуализации распределённых трасс, собранных с помощью OpenTelemetry.
Пример инструментирования функции с помощью OpenTelemetry:
import (
"context"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
)
var tracer = otel.Tracer("my-service-tracer")
func GetUserFromDB(ctx context.Context, userID int) (User, error) {
// Начинаем новый span (участок трассировки)
ctx, span := tracer.Start(ctx, "GetUserFromDB")
defer span.End() // Обязательно завершаем span
// Добавляем атрибуты для детализации
span.SetAttributes(attribute.Int("db.user.id", userID))
// ... логика обращения к базе данных ...
return user, nil
}
Комплексное использование этих трёх компонентов даёт полное представление о поведении и производительности системы.