Программа курса

Модуль 06 / Урок 27 из 27

Финальный проект

Теория и практика

Собираем курс в одно приложение: трёхсервисная система с полным циклом трассировки — от SDK до прод-конфигурации с tail-сэмплированием и SPM.

Архитектура проекта

shop-web ──► orders ──► payments
    │            │
    │            └──► PostgreSQL
    └──► Redis (сессии)
         │
   Kafka (orders.events) ──► notifier (консюмер)
         │
   всё выше: OTel SDK ─► OTel Collector ─► Jaeger (Elasticsearch)

Чек-лист реализации

  1. Инструментирование: автоинструментирование HTTP/DB/Kafka в трёх сервисах; ручной спан бизнес-операции place_order с атрибутами order.id, tenant, total;
  2. Контекст: трейс сшит shop-web → orders → payments и через Kafka в notifier (publish → process); baggage с tenant.id виден в notifier;
  3. Логи: trace_id/span_id в каждом лог-порядке; переход «лог → трейс» работает вручную;
  4. Collector: memory_limiter + filter (healthchecks) + batch; атрибуты db.statement удаляются;
  5. Сэмплирование: head-based parentbased_traceidratio 10% (dev-день 1), затем tail_sampling: errors 100%, latency > 500мс 100%, base 5% (день 2) — сравните объёмы;
  6. Хранилище: Elasticsearch + rollover по 24ч + lookback 7 дней + крон-очистка с алертом;
  7. Наблюдаемость: дашборд Collector/Jaeger (приток, потери, латентность) + SPM по операциям; алерты из урока 5.4;
  8. Аварии: воспроизведите N+1, ретраи внешнего вызова и «пустой промежуток» из модуля 4 — найдите каждый по трейсам за ≤ 5 минут.

Критерии «зачтено»

КритерийПроверка
Сквозной трейс 4 сервисоводин trace ID в waterfall от shop-web до notifier
Трейсы не ломают бизнесостановлен Jaeger под нагрузкой: RPS и латентность не деградируют
Ошибки гарантированно виднысоздана ошибка в 3% запросов — все попали в хранилище (tail)
Объём под контролемзамер ГБ/сутки соответствует расчёту ±30%
Инцидент-минутапо поиску находите «медленный checkout» и называете сегмент-виновник

Что дальше

  • Документация: opentelemetry.io (SDK, Collector, семантические конвенции), jaegertracing.io (архитектура, хранилища, API);
  • Книга: «Distributed Systems Observability» (C. Sridharan, бесплатно) — короткая и лучшая вводная по философии;
  • OpenTelemetry в Kubernetes: Operator, автоинъекция instrumentation, k8sattributes;
  • Профилирование: четвёртый столб наблюдаемости — continuous profiling (Pyroscope/Parca) рядом с трейсом;
  • eBPF-трассировка (Grafana Beyla и аналоги): трейсы без изменения кода — растущее направление.
Самопроверка курса (развернуть)

1. Что передаётся в traceparent? — версия, trace-id, parent span-id, флаги.

2. Почему parentbased — дефолт сэмплера? — сохраняет целостность трейса: решение одно, у корня.

3. Зачем OTel Collector, если Jaeger принимает OTLP? — батчинг, фильтры, PII, tail-сэмплинг, маршрутизация, развязка бэкенда.

4. Головная боль tail-сэмплинга? — память под ожидание трейса + LB по trace ID между репликами.

5. N+1 в трейсе выглядит как… — серия одинаковых последовательных спанов БД.

6. Как найти трейс по логу? — trace_id из лога в поле Trace ID UI.

7. messaging: спаны producer/process + контекст в свойствах сообщения.

8. Exemplar — что связывает? — метрику Prometheus с примером трейса.

9. Почему in-memory нельзя в проде? — данные исчезают при рестарте, объём = память процесса.

10. Первое при «трейсы пропали»? — метрики потерь: dropped/failed spans на пути SDK→Collector→Jaeger.