Трассировка OpenTelemetry
Трассировка показывает, что происходило внутри каждого запроса: какой эндпоинт его принял, какие запросы к базе он сделал, какие сервисы и внешние API вызвал и где потратил время. Наблюдатель принимает трассы стандартного OpenTelemetry SDK — отдельная библиотека Наблюдателя не нужна, достаточно OTel SDK для вашего языка и нескольких переменных окружения.
Трассы отправляются на агента стека внутри вашей сети. Агент обезличивает персональные данные и пересылает трассы в Наблюдатель. По ним строятся вкладка «Трассировка», карта сервисов и медленные запросы к БД, а у ошибок приложения появляется ссылка на трассу.
Что нужно для трассировки OpenTelemetry
- Агент стека — в Docker Compose или Kubernetes. Агент сервера трассы не принимает.
- В окружении агента
NABL_OTLP_ENABLED: "true". В готовом сервисе агента, который выдаёт Наблюдатель при создании стека, это уже включено. - Приложение видит агента по сети: в Docker Compose — по имени сервиса
nabl-agentв той же сети, в Kubernetes — сервисnabl-agentв том же namespace.
Агент принимает трассы на двух портах внутри сети стека:
| Порт | Протокол |
|---|---|
| 4318 | OTLP/HTTP, protobuf |
| 4317 | OTLP gRPC |
Важно. OTLP/HTTP в формате JSON агент не принимает — приложение получит ответ
400 bad protobuf. Нуженhttp/protobufили gRPC.
Публиковать эти порты наружу не нужно. Если приложение запущено не в Docker, а прямо на вашем компьютере, используйте http://127.0.0.1:4318 и опубликуйте порты агента на localhost — см. локальную разработку.
Как подключить: переменные окружения
Эти переменные понимает OTel SDK любого языка. Пример для сервиса в docker-compose.yml:
environment:
OTEL_SERVICE_NAME: api # имя сервиса в трассах; без него — unknown_service
OTEL_EXPORTER_OTLP_ENDPOINT: http://nabl-agent:4318
OTEL_EXPORTER_OTLP_PROTOCOL: http/protobuf
OTEL_TRACES_EXPORTER: otlp
OTEL_METRICS_EXPORTER: none # агент принимает только трассы
OTEL_LOGS_EXPORTER: none
OTEL_RESOURCE_ATTRIBUTES: deployment.environment=production,service.version=1.4.0OTEL_EXPORTER_OTLP_ENDPOINT— базовый адрес, SDK сам добавит/v1/traces. Если задаётеOTEL_EXPORTER_OTLP_TRACES_ENDPOINT, указывайте полный путь:http://nabl-agent:4318/v1/traces.- Для gRPC:
OTEL_EXPORTER_OTLP_ENDPOINT=http://nabl-agent:4317иOTEL_EXPORTER_OTLP_PROTOCOL=grpc. service.versionвOTEL_RESOURCE_ATTRIBUTESпомогает отличить трассы до и после релиза.- Сэмплер SDK оставьте по умолчанию и не задавайте
OTEL_TRACES_SAMPLER. Наблюдатель сохраняет все трассы без выборки, поэтому число запросов, доля ошибок и время ответа считаются по всем запросам. Сэмплер в приложении занизит цифры.
Примеры подключения по языкам
Node.js
npm i @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node @opentelemetry/exporter-trace-otlp-protoБез изменения кода — автоинструментация при запуске (переменные окружения из раздела выше):
node --require @opentelemetry/auto-instrumentations-node/register server.js
# или NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register"С кодом — файл tracing.js, который подключается до остального кода: node -r ./tracing.js server.js.
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-proto'); // proto, не exporter-trace-otlp-http (JSON)
new NodeSDK({
traceExporter: new OTLPTraceExporter(), // адрес из OTEL_EXPORTER_OTLP_ENDPOINT
instrumentations: [getNodeAutoInstrumentations({ '@opentelemetry/instrumentation-fs': { enabled: false } })],
}).start();Python
pip install opentelemetry-distro opentelemetry-exporter-otlp-proto-http
opentelemetry-bootstrap -a install # инструментации для найденных библиотек: Django, Flask, FastAPI, requests, psycopg…
opentelemetry-instrument python app.py # или: opentelemetry-instrument gunicorn app:appДля gunicorn с несколькими воркерами запускайте его через opentelemetry-instrument, как в примере.
Go
import (
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
"go.opentelemetry.io/otel/propagation"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)
func initTracing(ctx context.Context) (func(context.Context) error, error) {
exp, err := otlptracehttp.New(ctx) // OTEL_EXPORTER_OTLP_ENDPOINT, protobuf по умолчанию
if err != nil {
return nil, err
}
tp := sdktrace.NewTracerProvider(sdktrace.WithBatcher(exp)) // имя сервиса из OTEL_SERVICE_NAME
otel.SetTracerProvider(tp)
otel.SetTextMapPropagator(propagation.TraceContext{})
return tp.Shutdown, nil
}
// HTTP-сервер: http.ListenAndServe(":8080", otelhttp.NewHandler(mux, "api"))
// Gin: r.Use(otelgin.Middleware("api"))
// GORM: db.Use(tracing.NewPlugin()), запросы через db.WithContext(ctx)Java (Spring и другие)
Java-агент OpenTelemetry подключается без изменения кода:
java -javaagent:/otel/opentelemetry-javaagent.jar -jar app.jarС переменными окружения из раздела выше. В javaagent 2.x протокол http/protobuf используется по умолчанию.
.NET
Пакеты OpenTelemetry.Extensions.Hosting, OpenTelemetry.Instrumentation.AspNetCore и OpenTelemetry.Exporter.OpenTelemetryProtocol:
builder.Services.AddOpenTelemetry()
.WithTracing(t => t
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddOtlpExporter(o =>
{
o.Protocol = OtlpExportProtocol.HttpProtobuf;
o.Endpoint = new Uri("http://nabl-agent:4318/v1/traces");
}));PHP
Расширение OpenTelemetry, SDK с OTLP-экспортёром и автоинструментация вашего фреймворка (пример для Laravel):
pecl install opentelemetry
composer require open-telemetry/sdk open-telemetry/exporter-otlp php-http/guzzle7-adapter \
open-telemetry/opentelemetry-auto-laravelК переменным окружения из раздела выше добавьте OTEL_PHP_AUTOLOAD_ENABLED=true.
Как проверить, что трассы приходят
- Сделайте несколько запросов к приложению.
- Через 5–10 секунд откройте стек → вкладка «Трассировка». Пока трасс нет, там показана короткая инструкция подключения.
Если трассы не появились:
| Что видно | Причина |
|---|---|
в логах приложения 400 или bad protobuf |
экспортёр шлёт JSON — нужен http/protobuf (в Node.js — пакет exporter-trace-otlp-proto) |
ECONNREFUSED / connection refused к nabl-agent |
приложение не в той же сети, что агент, другое имя сервиса агента или NABL_OTLP_ENABLED не true |
404 на /v1/metrics или /v1/logs (агент до 0.9.1) |
включены экспортёры метрик или логов — задайте OTEL_METRICS_EXPORTER=none и OTEL_LOGS_EXPORTER=none |
трассы есть, но сервис называется unknown_service |
не задан OTEL_SERVICE_NAME |
| SDK отправляет, а в Наблюдателе пусто | агент привязан к серверу, а не к стеку |
Больше вариантов — в разделе решение проблем.
Вкладка «Трассировка»
Вкладка открывается на странице стека. Наверху — общая панель: выбор сервиса и период «Данные за» — 1 ч, 6 ч, 24 ч или 7 дн. Сервис и период действуют на всё ниже: карту, обзор, операции и список трасс. Когда выбран сервис, рядом появляется ссылка «Страница сервиса →» — подробнее в статье карта сервисов и страница сервиса.
Карта сервисов
Кто кого вызывает: сервисы, базы данных, брокеры сообщений и внешние адреса. Клик по сервису или базе показывает их трассы в списке ниже. Как читать карту — в отдельной статье.
Обзор
Четыре плитки с небольшими графиками:
- Входящие запросы — сколько запросов в секунду или минуту и сколько всего за период;
- Время ответа, p95 — 95% запросов быстрее этого значения;
- Ошибки — доля и число запросов с ошибкой;
- База данных — частота запросов к базе и их p95.
У каждой плитки — изменение к прошлому периоду: к прошлому часу, 6 часам, суткам или неделе. Под плитками — одна–три строки о главном: где ошибки, выросло ли время ответа, какая операция самая медленная и что больше всего нагружает базу. Клик по строке открывает эту операцию.
Операции
Таблица операций: HTTP-маршруты, запросы к базе, сообщения очередей и внутренние операции. Фильтр по типу — «Все», «Запросы», «База данных», «Очереди», «Внутренние», поиск — по строке вроде orders, SELECT или /api. Колонки «Вызовов», «p95» и «Ошибки» сортируются, в колонке «Динамика» — график времени ответа с красными точками на ошибках.
Сначала видны пять самых частых операций, остальные — по кнопке «Показать все». Названия читаемые: вместо postgresql:PG.QUERY:SET — «PostgreSQL · SET», а исходящие запросы к внешним сервисам подписаны адресом — «POST api.partner.ru/v1/orders», поэтому разные адреса не сливаются в одну строку. Клик по строке раскрывает графики операции за период — время ответа, вызовы, ошибки — и кнопку «Показать трассы этой операции».
Операции строятся по атрибуту http.route (/users/:id). Если инструментация его не пишет, адрес нормализуется автоматически, но хуже.
Список трасс
Ниже — трассы за выбранный период: операция, число спанов, длительность, время. Фильтры «Все», «OK», «Ошибки» и поиск «Поиск операции / trace id» — по названию любой операции внутри трассы или по идентификатору трассы.
Клик по трассе раскрывает временную шкалу спанов. Клик по спану показывает детали: текст SQL-запроса, атрибуты по разделам, события (например, записанное исключение), время от начала трассы и долю от общей длительности. Кнопка «JSON» у раскрытой трассы выгружает её целиком — со всеми спанами и атрибутами.
Под шкалой спанов — блок «Записи потоков с этим trace_id»: что пришло в запросе и что ответили, если приложение пишет в потоки событий trace_id текущего запроса.
Свёртка служебных спанов
Автоинструментация создаёт на каждый запрос десятки коротких служебных спанов: хуки fastify, middleware express, guards NestJS, получение соединения из пула. Подряд идущие такие спаны сворачиваются в одну строку, например «15 служебных спанов · 0,25 мс», поэтому обработчик, вызовы gRPC и SQL видны сразу. Строка раскрывается по клику, а переключатель «Показать все спаны» над трассой показывает всё без свёртки.
Спан с вложенными вызовами, с ошибкой или дольше 1 мс никогда не сворачивается. Данные не удаляются, отключать служебные спаны в приложении не нужно.
Что считается ошибкой в трассе
Спан со статусом ERROR или ответом HTTP 5xx считается ошибкой. Обрыв запроса клиентом (context canceled) — нет. Чтобы в трассе было видно, что именно упало, записывайте исключение в спан: recordException в Node.js и Java, span.RecordError в Go.
Чтобы ошибка на вкладке «Ошибки» вела к своей трассе, добавьте trace_id и span_id в запись лога — см. мониторинг ошибок.
Сроки хранения трасс
| Данные | Срок |
|---|---|
| Трассы без ошибок | 7 дней |
| Трассы с ошибками | 30 дней |
| Число запросов, ошибки и p95 по сервисам и операциям | 3 месяца |
Обзор и операции за длинный период считаются по сохранённым агрегатам, то есть по всем запросам, а не только по оставшимся трассам. На вкладке доступны периоды до 7 дней; за 30 дней обзор и операции можно попросить у ИИ-ассистента — за этот срок остаются только трассы с ошибками.
Персональные данные в трассах
Агент маскирует персональные данные и секреты до отправки: в атрибутах, SQL-запросах, адресах, сообщениях и стеках исключений. Литералы в SQL (WHERE email = '…') заменяются — в Наблюдатель уходит структура запроса без данных. Подробнее — в статье как работает агент.
Проверки сайтов в трассах
HTTP-проверки Наблюдателя приходят с заголовком traceparent и меткой в адресе (?nabl_check=…). Так Наблюдатель находит, какой сервис принимает проверку, и показывает узел проверки на карте. В обзор, операции и список трасс проверки не входят и нагрузку не искажают. Настраивать ничего не нужно; если приложение отвечает на лишний параметр ошибкой, метка в адресе выключится сама. Подробнее — в статье о проверках сайтов.
Что дальше
- Медленные запросы к БД и N+1 — что видно по трассам о базе данных.
- Карта сервисов и страница сервиса — связи и здоровье сервисов.
- Мониторинг ошибок приложения — ошибки со ссылкой на трассу.
- Аномалии — цель сервиса и уведомления, когда сервис стал медленнее или чаще ошибается.
Первый сервер или стек подключается за пару минут. Бесплатно в раннем доступе.
Нашли неточность или не хватает ответа? Напишите в поддержку