Collector — швейцарский нож телеметрии: единая точка приёма, обработки и маршрутизации. Большинство прод-фич трассировки (tail sampling, фильтрация PII, резервные маршруты) живут именно здесь.
Модель: receivers → processors → exporters
# otel-collector-config.yaml
receivers:
otlp:
protocols:
grpc: { endpoint: 0.0.0.0:4317 }
http: { endpoint: 0.0.0.0:4318 }
processors:
memory_limiter:
check_interval: 1s
limit_percentage: 75
spike_limit_percentage: 15
tail_sampling: # подробно — урок 5.2
decision_wait: 10s
num_traces: 50000
policies:
- name: errors
type: status_code
status_code: { status_codes: [ERROR] }
- name: slow
type: latency
latency: { threshold_ms: 1000 }
- name: base
type: probabilistic
probabilistic: { sampling_percentage: 5 }
batch:
send_batch_size: 1024
timeout: 5s
exporters:
otlp/jaeger:
endpoint: jaeger:4317
tls: { insecure: true }
debug: {} # печатает в лог (для отладки)
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, tail_sampling, batch]
exporters: [otlp/jaeger]
Ключевые процессоры
| Процессор | Зачем |
|---|---|
batch | агрегация в батчи — экономия сети и записи; почти всегда последний в цепочке |
memory_limiter | защита самого Collector от OOM; первым в цепочке |
tail_sampling | решение по завершённому трейсу (урок 5.2) |
attributes / resource | добавить/удалить/переписать атрибуты: PII, нормализация имён сервисов |
transform | OTTL-скрипты: маскирование значений, вычисления |
filter | выбросить шумные спаны (healthchecks, роботы) |
k8sattributes | обогащение спанов pod/namespace/owner из Kubernetes |
Как деплоят Collector
- Agent (sidecar/daemonset) — рядом с приложением: приём по localhost, кэш, отправка дальше. Разрывает связку «приложение ↔ бэкенд»;
- Gateway (deployment/service) — централизованный пул: tail sampling, обогащение, маршрутизация. Масштабируется независимо;
- Классическая прод-схема: agent (легкий: приём+batch) → gateway (тяжёлый: sampling, enrichment, routing) → Jaeger.
💡 Collector даёт главную развязку: смена хранилища трейсов не требует изменения ни одного приложения. Все смотрят на gateway, а он перенастраивается на новый бэкенд.
Надёжность и потери
- Очередь отправки и
retry_on_failureу экспортёров: переживают краткие паузы бэкенда; - При полном отказе приёмника данные теряются (in-memory) — для гарантированной доставки ставят exporter → Kafka (урок 3.4);
- Лимиты:
memory_limiter+ лимиты входа; полезно мониторитьotelcol_exporter_send_failed_*— счётчик потерь.
Практика
- Поднимите Collector между SDK и Jaeger (docker-compose): приложение шлёт в Collector, Collector — в Jaeger. Проверьте полный путь в UI.
- Добавьте
filter: выкинуть спаны healthcheck-ов (/health) — убедитесь, что они исчезли из UI. - Добавьте
attributes-процессор: удалите атрибутdb.statement(имитация PII-политики) и проверьте в UI. - Сломайте экспорт (неверный endpoint) — посмотрите метрики Collector и поведение очереди.
Мини-квиз
1. Почему memory_limiter стоит первым, а batch — последним? — Сначала защититься от всплесков входа; батчить — уже обработанное перед отправкой.
2. Зачем два уровня Collector? — Agent — близко к приложениям (надёжный приём), gateway — централизованные тяжёлые операции и маршрутизация.
3. Что произойдёт с трейсами при падении Collector? — SDK примет отказ, не блокируя приложение; данные потеряются, если нет Kafka-буфера.