--- id: 015 title: Add minimal OpenTelemetry tracing status: DONE created: 2026-03-13 --- ## Context После удаления observability stack в задаче `012` runtime-приложение осталось без трассировки. Появилось новое требование: вернуть только минимальный tracing для входящих HTTP-запросов и исходящих вызовов провайдера/Redis, без возврата metrics, alerting и trace/log correlation. ## Goal Подключить минимальный OpenTelemetry tracing через централизованный runtime bootstrap: настроить `TracerProvider` и OTLP exporter из YAML-конфига, добавить instrumentation для FastAPI, httpx и Redis и встроить этот bootstrap в startup приложения без переноса telemetry concern в Business Logic. ## Constraints - Соблюдать layered architecture из `AGENTS.md`. - Scope задачи: только tracing bootstrap, YAML configuration, instrumentation wiring и тесты на это поведение. - Не добавлять metrics, request correlation middleware, `request_id`, `trace_id` в логи, SigNoz, Telegram alerting и иные observability features кроме tracing. - Не добавлять business rules, branching или data access в runtime tracing bootstrap. - Инициализация OpenTelemetry должна жить в отдельном runtime-модуле или app startup; Controller, Service, Repository, Adapter и Business Logic не должны вручную создавать exporter/provider. - Конфигурация tracing должна читаться из отдельной секции `observability` в YAML-файлах конфигурации. - Bootstrap tracing должен быть идемпотентным: повторные вызовы `create_app()` в тестах не должны дублировать global instrumentation и span processors. - Не изменять API contract, логику расчета тарифов, кэш semantics и provider protocol. - Не изменять файлы в `spec/`. ## Acceptance criteria - В конфигурации приложения добавлена секция `observability` с параметрами включения tracing, `service_name`, OTLP endpoint и флагом insecure transport. - При `observability.enabled = true` приложение на старте создает `TracerProvider` с `Resource(service.name=...)` и OTLP exporter, используя значения из YAML-конфига. - При `observability.enabled = true` централизованно включается instrumentation для FastAPI, httpx и Redis. - При `observability.enabled = false` приложение стартует без инициализации exporter/provider и без регистрации instrumentation. - Повторное создание приложения или повторный вызов tracing bootstrap не приводит к duplicate instrumentation/span processor registration. - Реализация не восстанавливает metrics, alerts, request/log correlation и не меняет JSON logging contract. ## Definition of Done - [ ] Добавлена секция `observability` в config schema и runtime YAML-файлы. - [ ] Реализован централизованный runtime bootstrap для OpenTelemetry tracing. - [ ] `create_app()` подключает tracing bootstrap без бизнес-логики и без дублирования инициализации. - [ ] Добавлены tests на конфигурацию, enabled/disabled режимы и идемпотентность tracing setup. - [ ] Добавлен tracing test, подтверждающий создание spans для FastAPI/httpx/Redis instrumentation или корректный wiring этих instrumentors. ## Tests - Обновить `tests/config/test_config_sections.py` для проверки секции `observability`, обязательных полей и disabled/enabled конфигурации. - Обновить `tests/smoke/test_app_import.py` для проверки вызова централизованного tracing bootstrap при создании app. - Добавить `tests/tracing/test_bootstrap.py` для проверки OTLP exporter/provider setup, `service.name`, enabled/disabled режимов и идемпотентности instrumentation. - Добавить tracing test с in-memory exporter или эквивалентным deterministic harness для проверки, что FastAPI/httpx/Redis instrumentation корректно подключается без запуска внешнего OTLP collector. ## Commands - `poetry run pytest tests/config/test_config_sections.py -q` - `poetry run pytest tests/smoke/test_app_import.py -q` - `poetry run pytest tests/tracing/test_bootstrap.py -q` - `python3 spec/gen_spec_index.py --check`