Распределённая трассировка на сервере: OpenTelemetry на практике
OpenTelemetry связывает запросы между сервисами в одну трассу, но сама установка SDK не покажет, где теряется время. Разбираем три способа инструментирования Python-сервиса, их цену и минимальную настройку для передачи трасс в Collector.

Если запрос проходит через API, очередь и базу данных, обычный лог часто не объясняет, где именно он задержался. OpenTelemetry связывает операции в распределённую трассу: вы видите путь запроса и длительность каждого участка. Ниже — практические варианты для Python-сервиса и минимальный пример ручной инструментации на OpenTelemetry Python 1.27.0.
Что именно вы измеряете
Трасса — это дерево операций, связанных общим контекстом. Входящий HTTP-запрос становится родительским span, а вызовы базы, внешнего API или очереди — дочерними. Если сервис передаёт контекст дальше, трасса продолжается через границу между сервисами.
OpenTelemetry — не хранилище и не интерфейс для просмотра. SDK создаёт и отправляет телеметрию, Collector принимает её и направляет дальше, а backend хранит трассы и позволяет их искать. Это могут быть отдельные компоненты или управляемый сервис; в любом случае путь данных стоит проверить целиком.
Трассировка полезна не количеством span, а ответом на вопрос: какой участок запроса съел время и какой компонент за него отвечает.
Span1 — именованный интервал работы с началом, концом, атрибутами и статусом. Ручной span нужен для важной бизнес-операции, а не для каждой строки кода.
Три способа подключить трассировку
Варианты не взаимоисключающие: обычно начинают с автоматической инструментации, а затем добавляют ручные span там, где встроенных границ недостаточно.
| Подход | Что получаете | Цена и риск |
|---|---|---|
| Автоматическая инструментация | Span для поддерживаемых библиотек: например, HTTP-клиента или веб-фреймворка | Быстрый старт, но детализация зависит от конкретной библиотеки и её версии; лишние span могут увеличить объём данных |
| Ручные span | Видимость ключевых этапов собственной логики | Нужно сопровождать код и следить, чтобы контекст передавался при асинхронной работе |
| Инструментация через OpenTelemetry Collector | Отдельная точка приёма, обработки и отправки телеметрии | Появляется инфраструктурный компонент, который нужно развернуть, мониторить и обновлять |
Для первого запуска в одном Python-сервисе настройте SDK и отправку в Collector. Затем подключите автоматическую инструментацию используемых библиотек по документации именно к их версиям. Ручные span добавляйте для бизнес-этапов, которые иначе остаются одним непрозрачным интервалом.
Минимальная настройка ручного span
Пример рассчитан на OpenTelemetry Python 1.27.0: версии пакетов API, SDK и OTLP-экспортера должны совпадать. Он показывает настройку tracer provider и отправку по OTLP/gRPC. Collector должен принимать OTLP на локальном порту 4317; адрес и протокол измените, если ваша схема развёртывания отличается.
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
resource = Resource.create({"service.name": "orders-api"})
provider = TracerProvider(resource=resource)
exporter = OTLPSpanExporter(endpoint="http://localhost:4317", insecure=True)
provider.add_span_processor(BatchSpanProcessor(exporter))
trace.set_tracer_provider(provider)
tracer = trace.get_tracer("orders-api")
with tracer.start_as_current_span("validate-order") as span:
span.set_attribute("order.validation", "started")
# Здесь выполняется проверка заказа
В рабочем приложении инициализируйте provider один раз при старте, а завершайте его штатно при остановке процесса, чтобы SDK успел отправить накопленные данные. Не добавляйте в атрибуты токены, пароли, персональные данные и содержимое запросов. Атрибуты вроде идентификатора заказа тоже оцените с точки зрения приватности и кардинальности.
Этот фрагмент создаёт ручной span, но не превращает автоматически все HTTP-запросы в трассы и не добавляет инструментирование базы данных. Для этого подключите соответствующие инструменты из официальной документации OpenTelemetry Python. Не создавайте второй tracer provider, если фреймворк или агент уже настроил свой: иначе часть данных может идти не тем путём, который вы ожидаете.
Как выбрать подход и проверить результат
- Начните с границ. Зафиксируйте входящий запрос и исходящие вызовы, которые важны для расследования задержек. Проверка: в тестовой трассе видны ожидаемые операции, а не только один корневой span.
- Добавьте ручные span для собственной логики. Разделите крупную операцию на осмысленные этапы, например проверку и запись заказа. Проверка: этапы имеют правильного родителя и отражают фактический порядок работы.
- Проверьте передачу контекста между сервисами. Отправьте запрос через реальную границу сервисов. Проверка: в интерфейсе backend обе части запроса находятся в одной трассе, а не в двух несвязанных.
- Проверьте доставку. Убедитесь, что приложение отправляет данные в Collector, а Collector — в backend. Проверка: свежая трасса находится поиском по имени сервиса и времени теста.
- Ограничьте объём. Решите, какие запросы семплировать и какие атрибуты допустимы. Проверка: сравните объём телеметрии и нагрузку до и после включения трассировки на тестовом контуре.
Что обычно ломается
- Трасс в backend нет. Проверьте адрес и протокол экспорта, доступность Collector и его входной OTLP-приёмник. Настройки приложения и Collector должны совпадать.
- Видна только часть пути. Контекст мог не передаться через HTTP-вызов, очередь или фоновую задачу. Проверьте поддержку конкретной библиотеки и способ запуска фоновой работы.
- Слишком много данных. Сократите долю сохраняемых запросов и уберите высококардинальные атрибуты, например уникальные значения, которые почти не повторяются.
- В трассах появились секреты. Пересмотрите автоматический сбор атрибутов и собственные span. Не отправляйте заголовки авторизации, тела запросов и другие чувствительные данные.
Где подход ломается
Трассировка не гарантирует, что вы увидите каждый запрос: семплирование отбрасывает часть данных, а сбой доставки может оставить пробелы. Она также не заменяет метрики и логи: метрика показывает частоту ошибки или задержку на уровне сервиса, трасса помогает разбирать отдельный путь запроса, лог — детали события.
Асинхронная обработка требует отдельной проверки: трасса HTTP-запроса не обязательно автоматически продолжится в задаче очереди. Контекст нужно корректно передавать через используемый транспорт, а поведение инструмента — сверять с документацией его версии. Не делайте вывод о производительности по одной трассе: сравнивайте одинаковые сценарии и следите за затратами на сбор, передачу и хранение данных.
Что делать дальше
Начните с одного сквозного сценария: входящий запрос, один вызов другого сервиса и обращение к хранилищу. Проверьте, что они образуют одну трассу, а затем замерьте долю запросов с данными, объём экспорта и нагрузку на приложение. После этого подключайте остальные сервисы и задайте правила семплирования и хранения. Настройки Collector, автоматической инструментации и контекстной пропагации разбирайте отдельно для конкретных компонентов вашей системы.
1 Span — интервал трассы, описывающий отдельную операцию; несколько span связываются в дерево и образуют трассу.
Логотип и фирменный стиль: Три концепции разного характера, палитра с обоснованием, проверка на читаемость в малом размере и в один цвет.
Спросить за 60 ₽Источники: OpenTelemetry Python: документация, OpenTelemetry Collector: документация
Частые вопросы
Нужен ли Collector, чтобы начать?
OpenTelemetry — это хранилище трасс?
Можно ли включить трассировку без изменений кода?
Почему трасса обрывается на очереди или другом сервисе?
Как уменьшить стоимость хранения трасс?
Безопасно ли записывать в span идентификатор пользователя или заказа?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.