5. Jaeger и альтернативы

Хранение и визуализация распределенных трейсов

«Лучший способ предсказать будущее — воплотить его в коде».
— Алан Кэй

В предыдущих статьях мы научились генерировать спаны в Go-сервисах, наполнять их семантическими атрибутами и пробрасывать W3C-контекст через границы сетевых протоколов. Теперь перед нами встает фундаментальная инфраструктурная задача: где хранить миллиарды спанов в сутки и через какой инструмент визуализировать сложные водопадные диаграммы (Waterfall Diagrams) запросов?

На протяжении многих лет золотым стандартом распределенной трассировки в open-source экосистеме оставался Jaeger. Однако взрывной рост объемов данных и популяризация объектных хранилищ породили новые архитектурные решения — в первую очередь Grafana Tempo.

Разберем, как устроены эти бэкенды под капотом, сколько стоит их эксплуатация и как правильно интегрировать их с приложениями на Go.


Визуализация мира трейсов

Главная ценность систем трассировки — предоставить инженеру интуитивную визуальную шкалу времени (Timeline / Waterfall). Когда в одном трейсе участвуют 50 спанов от 12 сервисов, пользовательский интерфейс должен мгновенно подсвечивать:

  • Критический путь (Critical Path): последовательность операций, определяющая общее время ответа.
  • Параллельные вызовы (Concurrent RPCs): ветвления, где запросы выполнялись одновременно.
  • Точки сбоев: покрасневшие спаны с подробными стектрейсами ошибок.

Jaeger: Классика Open Source

Jaeger — это распределенная система трассировки, изначально разработанная в недрах компании Uber для мониторинга тысяч микросервисов, а затем переданная в CNCF (где стала выпускником высшего уровня). Jaeger написан на Go, что делает его архитектурно близким и понятным нашему сообществу.

Архитектура Jaeger

Jaeger построен на микросервисной архитектуре, что позволяет ему масштабироваться горизонтально.

flowchart LR
    A["Go App"] -->|"OTLP/UDP"| B["otel-collector"]
    B -->|"gRPC"| C["Jaeger Collector"]

    subgraph Storage ["Storage Layer"]
        D["Elasticsearch<br>или Cassandra"]
    end

    C -->|"Write"| D
    D -->|"Read"| E["Jaeger Query<br>UI"]
    F["User"] --> E

    style A fill:#1e293b,stroke:#38bdf8,stroke-width:2px,color:#fff
    style B fill:#312e81,stroke:#818cf8,stroke-width:2px,color:#fff
    style C fill:#065f46,stroke:#10b981,color:#fff
    style Storage fill:#0f172a,stroke:#475569,color:#fff
    style E fill:#78350f,stroke:#f59e0b,color:#fff
  

Компоненты Jaeger:

  1. Collector: Принимает спаны от приложения (или от OTel Collector), валидирует их, индексирует и пишет в базу. Stateless, можно масштабировать горизонтально за балансировщиком нагрузки.
  2. Query: Сервис, обслуживающий UI и API для поиска трейсов.
  3. Agent (Deprecated): Раньше использовался как sidecar для буферизации данных по UDP. Сейчас команда Jaeger рекомендует использовать OpenTelemetry Collector вместо Agent.

Альтернативы: Grafana Tempo

Появление Grafana Tempo изменило правила игры. Tempo не индексирует содержимое трейсов (теги, названия операций). Он индексирует только Trace ID.

Философия: Trace ID Lookup

Как мы обычно ищем трейсы?

  1. Мы видим ошибку в Logs (Loki).
  2. В логе есть trace_id.
  3. Мы копируем этот ID и ищем в трейсинге.

Tempo оптимизирован именно под этот сценарий. Так как он не строит сложных индексов, стоимость хранения трейсов в Tempo в 10-100 раз ниже, чем в Jaeger с Elasticsearch. Данные сжимаются и складываются напрямую в дешевое объектное хранилище (S3/GCS/MinIO).

TraceQL

Tempo представил TraceQL — язык запросов для поиска трейсов, похожий на LogQL.
Пример: {} | span.http.status_code = 500.
Это позволяет искать трейсы, даже если вы не знаете Trace ID заранее, но поиск происходит медленнее, чем по индексу. Движок потоково вычитывает сжатые блоки из S3 параллельными воркерами.


Сравнение систем

Система Стратегия хранения Сложность поддержки Стоимость Best for
Jaeger + ES Индексация всех полей Высокая (Java/ES expertise) Высокая Глубокий аналитический поиск, аудит.
Jaeger + Cassandra Ограниченная индексация Высокая Средняя Экстремальная нагрузка (Uber-scale).
Grafana Tempo No-Index (Object Storage) Низкая Очень низкая Kubernetes, интеграция с Loki/Grafana.
Zipkin Классический старый стандарт Средняя Средняя Legacy системы, простые проекты.

Интеграция с Go: Jaeger vs OTel

Исторически Jaeger имел свои клиентские библиотеки (jaeger-client-go). Это путь в никуда.

Вам не нужно менять код, чтобы сменить бэкенд с Jaeger на Tempo. Вы меняете только конфигурацию Exporter'а в OTel Collector.

Пример конфигурации OTel Collector (отправка в Jaeger):

YAML
# otel-collector-config.yaml
exporters:
  otlp:
    endpoint: jaeger-collector:4317 # Стандартный gRPC порт Jaeger
    tls:
      insecure: true

service:
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [otlp]

Итог

  1. Jaeger — зрелый, мощный инструмент. Идеален, если вам нужен сложный поиск по атрибутам трейсов. Сложен в эксплуатации (особенно с Elasticsearch).
  2. Grafana Tempo — современный стандарт для Kubernetes. Дешевле, проще, интегрирован в экосистему Grafana (Loki + Tempo + Mimir).
  3. OpenTelemetry SDK — единственно верный выбор для Go-приложения. Не завязывайтесь на проприетарные агенты.

Раздел Трейсинга завершен. Мы переходим к практике объединения всех знаний. В следующей статье мы разберем, как связать логи, метрики и трейсы через Correlation ID: 1. Correlation ID.