Distributed Tracing: OpenTelemetry
Distributed Tracing: OpenTelemetry
1) Por qué OTel y qué da
OpenTelemetry (OTel) es un estándar abierto y un conjunto de SDK/agentes/colectores para telemetría (tracks, métricas, logs) con un único protocolo OTLP. Objetivos:- Visibilidad end-to-end de las rutas de consulta (gateway → servicios → DB/caché/colas).
- Rápido RCA/depuración de degradaciones y liberaciones (canario/azul-verde).
- Conjunto con SLO y auto-retroceso (soluciones operativas en datos).
- Vendor-agnóstico: exportación a cualquier backend, sin referencia a una APM.
Principios de referencia: standardize, sample smart, secure by default, correlate everything.
2) Fundamentos: contexto, dormir, atributos
Trace - árbol/gráfico de llamadas; Span - operación (RPC, SQL, llamada de cola).
Span Kind: `SERVER`, `CLIENT`, `PRODUCER`, `CONSUMER`, `INTERNAL`.
W3C Trace Context: encabezados 'traceparent', 'tracestate'; el contexto se transfiere entre servicios.
Attributes - clave-valor (baja cardinalidad!), Eventos - marcas en el tiempo, Estado - código/descripción del error.
Links - la comunicación de los espías fuera de la jerarquía estricta (importante para async/fan-out/fan-in).
- HTTP: 'HTTP {METHOD}' ('GET/withdraw' como atributo)
- DB: `DB SELECT` / `DB INSERT`
- Queue: `QUEUE publish topic=X` / `QUEUE consume topic=X`
3) Convenciones semánticas (semconv)
Utilice esquemas de atributos estables:- HTTP/GRPC: `http. method`, `http. route`, `http. status_code`, `url. full`.
- DB: `db. system=postgresql`, `db. statement '(sólo apretón seguro!),' db. name`.
- Messaging: `messaging. system=kafka`, `messaging. operation=receive`, `messaging. destination`.
- Cloud/K8s/Host: `cloud. region`, `k8s. pod. name`, `container. id`.
- Atributos de recursos (obligatorio): 'servicio. name`, `service. version`, `deployment. environment`.
Especifique la estabilidad del esquema a través de 'schemaUrl' en los recursos SDK/Collector.
4) Sampling: head, tail, adaptive
Head-based (en SDK): resuelve de antemano, barato; bueno para high-QPS, pero puede saltarse pistas «interesantes».
Tail-based (en Coleccionista): decide después de completar la pista; permite reglas por estado, latencia, atributos.
Adaptive/Dinámico: aumenta la proporción de sample en errores/crecimiento p95.
Receta de nivel prod: Head 1-5% global + Tail selección «importante»: 'status = ERROR', 'latency> p95', «rutas monetarias», errores PSP/KYC.
5) Correlación: métricas, registros, tracks
Exemplars: etiquetas con 'trace _ id' en los histogramas de métricas (salto rápido a la pista).
Logs: agregue 'trace _ id '/' span _ id' y cambie de logs a track.
SpanMetrics (processor): agrega desde las rutas métricas RED ('requests, errors, duration') para SLO/alertas.
6) Arquitectura de implementación
El agente (DaemonSet) en cada nodo recopila desde aplicaciones (OTLP) y hacia adelante.
Gateway (Cluster/Region) - Coleccionista central (muchas réplicas) con líneas de enrutamiento/ensamblaje/enriquecimiento.
OTLP: gRPC `4317`, HTTP `4318`; incluya TLS/mTLS.
Ventajas «agent + gateway»: aislamiento, búfer, backpressure local, red simplificada.
7) OpenTelemetry Collector - Plantilla básica (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 y RED para SLO
Agregue el procesador: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] }
Ahora hay 'traces _ spanmetrics _ calls {service, route, code}' y 'duration _ bucket' para SLO/alerts.
9) K8s: implementación de Collector (DaemonSet + Deployment)
Agente (DaemonSet) fragmento: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): varias réplicas, Service ClusterIP/Ingress, HPA por CPU/QPS.
10) Seguridad y privacidad
TLS/mTLS между SDK → Agent → Gateway → Backend.
Autenticación (Basic/OAuth/Headers) en la entrada Gateway; limite los orígenes.
Revisión de PII: filtre/enmascare los atributos ('user. email ',' card') en el procesador Collector.
Límites: en SDK, limite el tamaño del evento/número de atributos (protección contra la cardinalidad).
RBAC en backend + nymspace individuales de proyectos/tenantes.
yaml processors:
attributes/redact:
actions:
- key: user. email action: delete
- key: payment. card action: delete
11) Herramientas: arranques rápidos
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) Asinhronschchchchin: colas, neumáticos, cron
PRODUCER/CONSUMER con comunicación a través de 'links' (los mensajes tienen su propio ciclo de vida).
Propaga el contexto en los encabezados de los mensajes ('traceparent '/' baggage').
Cuando batch-consume, cree un mensaje por correo o agregue con el atributo 'messaging. batch. size`.
Para cron/jobs: nuevo trace para ejecutar + links a eventos primarios (si los hay).
13) Baggage y segmentación
Almacene un mínimo de claves estables ('tenant _ id', 'region', 'vip _ tier') en baggage; Prohibir PII.
Pinche a través de gateway/gateway-logger para la posterior agregación de métricas por segmentos.
14) Integración con lanzamientos y juegos SLO
Pasos canarios → compruebe 'traces _ spanmetrics _' en los segmentos rutas/uz.
En degradación (5xx/p95): parada automática y retroceso (Argo Rollouts AnalysisTemplate + PromQL).
Las instancias de las métricas llevan directamente a las rutas «malas» del intervalo de lanzamiento.
15) Límites y rendimiento
Ограничивайте: `OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT`, `OTEL_SPAN_EVENT_COUNT_LIMIT`, `OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT`.
Sampule las excepciones/stacktrace en probabilidad/frecuencia.
Procesador de batch en SDK y Collector; mantenga las colas para no perder la pista en las ráfagas.
16) Compatibilidad y migración
Propagadores: utilice W3C; admitir la lectura de B3/X-Ray durante la migración (dual-propagation).
Exportación: OTLP → APM (Jaeger/Tempo/Elastic/X-Ray, etc.).
Versiones estables de semconv: fija 'schemaUrl' y planifica actualizaciones.
17) Anti-patrones
Alta cardinalidad de atributos ('user _ id' en etiqueta, claves dinámicas).
Registros sin 'trace _ id' → no hay correlación.
Exportar directamente desde aplicaciones a APM de Internet (sin gateway, sin TLS/mTLS).
Recaudar «solo» el 100% en la venta es caro y sin sentido.
Volcado de consultas SQL con datos de usuario en 'db. statement`.
Nombre de servicio/versión inconsistente: las métricas «se desmoronan».
18) Lista de verificación de implementación (0-45 días)
0-10 días
Habilitar SDK/autoinstrucción en 2-3 servicios críticos.
Configurar Agente (DaemonSet) + Gateway (Deployment), OTLP 4317/4318 con TLS.
Agregar 'servicio. name`, `service. version`, `deployment. environment 'está en todas partes.
11-25 días
Tail-sampling por error/latencia/rutas» monetarias».
SpanMetrics → Prometheus, incluye Exemplars y dashboards RED/SLO.
Propague W3C a través de la puerta de enlace API/NGINX/mesh; correlacionar los registros.
26-45 días
Cubrir colas/DB/caché; links para async.
Políticas de edición PII en Collector; límites de atributos en SDK.
Integrar SLO-gaming lanzamientos y auto-retroceso.
19) Métricas de madurez
Cobertura de solicitudes entrantes mediante seguimiento ≥ 95% (teniendo en cuenta sampling head/tail).
Proporción de métricas con Exemplars ≥ 80%.
Tiempo RCA «de métrica a pista» ≤ 2 min (p50).
0 fugas PII en atributos/eventos (escáner).
Todos los servicios tienen 'servicio. name/version/environment 'y una semántica coherente.
20) Aplicaciones: fragmentos útiles
Propagación 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))
Política: prohibición de atributos PII (pseudo-linter)
yaml forbid_attributes:
- user. email
- payment. card
- personal.
21) Conclusión
OpenTelemetry transforma la observabilidad en un circuito estandarizado y controlado: una sola semántica, propagación segura, sampling inteligente y fuerte correlación con métricas y logs. Construye agent + gateway, agrega tail-sampling, spanmetrics y Exemplars, vigila la PII y la cardinalidad, y el rastreo se convertirá en una herramienta no solo para depurar, sino también para las soluciones automatizadas SRE/Release, reduciendo el MTTR y riesgos en cada lanzamiento.