Проблема распределённой диагностики выглядит убедительно: в двух журналах найден один trace ID, рядом стоят одинаковые timestamps, а один span заметно длиннее остальных. Из этого легко сделать вывод, что найден виновник. Цена ошибки — неверный rollback или оптимизация не того участка. В распределённом маршруте идентификатор говорит «эти записи относятся к одному контексту», но не говорит «эта запись вызвала задержку». Между двумя утверждениями есть несколько проверок.
Механизм нужно разделить на три слоя. Log содержит сообщение и локальное состояние процесса. Span описывает операцию и её границы во времени. Metric агрегирует множество наблюдений и теряет часть контекста. Смешать эти формы — значит использовать ответ одного инструмента для вопроса другого. Хороший разбор сначала проверяет, что записи относятся к одному trace, затем — что parent/child связи и интервалы совместимы, и только после этого формулирует ограниченный вывод.
Что гарантирует идентификатор
W3C Trace Context стандартизирует HTTP-заголовок traceparent и формат идентификаторов. Это полезный транспортный контракт: сервис может продолжить контекст, а оператор — искать его в нескольких компонентах. Но стандарт не требует, чтобы все внутренние работы были представлены span-ами. Библиотека может не создать span для очереди, фона или локального cache. Отсутствие записи значит «в этом источнике её нет», а не «операции не было».
У trace есть и временная граница. Parent span может завершиться до того, как дочерняя работа закончилась, если связь отражает асинхронную передачу. Два span-а в одном trace могут быть соседями в маршруте, но не причиной друг друга. Поэтому при чтении надо видеть имя операции, service.name, parentSpanId, start и end, а не только цветную линию в интерфейсе.
| Источник | Сильная сторона | Проверить рядом | Не заключать автоматически |
|---|---|---|---|
| Log | локальное сообщение и состояние | время, источник, schema, request-id | что сообщение объясняет весь маршрут |
| Span | граница операции и длительность | parent, kind, status, attributes | что самый длинный span вызвал всё |
| Metric | частота и распределение | окно, population, labels | что агрегат указывает на один запрос |
| Trace ID | поиск общего контекста | пропагация и sampling | что цепочка полна и причинна |
Локальный граф связей
Ниже функция строит минимальное представление родительских связей по массиву span-ов. Она отмечает root, найденного parent и missing parent. Это предметный пример: результат помогает увидеть разрыв контекста в конкретной цепочке. Он не рисует красивый trace и не назначает виновника. Входы — именно те поля, которые должны быть сохранены при экспорте данных.
import { linkTraceRecords } from './upgrade-2027-01.mjs';
const records = [
{ traceId: 't-7', spanId: 's-gateway', service: 'gateway', parentSpanId: '', durationMs: 22 },
{ traceId: 't-7', spanId: 's-api', service: 'api', parentSpanId: 's-gateway', durationMs: 81 },
{ traceId: 't-7', spanId: 's-db', service: 'db', parentSpanId: 's-missing', durationMs: 4 },
];
console.log(linkTraceRecords(records));
// gateway: root; api: present; db: missingОжидаемый результат показывает разрыв у db. Это уже полезная находка: прежде чем говорить о задержке, надо понять, откуда взялся span без parent. Возможны потеря span, неправильное поле или независимая работа, ошибочно попавшая в trace. Ни одна из версий не следует из массива сама; функция лишь не даёт скрыть дырку за сплошной линией.
Время, статус и семантика
Длительность span сравнивают внутри одной временной шкалы и одной операции. Если gateway ждёт upstream 800 мс, это не означает, что upstream потратил 800 мс на вычисление: туда может входить соединение, очередь, retry и чтение ответа. В attributes нужны хотя бы тип операции, результат и причина окончания. Для HTTP это могут быть status_code, method и route; для базы — операция и имя зависимости без чувствительных параметров.
Log полезен, когда в нём есть структурированные поля, а не только строка сообщения. RFC 5424 отделяет header, structured data и message, что хорошо совпадает с задачей корреляции. Но формат журнала не гарантирует доставку: transport может отбросить или обрезать запись. Поэтому «в журнале не найдено» — это результат проверки качества источника, а не доказательство отсутствия события.
Действия по порядку
- Проверить, что trace-id и span-id имеют ожидаемый формат и не меняются при переходе между сервисами.
- Построить parent/child граф и отметить root, missing parent, duplicate span-id и операции без service.name.
- Сверить интервалы start/end с локальными timestamps; отдельно учесть async, retry и очередь.
- Сопоставить span с application log по span-id или request-id, а metric использовать только как фон для population.
- Сформулировать вывод в узкой форме: «этот участок наблюдался дольше» или «связь потеряна», не «он был причиной всего отказа».
Ограничения и следующий шаг
Sampling, tail-based filtering и ошибки clock skew меняют картину. Trace может не включать retry или consumer, а log collector — получить записи в другом порядке. Данные с персональными параметрами нельзя бездумно передавать в общий контур наблюдаемости. Наконец, даже полная trace-цепочка описывает наблюдаемую последовательность, но не контрфактический вопрос: что произошло бы без конкретного вызова.
Следующий шаг — выбрать один критичный маршрут и зафиксировать контракт полей для gateway, application и dependency span. Добавьте проверку на missing parent и отдельную метрику пропущенного контекста. После этого повторите разбор: качество решения растёт не от количества экранов, а от уменьшения числа неразличимых объяснений.
Проверяемые источники
- Trace Context — W3C Recommendation — версия и дата: Recommendation, 23 November 2021. Применение: Формат traceparent и правила передачи контекста между HTTP-сервисами. Граница: Спецификация не определяет внутреннюю модель span, sampling, очередь и причинность.
- RFC 5424: The Syslog Protocol — версия и дата: Standards Track, March 2009, DOI 10.17487/RFC5424. Применение: Структурированные поля и границы syslog-сообщения используются как пример дисциплины логирования. Граница: RFC не гарантирует доставку конкретного журнала и не описывает trace-связи приложения.
- RFC 9110: HTTP Semantics — версия и дата: Internet Standard, June 2022, DOI 10.17487/RFC9110. Применение: Семантика HTTP-операции и статуса отделена от длительности внутренних работ. Граница: HTTP Semantics не описывает конкретный backend, tracer или способ агрегации.