Чтобы перестать "гадать" в продакшене, выстройте наблюдаемость как связку логов, метрик и трейсов: структурированные события объясняют контекст, метрики показывают масштаб и динамику, а distributed tracing раскладывает путь запроса по сервисам. Дальше закрепите это в алертах и рутине расследований, используя одну observability платформа для корреляции данных.
Краткая карта наблюдаемости: что важно в продакшене
- Единый корреляционный ключ: trace_id/span_id + request_id в логах, метках метрик и заголовках запросов.
- Мониторинг логов и метрик строится от пользовательских SLI: ошибки, латентность, насыщение ресурсов, пропускная способность.
- Трейсы включайте на входе в систему и на всех сетевых границах; без этого "дыры" в цепочке неизбежны.
- Sampling и ограничение кардинальности меток - главный рычаг контроля стоимости и overhead.
- Алерты по симптомам (SLO/SLI), диагностика - по деталям (логи/трейсы/профили), иначе будет шум.
- Инцидент-рутина: от симптома → сегментации → локализации сервиса → поиска изменения → подтверждения корня.
Что логировать и как структурировать события для быстрых выводов
Кому подходит: командам с микросервисами и очередями, API с несколькими зависимостями, системам с частыми релизами, где APM мониторинг без логов не отвечает на вопрос "почему".
Когда НЕ стоит делать подробно: в системах с высокими требованиями к приватности/регуляторике без готовой политики редактирования (redaction), и в горячих путях, где синхронный вывод логов заметно бьёт по латентности - там начинайте с метрик и выборочных событий.
Минимальный формат события (схема, которую реально искать)
- timestamp (в UTC), level, service, env, version.
- message - коротко, без "романов".
- trace_id, span_id, request_id - для склейки с distributed tracing и запросами.
- event_name (например, payment.authorize) и outcome (success/fail/timeout).
- http.method, http.route (шаблон), http.status_code - без сырого URL с параметрами.
- user_id_hash/tenant_id (если есть мультиарендность) - только в безопасном виде.
Проблема → действие → пример
-
Проблема: невозможно отличить бизнес-ошибку от падения зависимости.
Действие: разделите ошибки на классы (validation/timeout/dependency/auth) и логируйте error.kind и dependency.name.
Пример: при таймауте в БД пишите error.kind=timeout, dependency.name=postgres, retry.count. -
Проблема: логи "шумят" и дорого хранятся.
Действие: оставьте INFO только для ключевых бизнес-событий и границ, DEBUG - под флаг/выборочно по trace_id.
Пример: включайте расширенные логи для 1% запросов или для проблемного клиента по tenant_id.
Выбор метрик: SLI/SLO, латентность, пропускная способность и ошибки
Перед тем как настраивать мониторинг логов и метрик, подготовьте базовые условия: единые имена сервисов, теги окружения (prod/stage), доступ к метрикам на уровне инфраструктуры и приложений, а также договорённость, где живут SLO (в репозитории/в observability платформа) и кто их утверждает.
Что понадобится (минимум, без которого будет "разрыв картины")
- Инструменты: метрики приложения (Prometheus/OpenTelemetry metrics/встроенные агенты APM), сбор инфраструктурных метрик, централизованный лог-стор и трейс-бэкенд.
- Доступы: просмотр дашбордов, чтение логов, просмотр трейсов, доступ к конфигам алертов; возможность добавить/изменить теги и поля логов.
- Стандарты именования: единый service.name, deployment.environment, service.version; одинаковые названия роутов/операций.
- Ограничения кардинальности: правила, какие метки запрещены (user_id, order_id, email и т. п.).
Практический набор SLI для старта
- Ошибки: доля 5xx, доля отказов бизнес-операции (например, payment.authorize.fail).
- Латентность: p95/p99 по http.route и по бизнес-операции; отдельно - внешние зависимости (БД/кэш/внешние API).
- Пропускная способность: RPS/ops/sec по роутам и очередям; скорость потребления/публикации сообщений.
- Насыщение: CPU throttling, memory pressure/GC, пул соединений, очередь запросов, thread/worker pool saturation.
Трассировка в распределённых системах: где открывать span и какие теги нужны
-
Определите границы трассировки. Трейс должен начинаться на входном edge (API gateway/ingress) или в consumer очереди и продолжаться через все сетевые вызовы. Так вы получите непрерывную картину вместо "кусочков" APM мониторинг.
- HTTP: start span на сервере при приёме запроса и propagate context дальше.
- MQ: start span при обработке сообщения; при публикации - span producer.
- Включите контекст и пропагацию. Настройте передачу trace context в заголовках HTTP и метаданных сообщений (W3C Trace Context или формат вашего стека). Проверьте, что trace_id попадает и в логи.
-
Откройте спаны на сетевых вызовах и критичных участках. Оборачивайте клиентские вызовы БД/кэша/HTTP/GRPC, а также очереди и файловые/облачные хранилища. Не пытайтесь "спанить" каждый метод - начинайте с границ и горячих точек.
- Отдельные спаны: db, http.client, rpc, messaging.
- Внутри сервиса: спаны вокруг сериализации, тяжёлых вычислений, вызовов внешних SDK.
- Добавьте обязательные атрибуты (теги) для поиска. Минимум: service.name, deployment.environment, service.version, http.route (шаблон), http.method, http.status_code, error.type/error.message (без секретов), dependency.name. Эти поля должны совпадать по смыслу с логами и метриками.
- Свяжите логи и трейсы. В каждый лог из контекста запроса добавляйте trace_id/span_id. В трейсах добавляйте ссылки на ключевые события (например, order_id в безопасном виде или внутренний correlation key).
- Настройте sampling осознанно. Для высоких нагрузок используйте head-based sampling (процент) + tail-based (по ошибкам/медленным запросам), чтобы сохранять проблемные трейсы. Зафиксируйте правила, чтобы команда понимала, почему "трейса нет".
Быстрый режим
- Сделайте пропагацию trace context везде (HTTP + очереди) и добавьте trace_id/span_id в логи.
- Оберните спанами все внешние зависимости (БД/кэш/HTTP) и входные обработчики.
- Стандартизируйте теги: service.name, env, version, http.route, dependency.name.
- Включите sampling: сохраняйте 100% ошибок и медленных запросов, остальное - процентом.
Инструментация и сбор данных: библиотеки, sampling и overhead в реале
Для практичной наблюдаемости выбирайте один путь инструментации: либо OpenTelemetry SDK/auto-instrumentation, либо агент конкретной APM/observability платформа. Смешивание подходов допустимо, но только если вы понимаете, кто создаёт спаны/метрики и не дублируете данные.
Проверка результата (чек-лист перед включением на весь прод)
- В логах по одному запросу видны trace_id и span_id, а по trace_id находится соответствующий трейс.
- В трейсе нет "провалов" на сетевых границах (клиентский и серверный спаны связаны).
- Метрики по http.route не раздуваются из-за кардинальности (нет меток со значениями типа user_id, order_id, полный URL).
- Sampling действительно сохраняет проблемные случаи: есть трейсы по 5xx, таймаутам и медленным запросам.
- Overhead контролируем: нет всплеска p95/p99 после включения, нет деградации CPU/памяти от экспортёров.
- Буферы/очереди экспортёра не переполняются при пиках (данные не "теряются молча").
- Тайм-ауты и ретраи экспортёра настроены так, чтобы не блокировать обработку запросов.
- Политика безопасности соблюдена: в логах/тегах нет секретов, токенов, персональных данных.
- Версии сервисов размечены (service.version), чтобы находить регресс после релиза.
Алертинг и эскалации: как настраивать пороги, чтобы уменьшить шум

- Алертите на всё подряд (CPU, диски, любые 5xx) без связи с пользовательским влиянием - начните с SLI/SLO и симптомов деградации.
- Пороги без окна и устойчивости: один всплеск → алерт. Добавьте окно оценки и условие "держится N минут" (по возможностям вашей системы алертинга).
- Одинаковые пороги для всех сервисов - разные нагрузки и профили трафика требуют разных порогов и разных SLO.
- Нет маршрутизации по владению: алерт падает "в общий чат". Настройте, кто дежурит за сервис/компонент, и укажите runbook-ссылку.
- Нет разделения на симптом/причину: алерт на "БД медленная" и на "ошибки API" одновременно без приоритета. Симптом - основной, причины - диагностические.
- Не учитываются деплои: алерты взрываются на раскатке. Введите корректное подавление/маркировку релизов и наблюдение за регрессом.
- Слишком детальная разбивка (например, по customer_id) - кардинальность и шквал алертов. Держите агрегацию на уровне route/операции/сервиса.
- Нет политики эскалаций: если не подтверждено за разумное время - кому и как повышаем приоритет, куда писать/звонить.
Пошаговое расследование инцидента: от симптома до корневой причины
Выберите маршрут расследования по тому, что у вас уже есть (метрики, логи, трейсы) и как быстро нужно локализовать проблему. Ниже - рабочие альтернативы, которые комбинируются в одной observability платформа.
Вариант 1: от SLO/SLI к сервису-источнику (когда есть качественные метрики)
- Уместно, если вы доверяете SLI (ошибки/латентность/трафик) и видите, что "сломалось" в масштабе.
- Ход: алерт по SLI → сегментация по route/региону/версии → переход к dependency метрикам → подтверждение в трейсе → точный лог по trace_id.
Вариант 2: от трейса к зависимости (когда деградация точечная и "прыгающая")
- Уместно при росте p99 без явных 5xx, при таймаутах, "залипаниях" на отдельных клиентах.
- Ход: найти медленные трейсы → увидеть самый длинный span → проверить теги dependency.name и error.type → открыть логи по trace_id → сопоставить с релизом/конфигом.
Вариант 3: от логов к воспроизведению (когда ошибка чётко проявляется сообщением/кодом)
- Уместно, если в логах есть стабильный маркер (error.kind, исключение, код бизнес-ошибки) и хорошие поля корреляции.
- Ход: фильтр по marker → группировка по version/route/dependency → взять один trace_id → пройтись по цепочке span'ов → сформулировать минимальный сценарий воспроизведения.
Решения для типичных проблем наблюдаемости
Почему трейс не находится по trace_id из логов?
Чаще всего не совпадает формат/пропагация контекста или трейс отсэмплирован. Проверьте, что trace_id пишется из активного span-контекста и что правила sampling сохраняют ошибки/медленные запросы.
Как быстро отличить регресс после релиза от внешней деградации зависимости?
Сегментируйте метрики и ошибки по service.version и сравните соседние версии. Если проблема привязана к одной версии - идите в diff конфигов/кода; если ко всем версиям - смотрите dependency метрики и трейсы на внешние вызовы.
Что делать, если мониторинг логов и метрик раздувается по стоимости?
Уберите высококардинальные метки и поля, ограничьте INFO-события до бизнес-границ, включите sampling для трейсов. Для логов применяйте редактирование чувствительных данных и выносите детали в DEBUG только по флагу.
Как настроить distributed tracing для очередей, чтобы не терялась связность?
Передавайте trace context в метаданных сообщения при публикации и создавайте span producer/consumer. В consumer начинайте новый span как дочерний к контексту сообщения и логируйте trace_id для каждого обработчика.
Почему APM мониторинг показывает "медленно", но непонятно где?

Обычно не хватает спанов на внешних зависимостях или отсутствуют корректные теги (dependency.name, http.route). Добавьте спаны на сетевые вызовы и убедитесь, что в трейсе видно время на БД/HTTP/кэше отдельными участками.
Как уменьшить шум от алертов, не потеряв реальные инциденты?
Оставьте алерты по симптомам (SLI/SLO) и добавьте устойчивость по времени, а причины перенесите в дашборды диагностики. Введите маршрутизацию по владению и runbook рядом с алертом, чтобы сокращать время реакции.



