Наблюдаемость
Что такое trace propagation и почему сломанная propagation хуже отсутствия трейсов
Клиент открывает тикет поддержки: «checkout занял 30 секунд». Tracing-инструмент показывает трейсы для каждого сервиса — но каждый из них один span, не связан ни с чем. Все данные есть, ответов нет.
Что такое trace propagation
Trace propagation — практика передачи маленького идентификатора от одного сервиса к другому на каждом запросе, чтобы вся работа, сделанная через много сервисов для одного пользовательского действия, сшилась в одну картинку.
Без propagation медленный checkout выглядит как 50 разных историй. С ней — один трейс, проходимый сверху вниз за 30 секунд.
Идентификатор несётся в HTTP-заголовке traceparent, определённом спецификацией W3C Trace Context. Каждый сервис, получающий запрос, читает traceparent, использует его как parent для своей работы, генерирует новый span-id для себя и пишет новый traceparent перед любым исходящим вызовом. Trace-id остаётся постоянным на каждом hop; span-id’ы формируют parent-child-дерево.
Метафора эстафеты
Представь доставку Amazon с одним tracking number. Посылка покидает склад, прыгает между сортировочными центрами, едет на трёх грузовиках и наконец приезжает к двери. Каждый hop сканирует тот же tracking number, записывая, где она была, когда и куда следующая.
Если какая-то одна остановка забывает просканировать — страница отслеживания замолкает и непонятно, где посылка, даже если она в итоге доедет.
Trace propagation — это сканирование. Каждый сервис обязан:
- Прочитать входящий
traceparent(извлечь trace-id и parent span-id). - Создать свой span (новый span-id, parent = входящий span-id).
- Написать новый
traceparentперед любым исходящим вызовом (тот же trace-id, свой span-id как новый parent-id).
Пропустишь любой из этих шагов — цепочка рвётся.
Конкретный сценарий с Bea и Sven
On-call-инженер получает тикет поддержки клиента: «checkout занял 30 секунд». Открывает tracing-инструмент, вводит request-id из тикета, поднимает один трейс. Видит: 50 мс на API gateway, 80 мс в auth-сервисе, 28 секунд в inventory-сервисе на ожидании DB-запроса, 200 мс в payment, 100 мс назад пользователю. 28-секундное узкое место точно названо.
Без propagation пришлось бы вручную сопоставлять 50 log-записей через 7 сервисов и угадывать, какие от этого пользователя. С одним трейсом — знаешь за 30 секунд.
Почему сломанная propagation хуже отсутствия трейсов
Без трейсинга вообще знаешь, что трейсов нет, и идёшь в логи. Со сломанной propagation каждый сервис эмитирует span’ы, но ни один не связан с другим — дашборд утверждает, что наблюдает систему, а каждый трейс покрывает только один сервис.
Думаешь, что отлаживаешь end-to-end, а реально отлаживаешь фрагментами. Пропавший трейс делает медленный сервис невидимым: запрос, быстрый в сервисе A и медленный в B, выглядит как быстрый трейс в A и отдельный медленный трейс в B без причинной связи. Операторы тратят часы, подозревая не тот сервис.
Типичный сценарий сбоя: команда добавляет tracing в один сервис, но забывает включить OTel HTTP-client auto-instrumentation. Каждый span стартует свежий трейс; дашборд показывает трейсы, но каждый — глубиной в один span. Клиенты жалуются на медленный journey, команда не может найти, где время — трейс тихо расщеплён на 50 кусков.
| Состояние propagation | Что видишь в дашборде | Что можешь отладить |
|---|---|---|
| Нет трейсинга вообще | Ничего | Только логи — знаешь, что гадаешь |
| Сломанная propagation | Трейсы везде, каждый глубиной 1 span | Ничего end-to-end — но дашборд утверждает, что можешь |
| Правильная propagation | Полное дерево: API → auth → inventory → payment | Точное узкое место за 30 секунд |
Трейс пропагируется между сервисами каким HTTP-заголовком (по W3C-стандарту)?
Какой самый частый production-сбой trace propagation?
Расставь, что происходит, когда запрос идёт через три сервиса с правильной propagation:
- 1 Клиент A генерирует новый trace-id и span-id, строит заголовок traceparent
- 2 Клиент A отправляет HTTP-запрос в сервис B с заголовком traceparent
- 3 Сервис B извлекает trace-id, создаёт свой span (новый span-id, parent = span-id клиента)
- 4 Сервис B зовёт сервис C: строит свежий traceparent с тем же trace-id, но со своим span-id как новый parent-id
- 5 Сервис C извлекает trace-id, создаёт свой span (parent = span-id B), делает работу
- 6 Каждый сервис эмитирует свой span в tracing-backend; backend сшивает по trace-id
- 7 Дашборд показывает полное дерево: A → B → C, span'ы делят один trace-id
Заполни пропуск: стандартный HTTP-заголовок, несущий идентификатор трейса между сервисами, называется _______.
- 01В одном абзаце: почему сломанная trace propagation хуже отсутствия трейсов вообще?
- 02Что три вещи обязан сделать каждый сервис, получив запрос с заголовком traceparent?
- 03Назови три состояния трейсинга и что каждое значит для отлаживаемости.
Trace propagation сшивает всю работу, сделанную для одного пользовательского запроса через каждый сервис, в один навигируемый трейс. W3C Trace Context делает это с 55-байтным HTTP-заголовком traceparent, несущим 128-битный trace-id, который остаётся постоянным на каждом hop. Каждый сервис читает входящий заголовок, создаёт дочерний span и пишет новый заголовок перед собственными исходящими вызовами. Пропустишь любой hop — трейс расщепляется на разрозненные single-span orphan’ы — состояние, которое активно хуже отсутствия трейсинга, потому что дашборды сообщают о нормальной видимости, скрывая настоящее узкое место от инженера, которому оно нужно больше всего.
встречается в40
- Federation и lookahead: батчинг за пределами DataLoadermiddle
- Senior GraphQL API: scheduling-контракт, изоляция арендаторов, наблюдаемостьsenior
- Инвалидация, dirty-биты и containmiddle
- Слои композитора: продвижение, перекрытие и память GPUmiddle
- Observability в проде: LoAF, INP и полная поверхность атакиsenior
- Hidden classes, деревья переходов и расположение в памятиmiddle
- V8 в production: Isolates, сжатие указателей и реальные аварииsenior
- Что такое воркеры и зачем они нужныjunior
- Механика web workers: dedicated, shared и OffscreenCanvasmiddle
- Structured clone и transferablesmiddle
- SharedArrayBuffer, Atomics и cross-origin isolationsenior
- Пулы воркеров, Comlink и наблюдаемость в продакшенеsenior
- Восемь слоёв трассировки: от service worker до второй навигацииmiddle
- Пять канонических поломок: где производство стабильно ломаетсяsenior
- Метод трёх треков: чтение трасс и построение системы мониторингаsenior
- Лок и single-flight: ограничение параллельных rebuildmiddle
- Stale-while-revalidate и CDN request coalescingmiddle
- Детектирование stampede и дизайн TTL для продакшенаmiddle
- Метастабильный сбой, fencing-токены и production-постмортемыsenior
- Что такое отношение: таблицы, строки, ключи и ограниченияjunior
- Ограничения, ключи и типы данных Postgresmiddle
- JSONB, массивы и когда side table побеждаетmiddle
- Целостность схемы: deferral, версионирование и сбои в продакшнеsenior
- Где происходит data fetching — и почему это решает LCPjunior
- React Server Components и Suspense streamingmiddle
- Senior internals: RSC payload, слои кэша и production паденияsenior
- Конверт IPjunior
- Читаем IP-заголовокmiddle
- Что делает TLS и зачем он нуженjunior
- Расписание ключей, SNI, ALPN и расширенияsenior
- Защита 0-RTT, ECH, гибридный PQ и продакшн TLSsenior
- Двенадцать слоёв: один URL, семь действующих лицjunior
- Устойчивость: каскадные повторы, circuit breakers и error budgetsenior
- At-most-once, at-least-once, exactly-once: три контракта доставкиjunior
- Consumer-side dedup: самый дешёвый путь к exactly-once processingmiddle
- Exactly-once в production: impossibility-доказательство, гибридные паттерны и реальные инцидентыsenior
- Что такое OAuth и почему пароли — не ответjunior
- Authorization code flow с PKCEmiddle
- Sender-constrained токены: DPoP и mTLSsenior
- OAuth в production: audience атаки, observability и реальные провалыsenior