Особенности работы OpenTelemetry трассировщика в Golang
OpenTelemetry трассировщик в Go спроектирован так, чтобы минимизировать влияние на основной процесс выполнения программы. Он это достигает за счёт асинхронной обработки данных, эффективного управления буферизацией и отправкой, а также оптимизированного дизайна API. Вот основные принципы, которые помогают ему не тормозить основной процесс:
1. Асинхронная отправка данных
- Трейсы и спаны, создаваемые в вашем приложении, сначала сохраняются локально в памяти (буферизуются).
- Вместо того чтобы отправлять данные сразу же в момент создания, трассировщик использует фоновые горутины для передачи этих данных в OpenTelemetry Collector или другую конечную точку.
- Это устраняет необходимость ожидания сети или отклика сервера в основном потоке.
Пример настройки асинхронной отправки:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import ( "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" ) func setupTracer() { exporter, _ := otlptracehttp.New(context.Background()) batcher := trace.NewBatchSpanProcessor(exporter) tp := trace.NewTracerProvider( trace.WithSpanProcessor(batcher), ) defer tp.Shutdown(context.Background()) } |
В данном примере BatchSpanProcessor
выполняет отправку в отдельной горутине.
2. Буферизация и пакеты
- Трейсы группируются в пакеты (batching) перед отправкой, чтобы уменьшить количество сетевых запросов.
- Это позволяет сократить накладные расходы на обработку каждого отдельного спана.
Вы можете настроить параметры буферизации в BatchSpanProcessor
:
- Максимальный размер пакета (
MaxExportBatchSize
) - Время ожидания перед отправкой (
ScheduleDelay
)
Пример:
1 2 3 4 5 6 |
batcher := trace.NewBatchSpanProcessor( exporter, trace.WithMaxExportBatchSize(1024), trace.WithScheduleDelay(5*time.Second), ) |
3. Минимальное использование блокировок
- API трассировщика спроектировано так, чтобы минимизировать использование блокировок (mutexes) при создании спанов и записи данных.
- В большинстве случаев операции записи выполняются в неблокирующем режиме с использованием кольцевых буферов или аналогичных структур данных.
4. Динамическое управление нагрузкой
- В случае высокой нагрузки или проблем с сетью трассировщик может пропускать (дропать) некоторые трейсы, чтобы избежать перегрузки системы. Это называется вынужденным сбросом данных (forced sampling).
Пример настройки процентного отбора:
1 2 3 4 |
tp := trace.NewTracerProvider( trace.WithSampler(trace.ParentBased(trace.TraceIDRatioBased(0.5))), ) |
В данном примере только 50% трассировок будут записаны.
5. Лёгкая API-интеграция
- API для создания спанов и контекстов является минимально инвазивным и не требует значительных изменений в основном коде. Большинство операций — это просто добавление метаданных (tags/attributes) к текущему контексту.
Пример:
1 2 3 4 5 6 |
tr := tp.Tracer("example.com/trace") ctx, span := tr.Start(ctx, "main-operation") defer span.End() // Основной код выполнения |
6. Настраиваемые экспортеры
Экспортеры (например, OTLP, stdout) имеют свои собственные фоновые процессы, которые можно оптимизировать под ваши потребности. Это даёт гибкость в зависимости от инфраструктуры (сеть, объём данных и т.д.).
Пример настройки OTLP-экспортера:
Recommended Posts
Golang Sarama: настройка Partitioner
20.03.2024