linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Уроки
  • How it works
  • Симулятор
  • База знаний
  • Собеседование
Index
Categories
All entries
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
home/linux/kb/Observability и мониторинг/opentelemetry

kb/observability ── Observability и мониторинг ── intermediate

OpenTelemetry: signals, OTLP, Collector pipeline

OpenTelemetry - CNCF-стандарт для metrics+traces+logs в одном SDK. OTLP протокол (gRPC или HTTP). Collector принимает, фильтрует, роутит в Prom/Tempo/Loki/Jaeger. Auto-instrumentation без code change.

view as markdownaka: otel, opentelemetry-sdk, otlp, otel-collector

Зачем OpenTelemetry

До OTel у каждого vendor свой SDK:

  • Prometheus client для metrics
  • Jaeger / Zipkin client для traces
  • Datadog APM agent для всего, но vendor lock
  • structured logger для logs

4 SDK, 4 пайплайна, 4 формата. Поменять backend = переписать всю instrumentation в коде.

OpenTelemetry (CNCF, 2019, объединение OpenCensus + OpenTracing) даёт:

  • Один SDK на все три signals (metrics+traces+logs)
  • Один протокол OTLP (OpenTelemetry Line Protocol)
  • Один Collector для трансформации/роутинга
  • Vendor-neutral: код не знает куда летит, в Prom, Datadog или cloud monitoring. Меняй backend через config.

В 2025 OTel, де-факто стандарт для новых проектов. Old Prometheus client всё ещё работает (OTel Collector умеет принимать), но новый код пишут на OTel.

Три signal'а

Traces (tracing-basics), request flow через сервисы. Span'ы с parent-child связями, context propagation через [[http2-internals|traceparent header]].

Metrics, counter, gauge, histogram. Семантика та же что в [[metric-types|Prometheus]], но через OTel SDK.

Logs, structured events с автоматической correlation: trace_id и span_id вшиваются в log record.

Все три едут одним SDK через один OTLP-канал. Это уменьшает coupling и даёт coherence.

Архитектура

┌──────────────┐     OTLP gRPC :4317       ┌─────────────┐
│     App      │ ──────────────────────►   │  Collector  │
│ ┌──────────┐ │     OTLP HTTP :4318       │             │
│ │ OTel SDK │ │                           │ ┌─────────┐ │
│ │ ┌──────┐ │ │                           │ │receivers│ │
│ │ │tracer│ │ │                           │ ├─────────┤ │
│ │ │meter │ │ │                           │ │processor│ │
│ │ │logger│ │ │                           │ ├─────────┤ │
│ │ └──────┘ │ │                           │ │exporters│ │
│ └──────────┘ │                           │ └────┬────┘ │
└──────────────┘                           └──────┼──────┘
                                                  │
                                ┌─────────┬───────┼────────┬────────┐
                                ▼         ▼       ▼        ▼        ▼
                            Prometheus  Tempo   Loki    Jaeger   Datadog

OTLP, протокол

OTLP, единый wire-format. Два транспорта:

ТранспортПорт (default)Когда
gRPC4317server-to-server, internal, low-latency
HTTP/protobuf4318через прокси, browser, restrictive net

Payload, Protocol Buffers. Структура:

ResourceSpans
  ├── Resource (service.name, host.name, k8s.pod.name)
  └── ScopeSpans
      ├── InstrumentationScope (library name + version)
      └── Span[]
          ├── trace_id, span_id, parent_span_id
          ├── name, start_time_nano, end_time_nano
          ├── attributes (key-value)
          ├── events[]
          ├── links[]
          └── status (OK / ERROR)

Аналогично для metrics (ResourceMetrics → ScopeMetrics → Metric) и logs (ResourceLogs → ScopeLogs → LogRecord).

Преимущества над Prom format:

  • Binary, компактнее в 3-5×
  • Streaming через [[grpc-basics|gRPC]] (без http poll)
  • Один формат для трёх signal'ов

SDK: auto vs manual instrumentation

Auto-instrumentation, agent патчит библиотеки runtime, без изменений кода:

  • Java: -javaagent:opentelemetry-javaagent.jar, патчит JDBC, Servlet, Kafka client, gRPC, ~120 библиотек
  • Python: opentelemetry-instrument python app.py, патчит requests, Flask, Django, psycopg2, redis-py
  • Node.js: --require @opentelemetry/auto-instrumentations-node
  • Go: нет рефлексии → нужно добавить вручную (eBPF-based agent в работе)
  • .NET: OTEL_DOTNET_AUTO_HOME env

Получаешь traces для HTTP/DB/Kafka без единой строки кода. Дальше можно дописать manual span'ы для бизнес-логики.

Manual instrumentation, explicit API:

python
from opentelemetry import trace, metrics
tracer = trace.get_tracer(__name__)
meter = metrics.get_meter(__name__)
request_counter = meter.create_counter("requests")
duration_histogram = meter.create_histogram("request_duration_ms")
@app.get("/checkout")
def checkout():
    with tracer.start_as_current_span("checkout") as span:
        span.set_attribute("user.id", user_id)
        request_counter.add(1, {"endpoint": "/checkout"})
        # ... business logic

OTel Collector

Standalone сервис, deploy в каждом узле (DaemonSet) или gateway per-cluster.

Конфиг, три секции:

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:                    # batches before exporting
    send_batch_size: 8192
    timeout: 200ms
  memory_limiter:           # backpressure
    limit_mib: 512
  tail_sampling:            # sample by trace condition
    policies:
      - name: errors
        type: status_code
        status_code: {status_codes: [ERROR]}
      - name: slow
        type: latency
        latency: {threshold_ms: 1000}
      - name: probabilistic-1pct
        type: probabilistic
        probabilistic: {sampling_percentage: 1}
exporters:
  prometheusremotewrite:
    endpoint: http://victoriametrics:8480/api/v1/write
  otlp/tempo:
    endpoint: tempo:4317
    tls:
      insecure: true
  loki:
    endpoint: http://loki:3100/loki/api/v1/push
service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, tail_sampling, batch]
      exporters: [otlp/tempo]
    metrics:
      receivers: [otlp, prometheus]
      processors: [memory_limiter, batch]
      exporters: [prometheusremotewrite]
    logs:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [loki]

Pipeline, ациклический граф. Один collector может обслуживать все три signal'а независимо.

Resource, что описывает источник

Resource, атрибуты процесса/хоста, общие для всех signal'ов:

service.name=checkout
service.version=1.4.2
service.instance.id=checkout-7f8b9c
k8s.namespace.name=prod
k8s.pod.name=checkout-7f8b9c-q2lx9
host.name=node-12.us-east
cloud.provider=aws
cloud.region=us-east-1

Установить через env:

OTEL_SERVICE_NAME=checkout
OTEL_RESOURCE_ATTRIBUTES=service.version=1.4.2,deployment.environment=prod

Auto-injected в k8s через [[opentelemetry-operator-k8s|OTel Operator]] (sidecar/auto-instrumentation CRD).

OTel vs Prometheus client

АспектProm clientOTel SDK
Signalsmetrics onlymetrics+traces+logs
TransportHTTP pull (/metrics)OTLP push
Vendor neutralityProm-onlyлюбой backend
Auto-instrumentationminimalполный
Adoptionширочайшаярастёт быстро
Wire formattext/OpenMetricsprotobuf

Можно совместить: OTel SDK для traces+logs + Prom client для metrics. Или OTel SDK для всего, а Collector экспортит metrics в Prom format.

Sampling, head vs tail

100% traces неподъёмны: 10K req/s × 5 spans × 5KB = ~250 MB/s. Sampling нужен.

  • Head-based: решение sample-or-drop в начале трассы (на edge), все downstream спаны соблюдают. Просто и предсказуемо. Минус рандомно роняет error traces.
  • Tail-based: собрать всю трассу в Collector, потом решить keep/drop по trace properties (status, latency, attributes). Видим все ошибки, но Collector держит все spans в памяти на 5-30s.

Tail-based предпочтительно. Tail Sampling Processor в Collector.

Когда что-то пошло не так

  • OTLP/gRPC connection refused, Collector не запущен или другой port. Default 4317. Проверь firewall.
  • Trace отсутствует, хотя ошибка, head sampling 1% уронил. Используй tail sampling с status_code: ERROR policy.
  • Collector OOM, memory_limiter processor отсутствует или лимит выше RAM. Добавь limit < 80% от container memory.
  • Cardinality explosion, attributes в metrics с user-id или request-id. См. cardinality-explosion.
  • Auto-instrumentation сломала app, обычно Java agent + конфликт байткод-патча. Поднимай OTel agent версию или disable конкретный instrumentation: OTEL_INSTRUMENTATION_<name>_ENABLED=false.
  • Span.attributes теряются, забыт batch processor, или attributes добавлены после end(). Set до .end().
  • Service.name = "unknown_service" в Tempo, забыт env OTEL_SERVICE_NAME. Resource не сконфигурен.

OTel vs Datadog/New Relic

Vendor APMs (Datadog, New Relic, Splunk) дают всё-в-одном с UI и ML-features. Но vendor lock, заменить = переписать.

С OTel пишешь instrumentation один раз, отправляешь в Datadog через native receiver. Через год, переключаешь exporter на Tempo/Loki/Mimir, код не трогаешь.

Cost-aware: OTel + self-hosted (Tempo+Loki+VictoriaMetrics) дешевле Datadog в 5-10× при ≥100 GB/day, но требует ops-инвестиций.

§ команды

bash
opentelemetry-instrument --service_name=myapp python app.py

Auto-instrumentation для Python - HTTP, DB, Kafka traces без кода

bash
java -javaagent:opentelemetry-javaagent.jar -Dotel.service.name=myapp -jar app.jar

Java auto-agent - патчит JDBC, Servlet, gRPC и ~120 библиотек на старте

bash
otelcol --config=/etc/otelcol/config.yaml

Запуск Collector. Логи покажут ошибки конфига и pipeline-проблемы

bash
curl -X POST -H 'Content-Type: application/x-protobuf' --data-binary @trace.pb http://collector:4318/v1/traces

Manual OTLP HTTP push - для отладки или CI-тестов

bash
OTEL_TRACES_EXPORTER=console python -c 'import myapp'

Debug-режим: traces в stdout вместо отправки. Видишь span structure

bash
otelcol validate --config=/etc/otelcol/config.yaml

Проверка конфига Collector без запуска - в CI

bash
curl -s localhost:13133/  # health check

OTel Collector health endpoint - 200 если pipeline ОК, 503 если backpressure

§ см. также

  • tracing-basicsDistributed tracing: span, context propagation, samplingTracing - граф spans (parent-child) одного логического запроса через сервисы. Context передаётся HTTP-header traceparent (W3C). Sampling: head (на edge, дёшево) или tail (в Collector, точнее). Backend: Jaeger, Tempo, Zipkin.
  • prometheus-basicsPrometheus: scrape, TSDB, PromQL и production-pitfallsPrometheus - сервер мониторинга: сам опрашивает приложения по HTTP, собирает числовые метрики, хранит во встроенной БД ~15 дней. По ним строят графики в Grafana и алерты через Alertmanager. Стандарт de-facto в Kubernetes.
  • metric-typesТипы метрик: counter, gauge, histogram, summary4 типа метрик: counter (только вверх), gauge (любое значение), histogram (buckets для p99), summary (quantile в клиенте). Native histogram (Prom 2.40+) - sparse buckets, аккуратнее по памяти. Exemplars связывают метрику с trace_id.
  • grpc-basicsgRPC - HTTP/2 + Protobuf RPC frameworkgRPC = HTTP/2 + Protocol Buffers + кодогенерация. Четыре типа RPC: unary (как REST), server-stream, client-stream, bidirectional. Сильная типизация, бинарный wire format, multi-language. grpcurl как curl для gRPC.
  • http2-internalsHTTP/2 internals - binary framing, HPACK, stream multiplexingHTTP/2 - бинарный мультиплексинг поверх одного TCP-соединения. HPACK сжимает headers через индексированный словарь. Streams независимы. Server push deprecated. На loss-friendly link HoL-blocking - проблема, которую решил QUIC.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки