Skip to content

Latest commit

 

History

History
211 lines (159 loc) · 14.5 KB

File metadata and controls

211 lines (159 loc) · 14.5 KB

OpenTelemetry

Автор: Oleborn

Дата: 23 февраля 2026 г.

Проект: OrderHub

1. Введение

До появления OpenTelemetry (OTel) мир наблюдаемости был фрагментирован. Каждый вендор (Datadog, New Relic, Dynatrace) предлагал свои проприетарные агенты и SDK. Это приводило к "Vendor Lock-in": переезд на другую платформу мониторинга требовал переписывания кода инструментирования во всем приложении.

OpenTelemetry — это проект CNCF (Cloud Native Computing Foundation), который ставит своей целью создание единого, вендор-нейтрального стандарта для сбора трех столпов наблюдаемости: Трассировок (Traces), Метрик (Metrics) и Логов (Logs).

Ключевая концепция: OpenTelemetry — это не бэкенд для хранения данных (как Prometheus или Jaeger). Это стандарт и набор инструментов для генерации, сбора и экспорта данных в любой бэкенд.


2. Архитектура OpenTelemetry

Архитектура OTel состоит из нескольких ключевых компонентов, которые работают вместе для обеспечения полного цикла жизни телеметрии.

2.1. Спецификация (Specification)

Это "сердце" проекта. Она определяет:

  • API: Как разработчик пишет код для создания спанов или метрик.
  • SDK: Реализация API на конкретном языке (Java, Go, Python и т.д.).
  • OTLP (OpenTelemetry Protocol): Протокол передачи данных.
  • Semantic Conventions: Стандартные имена для атрибутов (например, http.method, db.statement).

2.2. Инструментация (Instrumentation)

Существует два подхода к внедрению OTel в приложение:

  1. Автоматическая инструментация (Zero-code): В Java это реализуется через javaagent. Он "на лету" модифицирует байт-код популярных библиотек (Spring, JDBC, Kafka) и начинает генерировать телеметрию без изменения исходного кода.
  2. Ручная инструментация (Manual): Использование SDK напрямую для создания кастомных спанов или метрик, специфичных для бизнес-логики.

2.3. OpenTelemetry Collector

Это промежуточный сервис, который выступает в роли "швейцарского ножа" для телеметрии. Он может принимать данные, обрабатывать их и отправлять в несколько мест одновременно.


3. OpenTelemetry Collector

Collector — это самый мощный компонент системы. Его работа строится на базе Пайплайнов (Pipelines).

3.1. Структура пайплайна

Пайплайн состоит из трех этапов:

  1. Receivers (Приемники): Слушают порты и принимают данные в разных форматах (OTLP, Jaeger, Prometheus, Zipkin).
  2. Processors (Процессоры): Самая интересная часть. Они могут:
    • Batch: Группировать данные для эффективной отправки.
    • Memory Limiter: Предотвращать падение коллектора по OOM.
    • Attributes/Resource: Добавлять, удалять или изменять теги (например, добавить env: production ко всем данным).
    • Sampling: Фильтровать трассировки (например, оставлять только 10% успешных запросов и 100% ошибок).
  3. Exporters (Экспортеры): Отправляют обработанные данные в бэкенды (Prometheus, Jaeger, Elasticsearch, OTLP).

3.2. Пример конфигурации Collector (config.yaml)

receivers:
  otlp:
    protocols:
      grpc:
      http:

processors:
  batch:
  memory_limiter:
    check_interval: 1s
    limit_mib: 1024
  resourcedetection:
    detectors: [env, system]

exporters:
  prometheus:
    endpoint: "0.0.0.0:8889"
  otlp/jaeger:
    endpoint: "jaeger:4317"
    tls:
      insecure: true

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, batch, resourcedetection]
      exporters: [otlp/jaeger]
    metrics:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [prometheus]

Пайплайны — это то, где происходит "магия" обработки данных. Рассмотрим продвинутые техники.

3.3. Процессор transform (OTTF)

OpenTelemetry Transformation Language (OTTF) позволяет менять данные "на лету" без написания кода на Go.

processors:
  transform:
    error_mode: ignore
    trace_statements:
      - context: span
        statements:
          # Удаляем чувствительные данные из тегов
          - delete_key(attributes, "http.request.header.authorization")
          # Добавляем префикс к именам сервисов
          - set(resource.attributes["service.name"], Concat(["prod", resource.attributes["service.name"]], "-"))

3.4. Tail-based Sampling (Умное сэмплирование)

Обычное сэмплирование (Head-based) принимает решение в начале запроса. Tail-based Sampling принимает решение в конце, когда мы уже знаем результат.

  • Кейс: Мы хотим сохранять 100% запросов с ошибками (HTTP 500) и только 1% успешных (HTTP 200).
  • Реализация: Коллектор буферизирует все спаны одного traceId, ждет завершения всей трассы, анализирует её и решает — сохранять или дропнуть.

3.5. Resource Detection

Этот процессор автоматически обогащает телеметрию данными об окружении.

processors:
  resourcedetection:
    detectors: [env, system, gcp, ecs, ec2, azure]
    timeout: 2s
    override: false

Если ваше приложение запущено в AWS EC2, коллектор сам добавит теги cloud.region, host.id, instance.type ко всем метрикам и трассам.


4. Протокол OTLP

OTLP (OpenTelemetry Protocol) — это современный протокол, разработанный специально для высокой производительности.

4.1. Сериализация: Почему Protobuf?

В отличие от JSON, который используется в Zipkin, OTLP использует Protocol Buffers (Protobuf).

  • Бинарный формат: Данные передаются в сжатом виде, что экономит до 70% трафика.
  • Строгая типизация: Ошибки в структуре данных отлавливаются на этапе компиляции, а не в рантайме.
  • Быстрый парсинг: Десериализация Protobuf в 5-10 раз быстрее, чем JSON, что критично для коллекторов, обрабатывающих миллионы спанов в секунду.

4.2. Транспорт: gRPC vs HTTP

OpenTelemetry поддерживает оба варианта, но у каждого свои задачи:

  • gRPC (Порт 4317):
    • Преимущества: Двунаправленный стриминг, мультиплексирование запросов в одном соединении, встроенное сжатие.
    • Использование: Внутренние сети, общение между коллекторами, высоконагруженные сервисы.
  • HTTP/JSON (Порт 4318):
    • Преимущества: Проходит через любые Firewall и Proxy, не требует специальных библиотек (можно отправить curl).
    • Использование: Браузерные приложения (JS), мобильные устройства, среды с ограниченной поддержкой gRPC.

5. Semantic Conventions

Одна из главных проблем мониторинга — разные имена для одних и тех же вещей. Один разработчик пишет user_id, другой uid, третий customer.id.

OpenTelemetry вводит Semantic Conventions — жесткий стандарт именования.

  • http.status_code — всегда код ответа.
  • db.system — тип БД (mysql, postgresql).
  • net.peer.name — адрес удаленного узла.

Зачем это нужно? Это позволяет инструментам визуализации (Grafana) строить универсальные дашборды, которые будут работать для любого приложения, независимо от того, кто его писал.


6. Паттерны развертывания в Kubernetes

В K8s существует три основных способа развертывания Collector:

  1. Sidecar: Коллектор запускается как контейнер внутри каждого Pod'а.
    • Плюсы: Минимальная задержка, изоляция.
    • Минусы: Огромный расход ресурсов (CPU/RAM) на тысячи контейнеров.
  2. DaemonSet: Один коллектор на каждую ноду кластера.
    • Плюсы: Оптимальный баланс ресурсов.
    • Минусы: Если коллектор упадет, вся нода "ослепнет".
  3. Gateway (Deployment): Отдельный кластер коллекторов за балансировщиком.
    • Плюсы: Централизованное управление, агрегация данных, сложная фильтрация.
    • Минусы: Дополнительный сетевой прыжок (hop).

7. OpenTelemetry в Spring Boot 3.x

Spring Boot 3 полностью перешел на Micrometer Tracing, который является фасадом над OpenTelemetry.

Как это работает в OrderHub:

  1. Приложение использует Micrometer API.
  2. В рантайме подключается OpenTelemetry Bridge.
  3. Данные экспортируются по протоколу OTLP в Collector.
  4. Collector распределяет их: метрики в Prometheus, трассы в Jaeger.

Это дает нам "святой грааль" наблюдаемости: Correlation. Мы можем найти медленный запрос в Jaeger, увидеть его traceId и по этому же ID найти все логи этого запроса в Elasticsearch и метрики нагрузки на CPU в этот момент.


8. Correlation: Связываем всё воедино

Главная ценность OpenTelemetry — это Context Propagation.

8.1. Trace Context (W3C)

OTel использует стандарт W3C Trace Context, который состоит из двух заголовков:

  1. traceparent: Содержит traceId и spanId.
  2. tracestate: Содержит вендор-специфичную информацию.

8.2. Baggage

Baggage — это механизм передачи произвольных пар "ключ-значение" через всю цепочку вызовов.

  • Пример: Вы можете положить customer_id в Baggage в первом сервисе, и он автоматически "пролетит" через 10 микросервисов, став доступным в логах и трассах последнего сервиса без явной передачи в аргументах функций.

9. Лучшие практики (Best Practices)

  1. Используйте Collector всегда. Даже если вы отправляете данные в один бэкенд. Коллектор снимает нагрузку с приложения (очереди, ретраи, сжатие) и позволяет менять бэкенд без перезапуска приложения.
  2. Настраивайте Batch Processor. Без него каждый спан будет отправляться отдельным сетевым запросом, что создаст огромный оверхед.
  3. Следите за Cardinality. Не добавляйте динамические данные (например, user_id) в имена метрик. Используйте для этого атрибуты (теги).
  4. Используйте Semantic Conventions. Не придумывайте свои имена для стандартных вещей. Это позволит вам использовать готовые дашборды из Grafana Marketplace.
  5. Настраивайте Health Check. Коллектор должен иметь эндпоинт /health, чтобы Kubernetes мог перезапустить его в случае зависания.