OpenTelemetry: один стандарт вместо десятка SDK

В главе «Телеметрия» мы говорили про три типа данных — метрики, логи, трейсы. И про то, что в каждой компании исторически собирали их по-своему: Prometheus для метрик, ELK для логов, Jaeger для трейсов. Каждая система со своим агентом, своим протоколом, своим форматом.

OpenTelemetry (OTel) — это попытка индустрии договориться: один открытый стандарт вместо десятка проприетарных SDK. Как OpenAPI для REST или OpenSLO для SLO. Не продукт, не компания, не библиотека — стандарт, реализованный в виде SDK и инструментов, который к 2026 году стал де-факто выбором для новых проектов.

Зачем это нужно

До OpenTelemetry типичная интеграция выглядела так: ваш сервис на Python пишет метрики в Prometheus через prometheus_client, логи шлёт в Elasticsearch через Logstash, трейсы — в Jaeger через OpenTracing. Три разных SDK, три разных агента, три разных способа конфигурировать sampling и enrichment. И каждый SDK имеет свой API, свои best practices, свои баги.

Приходит момент, когда нужно сменить backend (Prometheus → VictoriaMetrics, Jaeger → Tempo). И вы переписываете половину кода, потому что SDK привязан к конкретному вендору. С OpenTelemetry такой проблемы нет: код пишется один раз, а backend меняется через конфигурацию Collector-а.

Что входит в OpenTelemetry

OpenTelemetry — это не один продукт, а семейство компонентов:

1. API и SDK

Единый API для метрик, логов и трейсов на разных языках: Java, Python, Go, Node.js, .NET, Rust, PHP, Ruby, C++, Erlang/Elixir, Swift. Каждый SDK поддерживает три сигнала (signals):

  • Traces — распределённые трейсы (раньше OpenTracing + OpenCensus)
  • Metrics — счётчики, гистограммы, gauge-значения
  • Logs — структурированные логи с привязкой к трейсу

Главная фишка — resource attributes: контекст, который прикрепляется ко всем сигналам автоматически. Сервис, версия, окружение, регион, кластер Kubernetes. Один раз настроили — все метрики/трейсы/логи обогащаются одинаковыми метаданными.

2. Collector

OpenTelemetry Collector — это прокси между приложениями и бэкендами. Архитектурно похож на Vector, Fluentd, Logstash: принимает данные по одному протоколу, обрабатывает и отправляет в нужный backend.

[Приложение с OTel SDK]
        ↓ OTLP (gRPC/HTTP)
[OpenTelemetry Collector]
        ↓ приёмники → процессоры → экспортёры
[Prometheus, Jaeger, Tempo, Datadog, Sentry, ...]

Collector работает в трёх режимах: - Agent — рядом с приложением, форвардит данные - Gateway — центральный, агрегирует данные от нескольких агентов - Sidecar — в Kubernetes как sidecar к поду

3. Семантические конвенции

Стандартные имена для атрибутов: http.method, http.status_code, db.system, messaging.destination. Без этого каждый разработчик называет поля как попало, и потом аналитик тратит дни на маппинг. OTel конвенции решают эту проблему на корню.

4. Auto-instrumentation

Для популярных библиотек (HTTP-клиенты, SQL-ORM, gRPC, Redis, Kafka) есть готовые инструментации. Не надо вручную оборачивать вызовы — добавляется агент или пакет, и все вызовы автоматически трейсятся с правильными span-ами.

В Java это вообще магия: -javaagent:opentelemetry-javaagent.jar — и ваш Spring Boot пишет трейсы в OTLP без изменений в коде.

Как это выглядит на практике

Типичный pipeline в Kubernetes:

  1. Приложение запускается с OTel SDK (или Java/Python/.NET auto-instrumentation)
  2. SDK отправляет данные в OTel Collector через OTLP — стандартный бинарный протокол на gRPC или HTTP+JSON
  3. Collector запускается как DaemonSet на каждом узле (или как deployment с replicas)
  4. Collector обрабатывает данные: фильтрует, обогащает, батчит, сэмплит
  5. Collector экспортирует данные в нужные backend-ы параллельно: Prometheus, Jaeger, Loki, Datadog, New Relic — что угодно

Преимущество: поменять backend = поменять конфиг Collector-а. Код приложения не трогаем.

OpenTelemetry и «три столпа observability»

Старая школа учит: метрики + логи + трейсы = observability. OpenTelemetry технически поддерживает все три, но в комьюнити набирает силу мнение, что это устаревшая рамка. Подробнее — в главе «Wide Events и Observability 2.0».

Если коротко: вместо трёх разных типов данных с разными SDK лучше иметь одно широкое событие со всем контекстом. OpenTelemetry в новых релизах движется именно туда — концепция Log + Span объединяется.

Что делать с существующими инструментами

Если у вас уже есть Prometheus + Jaeger + Loki, переезжать на OpenTelemetry не обязательно. OTel Collector может работать как прослойка: принимать OTLP от новых сервисов, читать Prometheus exposition формат от старых, и экспортировать всё в существующие backend-ы.

Поэтому типичная стратегия миграции: - Новые сервисы — пишутся с OTel SDK с первого дня - Старые сервисы — продолжают работать как раньше (Prometheus pull, Jaeger SDK) - Collector — становится единой точкой, куда сходятся все потоки - Backend-ы — можно менять постепенно, не трогая код

Практический пример: Python-сервис

from opentelemetry import trace, metrics
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
from opentelemetry.sdk.resources import Resource

# Контекст, который прикрепится ко всем сигналам
resource = Resource.create({
    "service.name": "payment-api",
    "service.version": "1.4.2",
    "deployment.environment": "production",
})

trace.set_tracer_provider(TracerProvider(resource=resource))
metrics.set_meter_provider(MeterProvider(resource=resource))

tracer = trace.get_tracer(__name__)
meter = metrics.get_meter(__name__)

# Метрика
request_counter = meter.create_counter(
    "http.server.requests",
    description="Количество HTTP-запросов"
)

# Трейс
with tracer.start_as_current_span("process_payment") as span:
    span.set_attribute("payment.amount", 100)
    span.set_attribute("payment.currency", "RUB")
    # ... бизнес-логика ...
    request_counter.add(1, {"http.method": "POST", "http.route": "/pay"})

Дальше эти сигналы уходят в OTel Collector → в Prometheus + Jaeger. Код ничего не знает про backend-ы.

Сравнение с альтернативами

Инструмент Что делает Отличие от OTel
Prometheus client Метрики Вендор-специфичный, pull-модель
Jaeger SDK Трейсы Только трейсы, свой протокол
StatsD Метрики Устаревший, push-модель
Datadog APM Метрики + трейсы Проприетарный, vendor lock-in
OpenTelemetry Все три сигнала Открытый стандарт, vendor-agnostic

OpenTelemetry не заменяет backend-ы — он заменяет SDK, через которые приложение отправляет данные в эти backend-ы.

Когда НЕ нужен OpenTelemetry

  • Простой монорепо с одной командой — можно обойтись нативными инструментами фреймворка
  • Legacy без миграций в планах — переписывать SDK ради переезда на стандарт нет смысла
  • Если уже есть зрелая обвязка (Datadog APM, New Relic) — её SDK тоже неплохие, и менять ради стандарта нет причин
  • Маркетинговая гонка за «современным стеком» — OTel не самоцель, а средство

Резюме

OpenTelemetry — это открытый стандарт для инструментации приложений: единый SDK для метрик, логов и трейсов, единый протокол (OTLP), единый агент (Collector), единые семантические конвенции. В 2026 это де-факто выбор для новых проектов и стратегия миграции для существующих.

Не нужно переписывать всё за выходные. Начните с того, что новые сервисы пишутся с OTel SDK, а Collector становится единой точкой сбора телеметрии. Старые сервисы продолжают работать как раньше — через Pull-модель Prometheus или свой SDK. Со временем доля OTel будет расти, и в какой-то момент смена backend-а станет делом конфигурации, а не переписывания.

См. также: «Телеметрия», «Wide Events и Observability 2.0», «SLO как код», «OpenSLO: декларативный стандарт для SLO».