Что такое OpenTelemetry и как работает распределённая трассировка
Основы4 минРедакция Innovialabs
Коротко
OpenTelemetry — открытый стандарт и набор инструментов для сбора трейсов, метрик и логов; распределённая трассировка с его помощью прослеживает один запрос через все сервисы, передавая общий trace ID с каждым вызовом.
Коротко
OpenTelemetry (OTel) — это открытый стандарт и набор SDK и инструментов для сбора телеметрии: трейсов, метрик и логов. Он не привязан к вендору: вы один раз инструментируете код и отправляете данные в любой бэкенд, который понимает протокол OTLP.
Распределённая трассировка отвечает на один вопрос: что произошло с конкретным запросом, пока он шёл через фронтенд, API, очереди, базы данных и другие сервисы. Каждый запрос получает trace ID, каждый шаг записывает своё время, а бэкенд собирает шаги в единую временную шкалу.
Трейсы и спаны
- Трейс — полная история одного запроса, от точки входа до последнего обращения к базе.
- Спан — одна операция внутри трейса: HTTP-обработчик, SQL-запрос, вызов внешнего API. У спана есть имя, время начала и конца, статус и атрибуты (например,
http.routeилиdb.system). - Спаны образуют дерево: корневой спан — входящий запрос, дочерние — работа, которую он запустил.
Глядя на дерево, вы сразу видите, какой шаг занял больше всего времени или где возникла ошибка, вместо того чтобы сопоставлять логи пяти разных сервисов.
Как работает передача контекста
Чтобы спаны из разных сервисов попали в один трейс, trace ID должен путешествовать вместе с запросом. Это называется context propagation.
- Сервис A начинает трейс и создаёт спан.
- При вызове сервиса B SDK добавляет заголовок с trace ID и ID текущего спана. Стандартный формат — W3C Trace Context (заголовок
traceparent). - Сервис B читает заголовок и создаёт свои спаны как дочерние к спану A.
- С очередями сообщений то же самое: контекст кладётся в заголовки сообщения.
Если хотя бы один сервис в цепочке не передаёт заголовки, трейс рвётся на куски. Это самая частая причина «неполных» трейсов.
OpenTelemetry Collector
Collector — отдельный процесс между приложениями и бэкендом. Его конвейер состоит из трёх частей:
- receivers принимают данные (OTLP, Jaeger, Prometheus и другие);
- processors группируют, фильтруют, обогащают данные и применяют сэмплирование;
- exporters отправляют данные в один или несколько бэкендов.
Минимальная конфигурация выглядит так:
receivers:
otlp:
protocols:
grpc:
http:
processors:
batch:
exporters:
otlp:
endpoint: tempo:4317
tls:
insecure: true
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp]
Зачем Collector, если можно экспортировать прямо из приложения? Бэкенд можно сменить без передеплоя сервисов, секреты не попадают в код приложений, а сэмплирование и объём данных контролируются в одном месте.
С чего начать на практике
- Начните с автоматической инструментации: для многих языков есть агенты и библиотеки, которые создают спаны для HTTP-серверов, клиентов и драйверов БД без изменения кода.
- Задайте понятное service.name каждому сервису, иначе трейсы будет трудно читать.
- Ручные спаны добавляйте только вокруг важных бизнес-операций.
- Настройте сэмплирование: хранить каждый трейс нагруженной системы дорого. Head sampling сохраняет фиксированную долю трейсов, tail sampling в Collector может сохранять все трейсы с ошибками или высокой задержкой.
- Свяжите логи и трейсы: пишите trace ID в каждую строку лога.
Сравнение бэкендов
| Бэкенд | Тип | Сильные стороны | Учтите |
|---|---|---|---|
| Jaeger | Open source, свой сервер | Зрелый, простой интерфейс для поиска и просмотра трейсов | Хранилище обслуживаете сами |
| Grafana Tempo | Open source, свой сервер или облако | Дешёвое объектное хранилище, связка с Grafana, Loki и Prometheus | Поиск опирается на TraceQL и связанные метрики и логи |
| Коммерческие APM (Datadog, New Relic, Honeycomb и другие) | SaaS | Готовые дашборды, алерты, корреляция всех сигналов, без админской работы | Стоимость растёт с объёмом данных; проверьте поддержку OTLP и модель тарификации |
Поскольку OTel не привязан к вендору, выбор не окончательный: можно начать с Jaeger или Tempo, а позже просто поменять exporter в Collector.
Частые ошибки
- Заголовки не передаются через прокси, шлюз или очередь, и трейсы рвутся.
- Слишком много бесполезных спанов, например на каждую мелкую функцию.
- Персональные данные в атрибутах спанов: токены, телефоны, тела запросов.
- Нет сэмплирования, и счёт за хранилище или SaaS оказывается неожиданным.