OpenTelemetry: следим за единым стандартом observability с момента анонса
OpenTelemetry объединил OpenCensus и OpenTracing в один SDK для метрик, трейсов и логов. Смотрим что это даёт на практике, если сейчас у вас три разных библиотеки.
OpenTelemetry анонсирован в мае 2019 как слияние OpenCensus и OpenTracing - единый стандарт инструментирования для трассировки, метрик и логов в облачных приложениях
В мае на KubeCon EU объявили об OpenTelemetry - слиянии двух конкурирующих проектов: OpenTracing и OpenCensus. Идея простая: один SDK, одна спецификация, все три сигнала - трейсы, метрики, логи. Мы отслеживаем это с самого анонса, потому что проблема, которую это должно решить, у нас вполне реальная.
На managed-проектах за последние полтора года сложилась характерная картина. Для трейсинга - Jaeger с opentracing-go. Для метрик - Prometheus с нативными клиентскими библиотеками. Для структурных логов - кто во что горазд: где-то logrus, где-то zap, корреляция trace_id с логами - на совести разработчика. Три отдельных инструментальных слоя, три набора зависимостей, три способа проставить контекст запроса. Когда сервисов немного - терпимо. Когда сервисов полтора десятка и каждый писала немного другая команда - начинается разброд.
Что именно произошло в мае
OpenTracing - это была спецификация без реализации: API для инструментирования, под которую разные трейсинг-бэкенды (Jaeger, Zipkin, Lightstep) делали свои клиенты. OpenCensus от Google - наоборот, полная реализация сбора и метрик, и трейсов, но без открытой спецификации под ней.
Оба проекта жили параллельно и решали одну задачу. Это было неудобно: выбрав OpenTracing, ты терял метрики из OpenCensus; выбрав OpenCensus, получал vendor-ориентированный SDK. Слияние в OpenTelemetry - попытка закрыть это противоречие. Проект переехал под крыло CNCF, за ним стоят Google, Microsoft, Uber, Lightstep и ещё добрый десяток компаний.
Спецификация OpenTelemetry описывает:
- Единую модель данных для трейсов, метрик и логов.
- API - стабильный интерфейс, который пишет приложение.
- SDK - реализация API с собственной конфигурацией, семплингом, экспортом.
- Протокол OTLP - для передачи данных от агента к коллектору или напрямую в бэкенд.
- Collector - отдельный компонент-прокси, который принимает телеметрию и отправляет куда нужно.
Где сейчас реально находится проект
Здесь важно не обмануться. OpenTelemetry анонсирован в мае, сейчас ноябрь - шесть месяцев. Трейсинговый API для Go и Java уже достаточно стабилен, чтобы экспериментировать. Метрики - в разработке, спецификация меняется. Логи - в черновике, SDK для части языков ещё не готов.
OpenTelemetry Collector существует и работает, но конфигурация его - yaml с пайплайнами receivers/processors/exporters - пока непривычна и документация местами догоняет код. Мы подняли его в тестовом окружении: принимает Jaeger-трейсы по gRPC, отдаёт их обратно в Jaeger через jaeger_grpc экспортер. Работает. Но вопрос «а зачем коллектор если есть Jaeger Agent» остаётся открытым до момента, когда метрики и логи тоже пройдут через него.
Практическая проблема: три библиотеки в одном сервисе
Посмотрели на один из Go-сервисов, где инструментирование исторически наслоилось. Там живут:
opentracing-go+jaeger-client-goдля трейсовprometheus/client_golangдля метрикlogrusдля логов, в хендлерах вручную цепляетсяspan.TraceID()
Корреляция трейса с логом - три строки бойлерплейта в каждом хендлере. Забыл добавить - и при разборе инцидента смотришь в два несвязанных места.
Идея OpenTelemetry: один инициализированный Tracer Provider знает и про трейсы, и про метрики; контекст передаётся единообразно; лог с trace_id - встроенная механика, а не ручной шов.
Сейчас мы не переходим. Причина простая - трейсинговый API для Go помечен как бета, метрики нестабильны. Переписывать инструментирование в продакшн-сервисах под API, который ещё меняется - неоправданный риск. Но пишем новые сервисы уже с прицелом на OpenTelemetry: не используем vendor-специфичные расширения OpenTracing, держимся ближе к стандартным интерфейсам.
Collector как точка сборки
Одна вещь уже вызывает практический интерес - OpenTelemetry Collector как унифицированный прокси. Сейчас у нас Prometheus сам скрейпит метрики, Jaeger Agent сидит sidecar-ом рядом с подом. Два разных агента, разные порты, разные форматы.
Collector предлагает другую модель: один процесс на ноде принимает OTLP от приложений, плюс может скрейпить Prometheus-эндпоинты сам, плюс умеет фильтровать, семплировать и пересылать в несколько бэкендов одновременно. Если метрики дозреют в спецификации - это убирает необходимость держать отдельный Prometheus scraper для части задач.
Что делаем прямо сейчас
- Читаем спецификацию - она публичная, живёт на GitHub в
open-telemetry/opentelemetry-specification. Понять что стабилизировано, а что черновик - важно до любых решений о миграции. - Подняли Collector в dev-окружении рядом с Jaeger, смотрим как он ведёт себя под нагрузкой.
- Новые сервисы инструментируем через
opentelemetry-go, трейсинговый API уже достаточно устоявшийся для нового кода. - Старые сервисы трогаем только при рефакторинге - не ради OpenTelemetry, а если уже есть повод лезть в инструментирование.
Идея единого SDK для всего observability-стека привлекательна не потому что это модно, а потому что реальная боль от трёх несвязанных библиотек хорошо знакома. Вопрос в том, когда спецификация устаканится достаточно, чтобы делать на неё ставку в продакшне. Пока - следим.
- Jaeger в микросервисах: нашли узкое место за час, искали бы неделю · 25 сентября 2019
- SLO на Prometheus: первый error budget и что он нам показал · 15 июля 2019