GH GambleHub

Distributed Tracing: OpenTelemetry

Distributed Tracing: OpenTelemetry

1) Зачем OTel и что он дает

OpenTelemetry (OTel) — открытый стандарт и набор SDK/агентов/коллекторов для телеметрии (трейсы, метрики, логи) с единым протоколом OTLP. Цели:
  • Сквозная видимость путей запроса (gateway → сервисы → БД/кэш/очереди).
  • Быстрая RCA/отладка деградаций и релизов (канареек/blue-green).
  • Связка с SLO и авто-откатами (операционные решения на данных).
  • Вендор-агностичность: экспорт в любой бэкенд, без привязки к одному APM.

Опорные принципы: standardize, sample smart, secure by default, correlate everything.

2) Основы: контекст, спаны, атрибуты

Trace — дерево/граф вызовов; Span — операция (RPC, SQL, вызов очереди).
Span Kind: `SERVER`, `CLIENT`, `PRODUCER`, `CONSUMER`, `INTERNAL`.
W3C Trace Context: заголовки `traceparent`, `tracestate`; контекст переносится межсервисно.
Attributes — ключ-значение (низкая кардинальность!), Events — метки во времени, Status — код/описание ошибки.
Links — связь спанов вне строгой иерархии (важно для async/fan-out/fan-in).

Именование спанов:
  • HTTP: `HTTP {METHOD}` (`GET /withdraw` как атрибут)
  • DB: `DB SELECT` / `DB INSERT`
  • Queue: `QUEUE publish topic=X` / `QUEUE consume topic=X`

3) Семантические конвенции (semconv)

Используйте стабильные схемы атрибутов:
  • HTTP/GRPC: `http.method`, `http.route`, `http.status_code`, `url.full`.
  • DB: `db.system=postgresql`, `db.statement` (только безопасная выжимка!), `db.name`.
  • Messaging: `messaging.system=kafka`, `messaging.operation=receive`, `messaging.destination`.
  • Cloud/K8s/Host: `cloud.region`, `k8s.pod.name`, `container.id`.
  • Resource attributes (обязательно): `service.name`, `service.version`, `deployment.environment`.

Стабильность схемы указывайте через `schemaUrl` в ресурсах SDK/Collector.

4) Сэмплинг: head, tail, adaptive

Head-based (в SDK): решает заранее, дешево; хорошо для high-QPS, но может пропустить «интересные» трассы.
Tail-based (в Collector): решает после завершения трассы; позволяет правила по статусу, латентности, атрибутам.
Adaptive/Динамический: поднимает долю сэмпла при ошибках/росте p95.

Рецепт прод-уровня: Head 1–5% глобально + Tail отбор «важного»: `status=ERROR`, `latency>p95`, «денежные маршруты», ошибки PSP/KYC.

5) Корреляция: метрики, логи, трейсы

Exemplars: метки с `trace_id` в гистограммах метрик (быстрый прыжок к трассе).
Логи: добавляйте `trace_id`/`span_id` и переключайтесь из логов в трассу.
SpanMetrics (processor): агрегирует из трасс RED-метрики (`requests, errors, duration`) для SLO/алертов.

6) Архитектура развертывания

Agent (DaemonSet) на каждом узле собирает из приложений (OTLP) и форвардит.
Gateway (Cluster/Region) — центральный Collector (много реплик) с пайплайнами маршрутизации/сэмплинга/обогащения.
OTLP: gRPC `4317`, HTTP `4318`; включайте TLS/mTLS.

Плюсы «agent+gateway»: изоляция, буферизация, локальный backpressure, упрощенная сеть.

7) OpenTelemetry Collector — базовый шаблон (gateway)

yaml receivers:
otlp:
protocols:
grpc: { endpoint: 0. 0. 0. 0:4317 }
http: { endpoint: 0. 0. 0. 0:4318 }

processors:
memory_limiter: { check_interval: 5s, limit_percentage: 75 }
batch: { timeout: 2s, send_batch_size: 8192 }
attributes:
actions:
- key: deployment. environment action: upsert value: prod resource:
attributes:
- key: service. namespace action: upsert value: core tail_sampling:
decision_wait: 5s policies:
- name: errors type: status_code status_code: { status_codes: [ERROR] }
- name: slow_traces type: latency latency: { threshold_ms: 800 }
- name: important_routes type: string_attribute string_attribute:
key: http. route values: ["/withdraw", "/deposit"]
- name: baseline_prob type: probabilistic probabilistic: { sampling_percentage: 5 }

exporters:
otlp/apm:
endpoint: apm-backend:4317 tls: { insecure: true }
prometheus:
endpoint: 0. 0. 0. 0:9464

extensions:
health_check: {}
pprof: { endpoint: 0. 0. 0. 0:1777 }
zpages: { endpoint: 0. 0. 0. 0:55679 }

service:
extensions: [health_check, pprof, zpages]
pipelines:
traces:  { receivers: [otlp], processors: [memory_limiter,attributes,resource,batch,tail_sampling], exporters: [otlp/apm] }
metrics: { receivers: [otlp], processors: [batch], exporters: [prometheus] }
logs:   { receivers: [otlp], processors: [batch], exporters: [] }

8) SpanMetrics и RED для SLO

Добавьте процессор:
yaml processors:
spanmetrics:
metrics_exporter: prometheus histogram:
explicit:
buckets: [50ms,100ms,200ms,400ms,800ms,1600ms,3200ms]
service:
pipelines:
traces: { receivers: [otlp], processors: [spanmetrics,batch,tail_sampling], exporters: [otlp/apm] }
metrics: { receivers: [otlp], processors: [batch], exporters: [prometheus] }

Теперь есть `traces_spanmetrics_calls{service,route,code}` и `duration_bucket` для SLO/алертов.

9) K8s: развертывание Collector (DaemonSet + Deployment)

Agent (DaemonSet) фрагмент:
yaml apiVersion: apps/v1 kind: DaemonSet metadata: { name: otel-agent, namespace: observability }
spec:
template:
spec:
containers:
- name: otelcol image: otel/opentelemetry-collector:latest args: ["--config=/conf/agent. yaml"]
ports:
- { containerPort: 4317, name: otlp-grpc }
- { containerPort: 4318, name: otlp-http }

Gateway (Deployment) — несколько реплик, Service ClusterIP/Ingress, HPA по CPU/QPS.

10) Безопасность и приватность

TLS/mTLS между SDK → Agent → Gateway → Backend.
Аутентификация (Basic/OAuth/Headers) на входе Gateway; ограничивайте истоки.
Редакция PII: фильтруйте/маскируйте атрибуты (`user.email`, `card.`) в процессоре Collector.
Лимиты: в SDK ограничьте размер события/число атрибутов (защита от кардинальности).
RBAC в бэкенде + отдельные неймспейсы проектов/тенантов.

Пример фильтра в Collector:
yaml processors:
attributes/redact:
actions:
- key: user. email action: delete
- key: payment. card action: delete

11) Инструментирование: быстрые старты

Node.js

js import { NodeSDK } from "@opentelemetry/sdk-node";
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-grpc";
import { Resource } from "@opentelemetry/resources";
import { SemanticResourceAttributes as R } from "@opentelemetry/semantic-conventions";

const sdk = new NodeSDK({
traceExporter: new OTLPTraceExporter({ url: "http://otel-agent. observability:4317" }),
resource: new Resource({
[R.SERVICE_NAME]: "payments-api",
[R.SERVICE_VERSION]: "1. 14. 2",
[R.DEPLOYMENT_ENVIRONMENT]: "prod"
}),
instrumentations: [getNodeAutoInstrumentations()],
});
sdk. start();

Java (Spring)

java
// Gradle: io. opentelemetry. instrumentation:opentelemetry-spring-boot-starter
// application. yml otel:
service:
name: orders-api exporter:
otlp:
endpoint: http://otel-agent. observability:4317 traces:
sampler: parentbased_traceidratio sampler-arg: 0. 05

Python (FastAPI)

python from opentelemetry import trace from opentelemetry. sdk. resources import Resource from opentelemetry. exporter. otlp. proto. grpc. trace_exporter import OTLPSpanExporter from opentelemetry. sdk. trace import TracerProvider from opentelemetry. sdk. trace. export import BatchSpanProcessor

provider = TracerProvider(resource=Resource. create({"service. name":"fraud-scoring","deployment. environment":"prod"}))
provider. add_span_processor(BatchSpanProcessor(OTLPSpanExporter(endpoint="http://otel-agent. observability:4317", insecure=True)))
trace. set_tracer_provider(provider)

Go

go exp, _:= otlptracegrpc. New(ctx, otlptracegrpc. WithEndpoint("otel-agent. observability:4317"), otlptracegrpc. WithInsecure())
res:= resource. NewWithAttributes(semconv. SchemaURL, semconv. ServiceNameKey. String("gateway"), semconv. DeploymentEnvironmentKey. String("prod"))
tp:= sdktrace. NewTracerProvider(sdktrace. WithBatcher(exp), sdktrace. WithResource(res), sdktrace. WithSampler(sdktrace. ParentBased(sdktrace. TraceIDRatioBased(0. 05))))
otel. SetTracerProvider(tp)

12) Асинхронщина: очереди, шины, cron

PRODUCER/CONSUMER со связью через `links` (у сообщений свой жизненный цикл).
Пропагируйте контекст в заголовки сообщений (`traceparent`/`baggage`).
При batch-consume создавайте по спану на сообщение или агрегируйте с атрибутом `messaging.batch.size`.
Для cron/джобов: новый trace на запуск + links к первичным событиям (если есть).

13) Baggage и таргетинг

Храните минимум стабильных ключей (`tenant_id`, `region`, `vip_tier`) в baggage; запрещайте PII.
Пробрасывайте через gateway/gateway-логгер для последующей агрегации метрик по сегментам.

14) Интеграция с релизами и SLO-гейтингом

Канареечные шаги → проверяйте `traces_spanmetrics_` по маршрутам/юз-сегментам.
При деградации (5xx/p95) — авто-стоп и откат (Argo Rollouts AnalysisTemplate + PromQL).
Экземпляры из метрик ведут напрямую в «плохие» трассы релизного интервала.

15) Лимиты и производительность

Ограничивайте: `OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT`, `OTEL_SPAN_EVENT_COUNT_LIMIT`, `OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT`.
Сэмплируйте исключения/stacktrace по вероятности/частоте.
Batch-процессор в SDK и Collector; держите очереди, чтобы не терять трассы при всплесках.

16) Совместимость и миграции

Пропагаторы: используйте W3C; поддержите чтение B3/X-Ray при миграции (dual-propagation).
Экспорт: OTLP → APM (Jaeger/Tempo/Elastic/X-Ray и т. п.).
Стабильные версии semconv — фиксируйте `schemaUrl` и планируйте апгрейды.

17) Анти-паттерны

Высокая кардинальность атрибутов (`user_id` в label, динамические ключи).
Логи без `trace_id` → нет корреляции.
Экспорт напрямую из приложений в интернет-APM (без gateway, без TLS/mTLS).
Сбор «всего» 100% в проде — дорого и бессмысленно.
Дампы SQL-запросов с данными пользователя в `db.statement`.
Несогласованное имя сервиса/версии — метрики «рассыпаются».

18) Чек-лист внедрения (0–45 дней)

0–10 дней

Включить SDK/автоинструментирование на 2–3 критичных сервисах.
Настроить Agent (DaemonSet) + Gateway (Deployment), OTLP 4317/4318 с TLS.
Добавить `service.name`, `service.version`, `deployment.environment` повсюду.

11–25 дней

Tail-sampling по ошибкам/латентности/«денежным» маршрутам.
SpanMetrics → Prometheus, включить Exemplars и дашборды RED/SLO.
Пропагировать W3C через API-шлюз/NGINX/mesh; коррелировать логи.

26–45 дней

Покрыть очереди/БД/кэш; links для async.
Политики PII-редакции в Collector; лимиты атрибутов в SDK.
Интегрировать SLO-гейтинг релизов и авто-откат.

19) Метрики зрелости

Покрытие входящих запросов трассировкой ≥ 95% (с учетом sampling head/tail).
Доля метрик с Exemplars ≥ 80%.
Время RCA «из метрики в трассу» ≤ 2 мин (p50).
0 утечек PII в атрибутах/событиях (сканер).
Все сервисы имеют `service.name/version/environment` и согласованную семантику.

20) Приложения: полезные фрагменты

NGINX пропагация:
nginx proxy_set_header traceparent $http_traceparent;
proxy_set_header tracestate $http_tracestate;
proxy_set_header baggage   $http_baggage;
Prometheus с Exemplars (Grafana):

histogram_quantile(0. 95, sum(rate(traces_spanmetrics_duration_bucket{route="/withdraw"}[5m])) by (le))

Policy: запрет PII-атрибутов (псевдо-линтер)

yaml forbid_attributes:
- user. email
- payment. card
- personal.

21) Заключение

OpenTelemetry превращает наблюдаемость в стандартизированный, управляемый контур: единая семантика, безопасная пропагация, умный сэмплинг и сильная корреляция с метриками и логами. Выстраивайте agent+gateway, добавляйте tail-sampling, spanmetrics и Exemplars, следите за PII и кардинальностью — и трассировка станет инструментом не только для отладки, но и для автоматизированных решений SRE/Release, сокращая MTTR и риски при каждом релизе.

Contact

Свяжитесь с нами

Обращайтесь по любым вопросам или за поддержкой.Мы всегда готовы помочь!

Telegram
@Gamble_GC
Начать интеграцию

Email — обязателен. Telegram или WhatsApp — по желанию.

Ваше имя необязательно
Email необязательно
Тема необязательно
Сообщение необязательно
Telegram необязательно
@
Если укажете Telegram — мы ответим и там, в дополнение к Email.
WhatsApp необязательно
Формат: +код страны и номер (например, +380XXXXXXXXX).

Нажимая кнопку, вы соглашаетесь на обработку данных.