Всем привет! Сегодня хочется поговорить про механизм распространения контекста трассировки в OpenTelemetry. Разберем, как он работает, и посмотрим простой пример на Go. Всё — коротко и по делу!
Меня зовут Носорев Константин, я backend-разработчик в Яндекс Пей, автор канала «Константин про IT» и просто любознательный инженер.
OpenTelemetry уже давно стал стандартом для построения системы наблюдаемости (observability) в микросервисной архитектуре. Начнем с небольшого ликбеза, чтобы проще воспринимать материал.
Трассировка строится вокруг двух базовых понятий: trace и span.
-
Trace — это путь, который проходит запрос.
-
Span — это отдельный шаг в обработке запроса.
Один trace начинается с корневого span’а, который порождает дочерние span’ы. Все они образуют дерево вызовов, которое можно визуализировать в системах наблюдаемости.
У каждого trace и span есть соответствующие идентификаторы — trace_id и span_id. Когда мы создаем первый span, библиотека OpenTelemetry (далее будем говорить просто otel) генерирует эти идентификаторы, сохраняет их в памяти и затем экспортирует во внешнюю систему. Для понимания принципа работы нам достаточно знать, что вся информация о трассировках каким-то образом доходит до системы мониторинга.
Каждый новый span привязан к trace’у и, при наличии, к родительскому span’у — так формируется полная цепочка.
Когда мы остаемся в рамках одного приложения или потока, сохранить эту цепочку довольно просто. Но сила трассировки именно в том, что она позволяет связать действия, происходящие между сервисами, в единую историю.
Возникает вопрос: как otel передает идентификаторы между сервисами?
Для этого используется механизм Propagation. Он позволяет передавать контекст трассировки с помощью двух компонентов:
-
traceparent— обязательный заголовок, содержащий версию протокола,trace_idиspan_idродителя; -
tracestate— дополнительная информация, специфичная для вендора.
В случае HTTP-запросов эти значения передаются в заголовках. В большинстве случаев вам не нужно делать это вручную — otel предоставляет готовые инструменты для встраивания заголовков в HTTP-запросы. Рекомендую изучить библиотеку otel для вашего языка.
Теперь рассмотрим более интересный случай — передачу контекста в фоновые процессы, например, при реализации асинхронных API. В этом случае контекст нужно передавать через внешние системы: очереди сообщений, БД и т.д.
Пример: передача контекста через БД
Представим, что у нас есть сервис с двумя обработчиками:
-
POST-ручка сохраняет задачу в БД и возвращает
task_id; -
GET-ручка по
task_idвозвращает статус задачи; -
Плюс есть фоновый воркер, который обрабатывает задачи и обновляет статус в БД.
Мы хотим получить сквозной trace, в котором будет видно всё: создание задачи, её обработку и обновление.
Для этого нужно передать trace-контекст от POST-запроса в воркер. Сохраним его в БД вместе с задачей. Otel предоставляет для этого TextMapPropagator — механизм, позволяющий сериализовать контекст в словарь (map[string]string), который можно, например, сохранить в поле jsonb в PostgreSQL.
Такой объект будем называть traceContext.
Код на Go:
package trace import ( "context" "go.opentelemetry.io/otel/propagation" ) type TraceContext struct { Trace propagation.MapCarrier `json:"trace"` } func Inject(ctx context.Context) TraceContext{ md := propagation.MapCarrier{} traceContext := propagation.TraceContext{} traceContext.Inject(ctx, md) return TraceContext{Trace: md} } func Extract(ctx context.Context, tc TraceContext) context.Context { traceContext := propagation.TraceContext{} ctx = traceContext.Extract(ctx, tc.Trace) return ctx }
Мы опустили часть с сохранением traceContext в БД — оставим это в качестве домашнего задания 😉
На стороне воркера всё просто: извлекаем traceContext из БД, восстанавливаем контекст, создаем новый span, и он автоматически становится частью исходного trace’а.
Резюме
Сегодня мы познакомились с механизмом propagation в OpenTelemetry и рассмотрели практический пример на Go. Этот механизм позволяет обеспечить связность трассировки даже при передаче контекста через внешние хранилища.
На этом всё! Если вам зашёл такой формат — ставьте лайк, делитесь мнением в комментариях и подписывайтесь на мой телеграм-канал Константин про IT. Если будет интерес, продолжу рассказывать про полезные инструменты разработки — коротко и по делу!
ссылка на оригинал статьи https://habr.com/ru/articles/901156/
Добавить комментарий