Webrium
Подписаться

OpenTelemetry: что стало стандартом, а что ещё нет

Разберёмся, какие слои OpenTelemetry действительно стали стандартами, а какие остаются удобным клеем, и почему граница проходит именно между ними

Поле, разделённое швом: элементы OpenTelemetry пересекают границу между тем, что уже стало стандартом, и тем, что остаётся удобным клеемСтало стандартомУдобный клей

Откуда растёт вопрос

Ситуация знакома почти любой платформе: метрики экспортируются в pull-формате, логи пишутся в файлы и увозятся шиппером, трейсов нет вовсе, а бэкенд наблюдаемости хочется уметь менять, не трогая код приложений. Под этот запрос продаётся OpenTelemetry: спецификация модели данных, SDK под популярные языки и коллектор, вместе обещающие телеметрию без привязки к вендору. Если совсем коротко, это попытка описать трейсы, метрики и логи единым способом — от приложения до порога бэкенда.

Здесь же начинается путаница, потому что словом «стандарт» в OpenTelemetry называют три разные вещи: протокол передачи с моделью данных, словарь имён атрибутов и готовые программные компоненты. Стандартом успела стать первая. Вторая и третья — нет, и причины у каждой свои.

Что уже стало стандартом

Фундамент — разделение API и SDK, доставшееся от слияния OpenTracing и OpenCensus: первый предлагал только интерфейс, второй — всё в комплекте. Приложение зависит лишь от тонкого API, у которого по умолчанию может стоять пустая реализация; SDK с настоящей работой подключается снаружи, как зависимость деплоя. Код перестаёт знать, кто и куда отправляет телеметрию, — единственная часть истории, которая работает одинаково во всех языках.

Второе — трейсы. Модель мала: спан — именованный интервал с родителем, дерево таких интервалов и есть трейс. Малую модель трудно испортить. Протокол OTLP, поверх gRPC и HTTP, приняли на вход почти все бэкенды. Пока приложение говорит на OTLP, оно не знает вендорских диалектов: смена хранилища трейсов — правка адреса экспорта в конфигурации, а не проект с переписыванием кода. Ровно этого от стандарта и хотели.

Третье — распространение контекста, стандартизованное не внутри проекта, а снаружи, в W3C: заголовки traceparent и tracestate. Это важнее, чем кажется: контекст умеет нести любая система, даже не знающая про OpenTelemetry, — достаточно пересылать заголовки. Рядом едет baggage, пары «ключ–значение», путешествующие с запросом; тут же первое предостережение: багаж пересекает границы сервисов, поэтому большие и чувствительные данные в него не кладут.

Почему стандартным стал именно этот слой? Из устройства, а не из удачи. У трейсов не было действующего формата, который пришлось бы вытеснять: для большинства стеков это новая способность, а не пересадка живого. Вводить новое дешевле, чем пересаживать существующее, и модель успели зафиксировать до того, как нарос груз обратной совместимости.

Что стандартом ещё не стало

Дальше идут слои, где пахнет стандартом, но не стандарт.

Логи. В каждом языке давно сложилась своя экосистема: аппендеры, ротация, фильтрация секретов. OpenTelemetry не пытается её заменить — строит мост: специальный пакет берёт запись из привычного фреймворка, штампует в неё идентификатор трейса и отправляет по OTLP. Качество моста зависит от языка, а сама «стандартность» логов конкурирует с трубой, которая уже работает: приложение → файл → шиппер → бэкенд. Там, где нет давления вытеснения, стандартизация не ускоряется. Стандартом в логах можно считать одно: trace_id попадает в запись и связывает её с трейсом. Остальное — клей, разный в каждой экосистеме.

Метрики. Мешает двойная наследственность: одна традиция — pull и кумулятивные счётчики, другая — push и дельты. Модель данных вынуждена уметь обе, и по пути она менялась с ломкой совместимости. Неприятный побочный эффект: темпоральность задаётся в настройках экспорта на стороне приложения, то есть предпочтение бэкенда просачивается в ваш конфиг — обещание «бэкенд не касается кода» даёт трещину. Коллектор закрывает её конвертацией, но конвертация требует состояния: чтобы вычесть из кумулятивного счётчика предыдущее значение, надо его помнить, а при рестарте процесса счётчик обнуляется, память сбивается и на стыке получается мусор. Ссылки из точек метрик на трейсы (exemplars) поддерживаются неравномерно. Слой рабочий, но тряский.

Семантические конвенции. Это словарь: договорённость, как называть атрибуты, чтобы метод HTTP звался одинаково у всех. Именно к этому слою цепляются ваши панели — и именно он чаще всего правится: реальное употребление вскрывает неудачное моделирование, атрибуты переименовывают, и панель, построенная на старом имени, после обновления молча пустеет. Поэтому у конвенций есть статусы, стабильные и разрабатываемые, и зрелость добирается сюда последней: каждое переименование дорого пользователям, проект консервативен, а консервативность — это медленно. Покрытие неравномерное: вокруг HTTP словарь устоялся, вокруг баз данных и брокеров — тоньше и правится чаще. Идентификация источника данных — сервис, контейнер, узел — тоже часть словаря, и она тоже в движении.

Асинхронные границы. Стандарт распространения контекста описывает заголовки HTTP. Когда сервисы общаются через брокер, контекст должен ехать в заголовках сообщения, а у каждого брокера и клиентской библиотеки свои привычки. Сквозной трейс рвётся ровно там, где ваша архитектура наиболее асинхронна.

Остальное — одной строкой: профилирование — самый молодой сигнал, в продакшене на него пока не обопрёшься; хвостовое сэмплирование живёт не в спецификации, а процессором коллектора, и требует буферизации спанов; инструментация без правок кода по-настоящему есть на JVM и в .NET, в Go она превращается в ручную проводку библиотек.

Коллектор: стандарт или продукт

Характерная поломка, из-за которой говорят «OpenTelemetry сломалось», сидит не в спецификации, а в коллекторе. Его путают со стандартом, а он — программа со своим циклом релизов: приёмники, процессоры и экспортёры появляются, переименовываются и выбывают; конфигурация — собственный диалект, меняющийся между версиями; основной дистрибутив — толстый бинарник, где компоненты едут и обновляются вместе.

Отсюда типичный сценарий: коллектор ставят по модели «поставил и забыл», как системную утилиту, а эксплуатируют как приложение. Ожидание задано словом «стандарт», реальность — движущимся продуктом. Честная рамка такая: стандарт заканчивается на протоколе. Коллектор — референсная реализация конвейера, полезная, но версионируемая как любая зависимость: фиксируйте версию, читайте changelog, относитесь к обновлению как к обновлению.

Тупик: поставить коллектор и включить автоинструментацию

Первым делом пробуют одно и то же: ставят коллектор, включают автоинструментацию и ждут, когда наблюдаемость «сойдётся». Не сходится, и вот почему — каждая причина следует из устройства.

Первая: коллектор ничего не собирает сам. Он состоит из приёмников, процессоров и экспортёров, и данные в него должен кто-то доставить. В сервисах, где автоинструментацию не включили или её нет без ручной проводки, труба стоит пустая; снаружи это выглядит как «OpenTelemetry не работает».

Вторая: автоинструментация видит фреймворки, а не ваши шаги. Она оборачивает входящие и исходящие HTTP-запросы, драйверы баз данных, клиентов брокеров — транспортный скелет. Бизнес-логика спанов не порождает вообще: трейс покажет дороги, но не движение. Разбирая, почему застряла оплата, вы обнаружите, что интересующего вас спана не существует.

Третья: панели, построенные в первый же день, сидят на конвенциях, которые переименовывают. Обновление доезжает, атрибут меняет имя, панель пустеет молча — алерт не срабатывает, и замечают это не сразу.

Проверить первые две причины на себе несложно. Запустите одну бизнес-операцию через сервис с автоинструментацией, откройте трейс и посчитайте спаны, в которых звучит ваш домен, против спанов про транспорт. Это соотношение — потолок автоинструментации навсегда; всё сверх него — ручные спаны. Как размечать шаги, чтобы трейс отвечал на вопрос «где застряло», а не «какие библиотеки вызывались», мы разбирали в материале про трассировку шагов вместо логов.

Заодно оцените цену миграции: поищите в коде прямые вызовы SDK текущего бэкенда. Каждое совпадение — место, где смена бэкенда означает правку кода. Если совпадений мало, аргумент переносимости сегодня слаб — но труба всё равно окупится при следующей смене.

Позиция редакции

Наша позиция: внедряйте OpenTelemetry как трубу — уже сейчас. OTLP на входе в бэкенд, W3C Trace Context между сервисами, коллектор как этап конвейера с зафиксированной версией. Словарь и миграцию логов с метриками не форсируйте: рабочую инструментацию не вырывайте, гоняйте новый сигнал параллельно со старым и мигрируйте по одному сигналу, начиная с трейсов — единственного, где стандарт уже держит вес.

Наша позиция неверна, если семантические конвенции по всем сигналам, которыми вы пользуетесь, дойдут до стабильного статуса, а ваш бэкенд научится строить панели и алерты прямо из словаря, без ручного маппинга с вашей стороны. Тогда выжидание перестаёт быть разумным: перенос атрибутов на конвенции сразу дешевле, потому что главный риск, от которого мы прячемся, — переименование, ломающее панели, — исчезает. Проверять просто: следите за статусом конвенций, на которых сидят ваши панели. Пока они в статусе разрабатываемых, наша позиция стоит; как только нужные вам группы перешли в стабильные и бэкенд читает их без вашего клея — позиция неверна, переносите атрибуты не откладывая.

Есть и второй случай, при котором часть позиции не работает: если вендорский SDK в коде сам стал источником инцидентов или мешает обновлению фреймворка и рантайма. Тогда совет «не вырывайте рабочую инструментацию» вреден: параллельный период стоит дороже немедленного демонтажа, и вырывать нужно сейчас, не дожидаясь стабильности словаря.

Отдельная оговорка для тех, кто уверен, что бэкенд не сменится никогда: переносимость тогда не стоит ничего, и даже труба — лишний слой. Но такие уверенности обычно дешёвые: смена бэкенда редко бывает плановой, чаще это покупка, слияние или смена тарифа, и узнаёте вы о ней постфактум.

С чем это связано

Метка над заголовком говорит, зачем туда идти: продолжить тему, перейти к практике или увидеть возражение.

Сетка из пятнадцати ячеек изображает ленту лога: девять заняты событиями, а рядом отдельный счётчик показывает лишь четыре причины решений — лента отвечает «гдепричины решений
Углубление

Трассировка шагов вместо логов

Логи отвечают не на тот вопрос: где упало — видно, почему агент решил именно так — нет. Как устроена трассировка шагов и где её ждёт тупик с идентификатором прогона в каждой строке.

Четыре показателя-поля трейса: ID запроса, шаг вызова и код ошибки в норме, а тело запроса уходит за шкалу — его место в архиве, а не в трейсетело запроса
Предыстория

Что писать в трассировку, а что нет

Перед разговором о стандартах стоит разобраться, какие поля остаются в спанах, а какие уходят в архив, чтобы дежурный сразу видел, где сломался запрос.

Из шести алертов в канале лишь один требует действия дежурного, остальные проматываютсяпоток алертовтребует действия
Практика

Алерты, на которые перестали смотреть

Дежурные рационально перестают читать канал алертов, а крутить пороги — тупик: частота меняется, применимость — нет. Что с этим делать руками — тоже разобрано.

Письмо по вторникам

Один разбор недели и короткий список того, что изменилось. Без дайджестов на сорок ссылок.

Начните вводить — материалы появятся здесь.

выбрать · Enter открыть · Esc закрыть