awesome-everything EN
↑ Обратно к восхождению

Наблюдаемость

Production-сбои propagation, span links и платформенный дизайн

Суть Баги propagation молчат: Uber, GitHub, Slack, Datadog — дашборды показывали трейсы, просто не те. Span-links решают fan-in и async follow-ups. Orphan rate и invalid-traceparent count — мета-слой, ловящий регрессии до пользователей.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 18 min

GitHub держал регрессию propagation целый квартал, когда 50% внутренних трейсов были orphan-спанами. Дашборды показывали трейсы всё это время. Никто не заметил, пока инженер не проверил orphan-span rate в рутинном ревью.

Реальные production-сбои propagation

Uber 2019: частичный rollout OTel привёл к тому, что 30% трейсов обрывались на границе между инструментированными и неинструментированными сервисами. Постмортем обязал добавить gate «ни один сервис не выходит в prod без W3C propagation», проверяемый в CI. Паттерн: инструментированные сервисы отдают идеальные спаны; неинструментированные отдают orphan-спаны; обе группы показывают разную глубину трейсов на дашбордах, но автоматических алертов на граничный сбой нет.

GitHub 2022: кастомная обёртка HTTP-клиента обходила хуки OTel и молча дропала traceparent у половины внутренних сервисов целый квартал — пока кто-то не заметил, что orphan-span rate вырос с 1% до 50%. Фикс — одна строка: обернуть клиент в OTel-aware версию. Урок: кастомные обёртки — самый частый пробел propagation в зрелых сервисах. Фикс всегда однострочный; найти его занимает квартал.

Slack 2023: tail-sampling Collector’ы упали по OOM и снесли pipeline трейсинга во время крупного инцидента — именно тогда, когда трейсинг был нужнее всего. Постмортем добавил лимиты num_traces и отдельный always-keep-тир для высокоприоритетных трейсов. Пробел мониторинга: health-метрики OTel Collector не были ни на одном SLO-дашборде.

Datadog 2024 (customer report): крупная Java-нагрузка использовала thread pool, который не переносил контекст через submitted tasks, поэтому 80% трейсов background-задач были orphan-спанами. Фикс: переключиться на executor с поддержкой CurrentTraceContext. Баг существовал месяцами; обнаружен в ходе квартального ревью orphan-rate.

Общий паттерн: баги propagation молчат. Дашборды продолжают показывать трейсы. Единственный механизм обнаружения — метрика orphan-span rate, и эта метрика должна быть на дашборде и желательно на алерте — OTel defaults её не выставляет автоматически.

Observability для самой propagation

Ключевые health-метрики propagation:

МетрикаНормаСигнал когда
orphan_span_rate по service.name<1% (только entry-points)Внутренний сервис >5% → регрессия propagation
invalid_traceparent_received count~0Любой sustained rate → сломанный upstream
trace_id_per_secondПропорционально RPS × sample_rateРезкий рост → свежие trace-id (propagation потеряна)
broken_parent_count<0.5%Спаны, чей parent-id не встречается ни в одном другом спане того же трейса
Здоровое состояниеПорогДействие по алерту
Orphan-спаны для внутренних сервисов<1%Page если >5% в течение 10 мин для конкретного сервиса
invalid_traceparent_received<0,01%Тикет если ненулевой rate держится >5 мин
broken_parent_count<0,5%Тикет если >2% в течение 10 мин

Модель родитель-потомок предполагает линейную причинность: A вызывает B, B вызывает C. Это ломается в трёх сценариях:

  1. Batch-обработка: consumer вытягивает 1 000 сообщений из Kafka и обрабатывает их в одном батче. Нет единственного осмысленного «родителя» — 1 000 входящих trace-контекстов питают один batch-спан.
  2. Fan-in: несколько параллельных подзадач сходятся в точке join. Каждая подзадача — потомок собственной ветви; у точки join несколько причинных участников.
  3. Async follow-ups: исходящий запрос завершается и возвращает ответ пользователю, но порождает follow-up, который выполняется спустя часы. Контекст исходного запроса закрыт; follow-up’ам нужна причинная связь без того, чтобы быть потомками «мёртвого» спана.

Span-links в OTel решают всё это: спан объявляет дополнительные ссылки на SpanContext, с которыми он причинно связан, но от которых не наследуется. Tracing-бэкенды визуализируют links как пунктирные линии рядом с деревом родитель-потомок.

Senior-паттерн: любой трейс длиннее 30 секунд или шире 100 спанов — кандидат на рефакторинг с span-links. Разбейте длинный workflow на sub-трейсы, каждый из которых умещается в окно принятия решения tail-sampler’а, и используйте links для сохранения причинной цепочки. Трейсы остаются небольшими, sampler’у хорошо, следственная связь сохраняется.

Long-running трейсы и проблема 30 минут

Tail-sampler’ы имеют окна принятия решения 30 с–5 мин. Batch-задача, работающая 30 минут, отдаёт спаны уже после закрытия окна; поздние спаны выглядят для sampler’а как orphan-спаны.

Два production-паттерна:

  1. Разбить работу: разделить длинные workflows на sub-трейсы, связанные span-links, каждый умещается в окно принятия решения. Чистая архитектура, корректная по построению.
  2. Поддержка поздних спанов бэкендом: Tempo, Honeycomb и Datadog поддерживают поздно прибывшие спаны до 24 ч после старта трейса. Для long-running трейсов пропустить tail-sampling; использовать head sampling на 100% для batch-нагрузок. Практический retrofit для legacy batch-задач.

Окно принятия решения — это рычаг, который нужно настраивать, когда batch-нагрузки ломают tail-sampling. Увеличение его вверх увеличивает RAM Collector’а; правильный ответ чаще всего — разбить работу.

Проследи
1/5

Обнаружен orphan rate 0,5% для внутреннего сервиса. Найдите первопричину.

1
Step 1 of 5
Шаг 1: orphan rate 0,5% — норма или сигнал?
2
Locked
Шаг 2: фильтр orphan-спанов по service.name. Какой паттерн?
3
Locked
Шаг 3: один конкретный сервис — источник. Что искать во входящем трафике?
4
Locked
Шаг 4: traceparent отсутствует в запросах от одного upstream client'а. Почему?
5
Locked
Шаг 5: долгосрочный фикс?
Найди ошибку

Диагностика сломанного трейса по выводу tracing-бэкенда

log
# Запрос: trace_id == "4bf92f3577b34da6a3ce929d0e0e4736"
# Результат: 7 спанов

#  сервис             span_id           parent_id           длительность   статус
1  api-gateway       1a2b3c4d5e6f7890  -                   18ms           OK
2  auth              7890abcdef123456  1a2b3c4d5e6f7890    14ms           OK
3  inventory         abcdef1234567890  1a2b3c4d5e6f7890    1200ms         OK
4  payment           fedcba0987654321  -                   80ms           OK    # ORPHAN
5  postgres-client   1111222233334444  fedcba0987654321    55ms           OK
6  email-job         5555666677778888  -                   240ms          OK    # ORPHAN
7  audit-log         9999aaaabbbbcccc  -                   12ms           OK    # ORPHAN

# Также отдельные orphan-трейсы с одним спаном:
# trace_id 9981a... сервис payment, 78ms
# trace_id ab32c... сервис email-job, 280ms
# trace_id ff8e1... сервис audit-log, 14ms

Трейс содержит 7 спанов, но 3 из них — orphan (нет parent_id), и существуют 3 отдельных трейса с одним спаном от тех же сервисов. Что происходит?

Спроектируй

Спроектируйте end-to-end trace propagation для новой платформы с 30 микросервисами, браузерным frontend, Kafka backbone, service mesh и tier tail-sampling collector.

  • Polyglot: 12 сервисов Node.js, 10 Java, 5 Go, 3 Python.
  • Браузерный frontend (React) делает fetch-вызовы к API gateway.
  • Kafka используется для async-обмена между 8 сервисами.
  • Service mesh: Linkerd (Linux) для east-west HTTP и gRPC.
  • Sampling: 100% ошибок, 100% медленных (>2 с), 1% baseline.
  • On-call должен видеть любой пользовательский запрос как единый трейс в течение 30 с после завершения.
Пороги health propagation
Здоровый orphan-span rate (внутренние сервисы)
≤1% от всех спанов
Здоровый invalid_traceparent rate
≤0,01%
Здоровый broken-parent rate
≤0,5%
Порог алерта: orphan rate внутреннего сервиса
>5% в течение 10 мин
GitHub 2022: orphan rate в момент обнаружения регрессии
50% (от baseline 1%)
Время обнаружения регрессии GitHub без алертинга
>1 квартала
Викторина

Batch-процессор вытягивает 1 000 сообщений из Kafka и обрабатывает их в одной транзакции. Инженер моделирует это как один родительский спан с 1 000 дочерних спанов, по одному на сообщение. После деплоя tail-sampling Collector падает по OOM. Каков архитектурный фикс?

Викторина

Production-команда добавляет алертинг на orphan-span rate. Алерт срабатывает для 'email-job' на уровне 6% (baseline 0,5%). Каков первый диагностический шаг?

Вспомните перед уходом
  1. 01
    Объясните, зачем существуют span-links, и когда senior-инженер выбирает их вместо отношений родитель-потомок.
  2. 02
    Опишите три health-метрики propagation, которые должен мониторить каждый production tracing-деплой, и пороги алертов.
  3. 03
    Опишите 8-уровневый платформенный дизайн end-to-end propagation для polyglot-системы с 30 сервисами, Kafka, service mesh и tail sampling.
Итог

Production-сбои propagation молчат: Uber (30% сломанных трейсов месяцами), GitHub (50% orphan rate целый квартал), Slack (Collector OOM во время инцидента) и клиенты Datadog (80% orphan-спанов у background-задач) — все сбоили именно так. Общий паттерн: дашборды показывали трейсы, просто не связанные, и ни одна метрика не алертила на разрыв. Фикс — наблюдать health propagation через собственные RED-эквивалентные метрики: orphan-span rate по сервису, invalid-traceparent count, broken-parent rate — и алертить по ним. Span-links решают случаи, когда дерево родитель-потомок не работает: batch fan-in, async follow-ups, workflows шире, чем окно принятия решения. Long-running трейсы необходимо разбивать на sub-трейсы, связанные span-links, умещающиеся в окно Collector’а. Propagation — невидимый фундамент, от которого зависит каждая другая observability-фича; воспринимайте её health как первоклассную production-метрику.

Связанные уроки
встречается в40
Продолжить восхождение ↑Trace propagation: тест с множественным выбором
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.