English translation is not available yet. Showing Russian content.
Настроить distributed tracing
ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Настроить distributed tracing
1. Цель задачи
Настроить сквозную распределённую трассировку (distributed tracing) между агентами многокомпонентной системы. Каждое меж-агентское сообщение должно содержать уникальный trace_id, который позволяет восстановить полную цепочку вызовов от инициатора до всех вложенных агентов. Это даст возможность анализировать задержки, ошибки и зависимости в архитектуре, где агенты общаются через асинхронные очереди (RabbitMQ) или синхронные вызовы (gRPC/HTTP).
Ключевой результат Работающий дашборд в Jaeger/Zipkin, отображающий спаны для каждого шага общения агентов, с trace_id, передаваемым через заголовки сообщений.
2. Исходные данные
| Что нужно | Откуда взять |
|---|---|
| Многокомпонентная система агентов (2+ агента) | Собранный пет-проект (например, на LangGraph, CrewAI) или самописные микросервисы |
| Очередь сообщений или RPC-канал между агентами | RabbitMQ, Kafka, gRPC, HTTP (на выбор; предпочтительно RabbitMQ) |
| Docker / Docker Compose | Локальная установка |
| Python 3.10+ | Установлен в окружении |
| OpenTelemetry Python SDK | pip install opentelemetry-api opentelemetry-sdk |
| Jaeger (или Zipkin) для визуализации | docker run -p 16686:16686 jaegertracing/all-in-one:latest |
Если нет реального инструмента — симулируем:
- Напишите двух простых Python-сервисов (агент A и агент B), общающихся через RabbitMQ (или gRPC).
- Используйте aio_pika для RabbitMQ или grpc для синхронных вызовов.
- Разверните Jaeger
all-in-oneв Docker Compose. - Инструментируйте оба сервиса с помощью OpenTelemetry.
3. Технологический стек
| Компонент | Инструменты | Назначение |
|---|---|---|
| Язык | Python 3.10+ | Реализация агентов |
| Агенты | LangGraph / CrewAI / самописные asyncio-сервисы | Многокомпонентная система |
| Транспорт между агентами | RabbitMQ / gRPC / HTTP (REST) | Передача сообщений |
| Трассировка | OpenTelemetry SDK, OpenTelemetry Python APIs | Генерация спанов и контекста |
| Бэкенд трейсов | Jaeger (all-in-one) / Zipkin | Хранение и визуализация |
| Контейнеризация | Docker + Docker Compose | Окружение для запуска |
| Python-клиенты | opentelemetry-exporter-otlp, opentelemetry-instrumentation | Инструментирование HTTP/gRPC/AMQP |
4. Этапы выполнения
Этап 1: Подготовка окружения и запуск Jaeger (30 минут)
Действия
- Создать директорию проекта
distributed-tracing-lab. - В корне создать docker-compose.yml с сервисом Jaeger:
version: '3' services: jaeger: image: jaegertracing/all-in-one:latest ports: - "16686:16686" # UI - "4317:4317" # OTLP gRPC - "4318:4318" # OTLP HTTP - Запустить docker compose up -d jaeger.
- Проверить UI: открыть http://localhost:16686.
Ожидаемый результат этапа Запущенный Jaeger, пустой дашборд.
Этап 2: Создание тестовой системы агентов (1 час)
Действия
- Написать
agent_a.pyиagent_b.pyс базовым обменом через RabbitMQ (или gRPC). Пример для RabbitMQ:- Агент A получает HTTP-запрос, создаёт задачу, шлёт сообщение в очередь
tasks. - Агент B слушает
tasks, выполняет работу, отправляет результат в очередьresults. - Агент A потребляет
resultsи возвращает финальный ответ.
- Агент A получает HTTP-запрос, создаёт задачу, шлёт сообщение в очередь
- Установить зависимости:
pip install aio-pika opentelemetry-distro opentelemetry-bootstrap -a install - Убедиться, что система работает без трассировки (простое логирование).
Ожидаемый результат этапа Рабочая коммуникация между двумя агентами, сообщения передаются через брокер (или gRPC).
Этап 3: Инструментирование OpenTelemetry (1.5 часа)
Действия
- В каждом агенте инициализировать TracerProvider и экспортёр OTLP:
from opentelemetry import trace from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor provider = TracerProvider() exporter = OTLPSpanExporter(endpoint="localhost:4317", insecure=True) provider.add_span_processor(BatchSpanProcessor(exporter)) trace.set_tracer_provider(provider) tracer = trace.get_tracer(__name__) - Создать корневой span при входящем запросе к Agent A.
- При отправке сообщения в RabbitMQ (или gRPC) передать контекст трассировки через заголовки:
- Для RabbitMQ: при отправке сообщения вставить заголовки traceparent (формат W3C trace-context).
- Для gRPC: использовать стандартные метаданные gRPC.
- Для HTTP: заголовок traceparent.
- В Agent B при получении сообщения извлечь контекст с помощью propagators:
from opentelemetry import propagate ctx = propagate.extract(carrier=headers) # headers — словарь из сообщения with tracer.start_as_current_span("agent_b_process", context=ctx): # обработка - Добавить вложенные спаны для каждой значимой операции (parse, call external API, write to DB).
Ожидаемый результат этапа При запуске цепочки запросов в Jaeger появляются трейсы, состоящие из нескольких спанов (для Agent A и Agent B).
Этап 4: Проверка передачи trace_id и визуализация (30 минут)
Действия
- Отправить несколько тестовых запросов через Agent A (например, через curl или Python requests).
- Открыть Jaeger UI, найти трейс по service name
agent_a. - Убедиться, что:
- В трейсе есть спаны обеих служб.
trace_idодинаковый для всех спанов одной цепочки.- Видны временные метки и длительности каждого шага.
- Проверить, что
traceparentпередаётся в заголовках сообщений (можно включить отладочный вывод).
Ожидаемый результат этапа В Jaeger отображаются полные трейсы меж-агентских вызовов.
Этап 5: Документирование и автоматизация (30 минут)
Действия
- Написать
README.mdс инструкцией по запуску:docker compose up, запуск агентов, пример запроса. - Создать Makefile или bash-скрипт для однокомандного запуска всей системы.
- Добавить в код комментарии о том, как контекст прокидывается через брокер.
Ожидаемый результат этапа README и скрипты, позволяющие воспроизвести решение на чистом окружении.
5. Критерии приемки (Definition of Done)
- Jaeger UI запущен и доступен по адресу
http://localhost:16686. - Два агента обмениваются сообщениями через выбранный транспорт (RabbitMQ/gRPC/HTTP).
- При старте каждого агента инициализируется OpenTelemetry TracerProvider с экспортом в Jaeger.
- При отправке сообщения от Agent A к Agent B в заголовки добавляется
traceparent. - При получении сообщения Agent B извлекает контекст и создаёт дочерние спаны.
- В Jaeger отображается полный трейс для каждого запроса, содержащий спаны обеих служб.
-
trace_idедин для всех спанов одной цепочки (проверено по UI). - Код задокументирован (README, комментарии).
- Система воспроизводится одной командой
docker compose up+ запуск агентов. - Тестовый запрос (например, POST на Agent A) возвращает ответ, а трейс отображается в Jaeger за < 1 секунды.
6. Ожидаемый результат
- Артефакт Папка
distributed-tracing-labс файлами:docker-compose.yml,agent_a.py,agent_b.py,requirements.txt,Makefile,README.md. - Содержание Рабочая система distributed tracing для двух агентов с передачей контекста через сообщения.
- Опционально Графики в Jaeger (скриншот трейса приложен к задаче), скрипт для нагрузки (test.sh).
7. Возможные сложности и их решение
| Сложность | Решение |
|---|---|
| OpenTelemetry не видит библиотеку RabbitMQ (aio-pika) | Использовать opentelemetry-instrumentation с aio-pika или вручную создать спаны при отправке/получении |
| Контекст не передаётся через RabbitMQ | Убедиться, что используется W3C traceparent в заголовках сообщения и propagate.extract вызывается на стороне потребителя |
| Jaeger не показывает спаны | Проверить, что экспортёр OTLP отправляется на правильный порт (4317), и что Jaeger слушает gRPC |
| Разные trace_id для одного запроса | Проверить, что при извлечении контекста не создаётся новый корневой span вместо дочернего |
| Зависимости конфликтуют (версии OpenTelemetry) | Использовать opentelemetry-distro и opentelemetry-bootstrap, зафиксировать версии в requirements.txt |
| Задержки при старте из-за RabbitMQ | Использовать docker compose с зависимостью depends_on на rabbitmq |
8. Бюджет времени (оценка)
| Этап | Время |
|---|---|
| Подготовка окружения и запуск Jaeger | 30 мин |
| Создание тестовой системы агентов | 1 ч |
| Инструментирование OpenTelemetry | 1 ч 30 мин |
| Проверка передачи trace_id и визуализация | 30 мин |
| Документирование и автоматизация | 30 мин |
| Итого | 4 ч |
Примечание: Для первого исполнителя с нулевым опытом OpenTelemetry время может увеличиться до 6-8 часов. Рекомендуется предварительно пройти quickstart OpenTelemetry для Python.
9. Связанные вопросы из базы знаний
| Вопрос | Тема |
|---|---|
| 12 | Что такое distributed tracing и зачем он нужен в multi-agent системах? |
| 34 | Как работает OpenTelemetry propagators? |
| 89 | Формат W3C trace-context: traceparent и tracestate |
| 145 | Инструментирование RabbitMQ с OpenTelemetry в Python |
| 203 | Сравнение Jaeger и Zipkin |
| 267 | Настройка batch span processor |
| 310 | Как дебажить проблемы с экспортом трейсов? |
| 422 | gRPC metadata propagation для trace context |
| 578 | Интеграция OpenTelemetry с LangGraph |
| 601 | Мониторинг задержек между агентами через дашборды |
10. Чек-лист самопроверки
- Я запустил Jaeger через Docker Compose и убедился, что UI доступен.
- Мои агенты общаются через брокер (RabbitMQ) или RPC, и я вижу логи сообщений.
- Я добавил импорты и инициализацию OpenTelemetry в каждом агенте.
- При отправке сообщения я вставил заголовок
traceparent(илиtraceparent+tracestate). - При получении сообщения я вызвал
extractи использовал полученный контекст при создании нового span. - Я отправил тестовый запрос и увидел в Jaeger трейс, содержащий спаны обеих служб с одинаковым
trace_id. - Я написал README и Makefile для воспроизведения на чистом окружении.