Налаштування наскрізної кореляції логів, метрик і трейсів?
Розбираєш інцидент: метрики показують різке зростання latency о 03:47, але в Grafana немає анотації, Loki видає тисячі рядків логів за ту хвилину, а в Jaeger трейси є, але незрозуміло, який span «ліг» першим. Три системи, три інтерфейси, нуль зв'язку між ними — і ви витрачаєте годину на ручне звірення timestamp'ів. Ми стикалися з цим десятки разів. Наш підхід — налаштувати наскрізну кореляцію за 5–10 робочих днів, скоротити MTTR на 60% (економія від $5000/міс) і позбавити команду рутини. Налаштування через OpenTelemetry в 3 рази швидше за ручний парсинг логів.
Кореляція логів, метрик і трейсів — це можливість в один клік перейти від аномалії на графіку до конкретного трейсу, а з трейсу — до рядка лога з повним контекстом помилки. Без неї діагностика розподілених систем перетворюється на детектив з лупою. Отримайте консультацію з налаштування кореляції для вашого проекту.
Як OpenTelemetry забезпечує єдиний шар?
Сучасний стек для кореляції — це OpenTelemetry Collector, який отримує дані від усіх трьох сигналів і пробрасовує їх у відповідні бекенди. Типова конфігурація:
Конфігурація OpenTelemetry Collector
---
# otel-collector-config.yaml
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
prometheus:
config:
scrape_configs:
- job_name: 'app'
static_configs:
- targets: ['app:8080']
processors:
batch:
timeout: 10s
resource:
attributes:
- key: deployment.environment
value: production
action: upsert
exporters:
otlp/jaeger:
endpoint: jaeger:4317
tls:
insecure: true
loki:
endpoint: http://loki:3100/loki/api/v1/push
labels:
resource:
service.name: "service_name"
deployment.environment: "env"
prometheus:
endpoint: 0.0.0.0:8889
namespace: otel
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch, resource]
exporters: [otlp/jaeger]
metrics:
receivers: [otlp, prometheus]
processors: [batch]
exporters: [prometheus]
logs:
receivers: [otlp]
processors: [batch, resource]
exporters: [loki]
Ключовий момент: всі три пайплайни працюють через один Collector, який забезпечує єдиний resource. Відповідно до специфікації OpenTelemetry (https://opentelemetry.io/docs/specs/otel/trace/), trace_id повинен бути 128-бітним hex.
Exemplars: зв'язок метрик з трейсами
Prometheus починаючи з версії 2.29 підтримує exemplars — це точки на гістограмі, до яких прикріплений trace_id. Щоб це працювало, потрібні дві умови:
# prometheus.yml global: scrape_interval: 15s storage: exemplars: max_exemplars: 100000 І в самому застосунку (приклад для Go з prometheus/client_golang):
histogram.With(prometheus.Labels{"handler": "/api/users"}).
ObserveWithExemplar(
duration,
prometheus.Labels{"traceID": span.SpanContext().TraceID().String()},
)У Grafana при увімкненому режимі exemplars на графіку з'являються маленькі ромбики — клік переносить прямо в Jaeger/Tempo на конкретний трейс. Наш досвід показує, що exemplars скорочують час пошуку першопричини з 40 хвилин до 5.
Прокидання trace_id в логи
Застосунок повинен при кожному запиті витягувати trace_id з активного span'а і додавати його в лог-запис. У Node.js з winston це виглядає так:
const { trace } = require('@opentelemetry/api');
const addTraceInfo = winston.format((info) => {
const span = trace.getActiveSpan();
if (span) {
const ctx = span.spanContext();
info.trace_id = ctx.traceId;
info.span_id = ctx.spanId;
}
return info;
});Після цього Loki отримує логи з полем trace_id, і Grafana будує посилання з лога прямо в Tempo/Jaeger через derivedFields в datasource.
Недостатність correlation_id для повної кореляції
Багато хто зупиняється на рівні X-Request-ID в заголовках і correlation_id в JSON-логах. Це необхідно, але недостатньо. Проблеми починаються там, де сервіс на Go логує в stdout без структури, Logstash парсить через grok з регулярками, які не захоплюють trace_id, а Prometheus збирає метрики без label'а trace_id — і не може, це принципово інший тип даних. Трейси в Jaeger зберігають span_id і trace_id, але логи сервісу їх не містять, тому що розробник не прокинув контекст через context.Context.
Справжня кореляція будується на трьох речах: єдиний формат часу (UTC, мілісекунди), propagation контексту трейсу в логи та exemplars в метриках для зв'язку з трейсами. Без exemplars кореляція буде неповною.
Як Grafana об'єднує всі три джерела?
Grafana 10+ вміє «склеювати» всі три джерела через Explore. Один запит у Loki — і поруч кнопка «View in Tempo». З Tempo — кнопка «Logs for this span». Це працює тільки якщо налаштовані correlations між datasource'ами. На практиці налаштування correlations через UI Grafana крихке — краще описувати її в provisioning/datasources/.
Порівняємо три методи кореляції.
| Метод | Вимоги | Переваги | Недоліки |
|---|---|---|---|
| correlation_id | Прокидання заголовка | Простота реалізації | Немає зв'язку з трейсами та метриками |
| OpenTelemetry + exemplars | OpenTelemetry SDK, exemplars в метриках | Повна наскрізна кореляція | Вимагає змін у коді |
| Ручний парсинг логів | Тільки логи | Не потребує змін | Повільний, ненадійний |
Типові проблеми при впровадженні
- Різні формати trace_id. Jaeger використовує 128-bit hex, Zipkin — 64-bit. Якщо в системі є legacy-сервіс з Zipkin, trace_id в логах буде в різних форматах — correlate не спрацює. Рішення: OpenTelemetry Collector з
zipkinreceiverі конвертацією. - Асинхронні завдання втрачають контекст. Celery-воркер, що обробляє задачу з Redis-черги, не знає trace_id HTTP-запиту. Треба явно передавати контекст трейсу в payload і відновлювати його через
propagate.extract(). - Логи без структури. Якщо застосунок пише
ERROR: connection refusedв stdout, витягнути trace_id неможливо без grok-парсингу. Іноді простіше додати JSON-форматер.
Що входить в роботу
- Аудит поточного стеку: інвентаризація сервісів, мов, форматів логів та наявності tracing instrumentation.
- Впровадження OpenTelemetry SDK або auto-instrumentation через otel-operator для Kubernetes.
- Розгортання OpenTelemetry Collector з трьома пайплайнами та налаштування exporters.
- Налаштування exemplars в Prometheus та correlations в Grafana через provisioning.
- Прокидання trace_id в логи у всіх сервісах.
- Тестування наскрізної кореляції: генерація трафіку, перевірка trace_id від HTTP до БД.
- Документація: опис архітектури кореляції, інструкція для розробників.
- Навчання команди (2-годинний вебінар).
- Підтримка 2 тижні після впровадження.
Як ми це робимо: покроково
- Аудит поточного стеку (1–2 дні).
- Впровадження OpenTelemetry SDK у всіх сервісах (3–10 днів).
- Налаштування Collector та Grafana (1–2 дні).
- Тестування та документування (1–2 дні).
Наші інженери мають 5+ років досвіду в observability, сертифіковані за OpenTelemetry та Kubernetes — гарантія результату. За 5 років виконали понад 50 проектів з налаштування observability. Проект окупається за 2–3 місяці за рахунок скорочення часу діагностики інцидентів. Зв'яжіться з нами для оцінки вашого проекту — замовте впровадження під ключ.







