Ответ
OpenTelemetry (OTel) — это открытый стандарт и набор инструментов для сбора, обработки и экспорта телеметрических данных (трассировок, метрик и логов) из ваших приложений. Его главная цель — унифицировать процесс инструментирования кода для наблюдаемости (observability).
Ключевые концепции:
- API: Набор интерфейсов, которые вы используете в коде своего приложения для генерации телеметрии (например,
tracer.Start(ctx, "my-operation")
). Код приложения зависит только от API, а не от конкретной реализации. - SDK: Реализация API от OpenTelemetry. SDK отвечает за обработку, сэмплирование и экспорт данных.
- Exporter: Компонент, который отправляет обработанные данные в выбранную вами систему мониторинга (бэкенд), например, в Jaeger, Prometheus, Zipkin или Datadog.
Зачем это нужно?
- Стандартизация: Вам не нужно изучать проприетарные агенты и библиотеки для каждого бэкенда мониторинга.
- Отсутствие привязки к вендору (Vendor Lock-in): Вы можете легко переключиться с Jaeger на Datadog, просто поменяв экспортер в конфигурации, не изменяя код приложения.
- Корреляция данных: OTel позволяет связывать трейсы, метрики и логи между собой, давая полную картину происходящего в системе.
Пример на Go (настройка экспорта трейсов в Jaeger):
package main
import (
"context"
"log"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/jaeger"
"go.opentelemetry.io/otel/sdk/resource"
tracesdk "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
)
// newTracerProvider создает и настраивает провайдер трассировки.
func newTracerProvider(url string) (*tracesdk.TracerProvider, error) {
exporter, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(url)))
if err != nil {
return nil, err
}
tp := tracesdk.NewTracerProvider(
tracesdk.WithBatcher(exporter),
tracesdk.WithResource(resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceNameKey.String("my-app"), // Имя вашего сервиса
)),
)
return tp, nil
}
func main() {
tp, err := newTracerProvider("http://localhost:14268/api/traces")
if err != nil {
log.Fatal(err)
}
// Регистрируем наш провайдер как глобальный.
otel.SetTracerProvider(tp)
// Важно не забыть корректно завершить работу провайдера.
defer func() {
if err := tp.Shutdown(context.Background()); err != nil {
log.Printf("Error shutting down tracer provider: %v", err)
}
}()
ctx, span := otel.Tracer("main").Start(context.Background(), "my-main-operation")
defer span.End()
// ... ваша бизнес-логика здесь ...
log.Println("Operation completed.")
}