awesome-everything EN
↑ Обратно к восхождению

Наблюдаемость

Авто-инструментирование и ручные спаны: правило 80/20 в OTel

Суть Авто-инструментирование покрывает 70-80% production-трафика бесплатно — HTTP, БД, очереди. Оставшиеся 20-30% — ручные спаны с бизнес-атрибутами, и именно здесь живёт настоящая диагностическая ценность.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на middle-высоте — в небе
◷ 11 min

Авто-инструментирование говорит вам: “этот HTTP-запрос занял 800 мс и сделал 5 запросов в БД.” Ручное инструментирование говорит: “медленной частью был цикл проверки мошенничества, который разветвился на 12 вызовов движка правил, из которых 3 завершились таймаутом.” Оба необходимы. Ни одного в отдельности недостаточно.

Авто-инструментирование: 70-80%, которые вы получаете бесплатно

Большая часть production-трафика проходит через небольшой набор фреймворков — HTTP-серверы, HTTP-клиенты, драйверы БД, клиенты очередей — которые contrib-библиотеки OTel инструментируют из коробки.

Java: OTel Java Agent (-javaagent JAR) перезаписывает байткод при старте JVM и автоматически инструментирует ~200 библиотек — никаких изменений кода не требуется. Добавьте один флаг -javaagent к JVM-аргументам, задайте переменные окружения OTEL_SERVICE_NAME и OTEL_EXPORTER_OTLP_ENDPOINT, и каждый HTTP-запрос, JDBC-запрос и Kafka-сообщение будет трассирован.

Python: opentelemetry-instrument оборачивает процесс и monkey-patching применяет изменения к популярным библиотекам (Flask, Django, FastAPI, SQLAlchemy, Redis, Celery и др.).

Node.js: @opentelemetry/sdk-node плюс набор инструментаций (express, http, pg, redis, kafkajs), зарегистрированных до любых других импортов через require hook.

Go: Авто-инструментирование менее зрелое, поскольку в Go нет monkey-patching. Авто-инструментирование на основе eBPF (через uprobes) — развивающийся подход; contrib-библиотеки OTel для Go требуют явной настройки middleware для каждого фреймворка.

ЯзыкМеханизм авто-инструментированияПокрытие
Java-javaagent JAR, перезапись байткода при старте~200 библиотек: HTTP + БД + очереди + кэши
Pythonopentelemetry-instrument, monkey-patchingFlask, Django, FastAPI, SQLAlchemy, Redis, Celery
Node.jsrequire hook до других импортовexpress, http, pg, redis, kafkajs, grpc
GoНастройка middleware вручную (нет monkey-patching)net/http, gRPC, database/sql — требует ручной интеграции

70-80% — простая часть: HTTP-маршруты, запросы в БД, вызовы кэша, взаимодействие с очередями. Авто-инструментирование говорит вам что произошло. Ручное инструментирование говорит почему.

Ручное инструментирование: мост к диагностической ценности

Оставшиеся 20-30% — бизнес-специфичные спаны, кастомные атрибуты и сквозные концерны — здесь живёт настоящая диагностическая ценность, потому что именно здесь живут бизнес-вопросы.

Паттерн: откройте спан вокруг бизнес-операции, прикрепите атрибуты, описывающие операцию, и генерируйте span events для значимых моментов.

const span = tracer.startSpan("fraud.check", {
  attributes: {
    "customer.segment": customer.segment,
    "order.value_cents": order.valueCents,
    "feature_flag.fraud_model": flags.fraudModel,
  },
});

try {
  for (const rule of rules) {
    const result = await rules.engine.evaluate(rule, order);
    span.addEvent("rule.evaluated", {
      "rule.id": rule.id,
      "rule.result": result.outcome,
      "rule.latency_ms": result.latencyMs,
    });
  }
} catch (err) {
  span.recordException(err);
  span.setStatus({ code: SpanStatusCode.ERROR });
} finally {
  span.end();
}

Этот спан сообщает о сегменте клиента, стоимости заказа, состоянии фича-флага модели проверки мошенничества и результате каждой оценки правила — данные, которые авто-инструментирование не может видеть, поскольку не знает вашего бизнес-домена.

Паттерн платформенной обёртки

Ручное инструментирование — это один и тот же паттерн во всех сервисах, поэтому платформенные команды публикуют тонкую вспомогательную библиотеку, оборачивающую OTel API с организационными конвенциями:

  • Типизированные бизнес-атрибуты — предопределённые имена атрибутов для общих концептов (сегмент клиента, состояние фича-флага, размер батча), чтобы команды не могли сделать опечатки.
  • Хелперы редактирования — удаление PII перед прикреплением к спанам (email → хэш, SSN → маска).
  • Хелперы span events — типизированные хелперы для типовых событий (cache miss, retry, fallback).
  • Предварительная конфигурация Resource — имя сервиса, версия и окружение развёртывания из стандартизированного набора переменных окружения.

Новые сервисы импортируют обёртку; CI-линтер отклоняет прямое использование OTel SDK в новом коде (для предотвращения неконтролируемых имён атрибутов). Хуки переопределения позволяют командам добавлять специфичные для сервиса атрибуты без изменения обёртки.

Почему это работает

Почему не один спан на функцию? Каждый спан имеет накладные расходы: SDK выделяет структуру спана, записывает атрибуты, запускает семплер, а при завершении спана — запускает batch processor, сериализует в OTLP и, возможно, помещает в очередь экспортёра. При ~1-5 мкс на спан, 100 спанов на запрос при 10к RPS — это 1-5 мс накладных расходов CPU на ядро в секунду. Что важнее, плоский список из 100 спанов на уровне функций читается хуже, чем 8 спанов на правильном уровне абстракции. Рекомендация: один спан на пересечение границы сервиса плюс один на значимый вызов подсистемы (один спан для проверки мошенничества, один для запроса в БД внутри неё, но не по спану на каждый метод внутри проверки).

Викторина

Что покрывает авто-инструментирование, чего не может ручное, и что покрывает ручное, чего не может авто?

Викторина

Почему платформенная команда публикует языково-специфичную обёртку вокруг OTel SDK вместо того, чтобы позволить продуктовым командам вызывать OTel SDK напрямую?

Расставь шаги по порядку

Упорядочите шаги добавления хорошо инструментированного бизнес-спана в сервис:

  1. 1 Откройте спан с описательным именем операции (например, fraud.check)
  2. 2 Прикрепите структурированные атрибуты: сегмент клиента, стоимость заказа, состояние фича-флага
  3. 3 Выполните бизнес-логику
  4. 4 Генерируйте span events для значимых моментов: cache miss, retry, результат оценки правила
  5. 5 При ошибке: вызовите span.recordException(err) и установите статус ERROR
  6. 6 Всегда вызывайте span.end() в блоке finally для гарантированного сброса спана
Вспомните перед уходом
  1. 01
    Почему OTel Java Agent — наиболее мощный вариант авто-инструментирования среди языков?
  2. 02
    Какова правильная гранулярность ручных спанов и почему?
  3. 03
    Что решает паттерн платформенной обёртки и что он стоит?
Итог

Авто-инструментирование инструментирует 70-80% production-трафика бесплатно: OTel Java Agent перезаписывает байткод для покрытия ~200 библиотек; opentelemetry-instrument в Python применяет monkey-patching к популярным фреймворкам; Node.js использует require-hook до других импортов. Go требует ручной настройки middleware (нет monkey-patching). Оставшиеся 20-30% — ручные спаны: откройте спан вокруг бизнес-операции, прикрепите типизированные атрибуты (сегмент клиента, состояние фича-флага, размер батча), генерируйте span events для значимых моментов, записывайте исключения через span.recordException(). Накладные расходы — ~1-5 мкс на спан; сохраняйте гранулярность на уровне бизнес-операций, а не функций. Платформенные команды публикуют языково-специфичную обёртку, обеспечивающую соблюдение Semantic Conventions, редактирование и конфигурацию resource, чтобы продуктовые команды могли добавлять бизнес-спаны без изобретения новых имён атрибутов.

Связанные уроки
встречается в167
Продолжить восхождение ↑Collector OTel: receivers, processors, exporters и паттерны развёртывания
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.