Контекст
Observability & Monitoring Design
Эта глава - deep dive по distributed tracing внутри общего observability-контура.
Distributed tracing в микросервисах отвечает за точную диагностику latency и ошибок на end-to-end пути запроса. Эта глава продолжает Observability & Monitoring Design и фокусируется на архитектуре и операционных решениях для Jaeger и Tempo.
Инструменты: Jaeger и Tempo
Jaeger
Классический open source tracing backend с понятным UI и быстрым входом для команд, которые начинают путь с distributed tracing.
Сильные стороны
- Быстрый time-to-value: легко показать waterfall и critical path уже на первом rollout.
- Богатый ecosystem и интеграции с OpenTelemetry Collector.
- Удобен как operational UI для on-call и incident triage.
Trade-offs
- При росте объема трейсинга стоимость хранения и индексов становится чувствительной.
- Нужна аккуратная стратегия retention и контроль cardinality тегов.
Tempo
Tracing backend от Grafana Labs, ориентированный на дешевое хранение в object storage и масштабирование большого объема спанов.
Сильные стороны
- Экономика на масштабе за счёт object storage и блочного формата хранения.
- Хорошо сочетается с Grafana Explore и метриками в одном UX-контуре.
- Подходит для high-throughput tracing-платформ и долгого retention.
Trade-offs
- Диагностика зависит от качества тегов и корректной sampling-политики.
- Нужен продуманный read path, иначе trace lookup может стать медленным.
Визуализация tracing-системы
Визуализация tracing-контура в микросервисах
Одна и та же telemetry-платформа обслуживает два разных пути: write path (ingest) и read path (диагностика).
Вертикальная схема ingest-пути
Этапы выстроены сверху вниз: источник, обработка, backend и финальный результат.
Инструментированные микросервисы
SDK создают спаны и передают trace context между HTTP/gRPC/Kafka hop-ами.
OTel Collector
Collector выполняет enrichment, filtering, sampling и маршрутизацию телеметрии.
Ingest backends
Поток экспортируется в Jaeger Collector и/или Tempo Distributor.
Tracing storage
Jaeger пишет индексы/спаны в backend, Tempo складывает blocks в object storage.
Write path: как спаны доходят до хранилищ
- SDK в сервисах создают спаны и передают traceparent между HTTP/gRPC/Kafka hop-ами.
- OTel Collector делает enrichment (service, env, tenant) и применяет sampling policy.
- Collector экспортирует поток в Jaeger Collector и/или Tempo Distributor.
- Jaeger пишет индексы и спаны в backend; Tempo формирует blocks в object storage.
Операционные акценты
- Jaeger удобен для быстрого старта и знакомого UX расследований.
- Tempo экономит стоимость за счёт object storage и отсутствия жесткого индексирования как в classic tracing DB.
- Для high-cardinality сценариев критичны tail sampling и retention tiers.
Design decisions для write/read path
Write path (ingest)
- Контекст должен передаваться на каждой границе: HTTP, gRPC, message broker, background jobs.
- OTel Collector работает как policy-точка: enrichment, filtering, tail sampling и routing в нужный backend.
- Для high-load систем задайте отдельные quota на ingest, чтобы tracing не съедал бюджет логов/метрик.
- Хранение и retention проектируются как product requirement: cold/warm tiers, TTL и цели по стоимости.
Read path (query)
- Ищите trace сначала по impact-сигналам: service, status=ERROR, p95/p99 latency window.
- Jaeger UI и Grafana Explore должны иметь единые naming conventions для service/span attributes.
- Query latency контролируйте как отдельный SLI: инженер должен получить trace за секунды, а не минуты.
- Склейка trace + logs + metrics обязательна: без корреляции расследование становится ручным и медленным.
Практический checklist внедрения
Согласовать обязательные span attributes: service.name, deployment.environment, tenant, error.type.
Ввести отдельные sampling-профили для critical API, background jobs и noisy endpoints.
Проверить нагрузку коллектора и storage на synthetic + production-like трафике.
Встроить trace-ссылки в runbooks и шаблоны incident response для on-call команды.
Частые антипаттерны
Включать 100% sampling без оценки storage/query стоимости и без профилей по критичности трафика.
Ограничиваться только edge-span, теряя внутренние hop-ы между микросервисами.
Смешивать naming span-ов и тегов между командами без общего контракта observability.
Проектировать tracing как отдельный tool, а не как часть incident-management процесса.
