API-сервис принимает запрос, публикует сообщение в Kafka и возвращает ответ. Обработчик получает запись позже, обращается к следующему сервису или базе данных, а связанная с запросом операция выполняется дольше ожидаемого. При этом показатели каждого компонента по отдельности могут оставаться в пределах нормы.
Условная цепочка выглядит так:
HTTP-запрос → сервис-источник → Kafka-топик → обработчик → следующий сервис или БД
После публикации сообщения исходный HTTP-запрос уже завершился, а обработка продолжится в другом процессе или на другом экземпляре приложения. Без передачи диагностического контекста трейс сервиса-источника закончится на публикации, а работа обработчика отобразится как отдельный трейс.
Логи можно попытаться сопоставить по времени, но при параллельной и пакетной обработке, а также повторных попытках такая связь становится ненадёжной. Идентификатор сообщения или бизнес-операции помогает искать события, однако сам по себе не описывает отношения между spans.
Чтобы сохранить связь, producer добавляет контекст трассировки в метаданные сообщения - в Kafka для этого можно использовать record headers. Consumer извлекает контекст во время обработки, после чего с ним можно связать spans обработчика, последующие обращения к сервисам и записи в логах.
Связь между producer- и consumer-span не всегда выглядит как прямая parent-child цепочка. Например, при пакетном чтении consumer получает сообщения с разными контекстами. В таких случаях причинные связи можно сохранить через Span Links.
На курсе Observability этот механизм рассматривается как часть проектирования наблюдаемости системы. В программе связаны Observability асинхронных взаимодействий, работа с OpenTelemetry, корреляция трейсов, логов и метрик, а также поиск высокой latency и ошибок по трейсам. Такой подход помогает исследовать путь операции через несколько компонентов, а не ограничиваться состоянием одного сервиса.
При этом даже связный трейс не гарантирует готового ответа о первопричине. Часть пути может отсутствовать из-за семплирования или неполного инструментирования, а продолжительный span показывает место задержки, но не обязательно объясняет, почему она возникла. Зато команда получает данные, по которым можно последовательно сужать область поиска.
Как это устроено у вас: контекст передаётся автоматически, добавляется в Kafka headers вручную или трейс обрывается после публикации сообщения?
