Distributed Tracing: OpenTelemetry
Distributed Tracing: OpenTelemetry
1) Perché OTel e cosa dà
OpenTelemetry (OTtel) è uno standard aperto e un set SDK/agenti/raccoglitori per la telemetria (trailer, metriche, logi) con un unico protocollo OTLP. Obiettivi:- Visibilità completa dei percorsi di query (gateway servizi di database/cache/coda).
- Rapido RCA/debug di degrado e rilascio (canarini/blue-green).
- Collegamento con SLO e auto-reimpostazione (soluzioni operative per dati).
- Vendor-agnosticità: esporta in qualsiasi backend, senza alcun riferimento a un singolo APM.
I principi di riferimento sono standardize, sample smart, secure by default, correlate everything.
2) Base: contesto, span, attributi
Trace - albero/grafico delle chiamate Operazione span (RPC, SQL, chiamata coda).
Span Kind: `SERVER`, `CLIENT`, `PRODUCER`, `CONSUMER`, `INTERNAL`.
W3C Trace Text: intestazioni «traceparent», «tracestate»; il contesto viene spostato interserver.
Attribute è la chiave-valore (bassa cardinalità!), Events sono le etichette nel tempo, Status è il codice/descrizione dell'errore.
Links è un collegamento span fuori dalla gerarchia rigorosa (importante per async/fan-out/fan-in).
- HTTP: 'HTTP {METHOD}' ('GET/withdraw'come attributo)
- DB: `DB SELECT` / `DB INSERT`
- Queue: `QUEUE publish topic=X` / `QUEUE consume topic=X`
3) Convenzioni semantiche (semconv)
Utilizzare schemi di attributi stabili:- HTTP/GRPC: `http. method`, `http. route`, `http. status_code`, `url. full`.
- DB: `db. system=postgresql`, `db. statement '(solo spremitura sicura!),' db. name`.
- Messaging: `messaging. system=kafka`, `messaging. operation=receive`, `messaging. destination`.
- Cloud/K8s/Host: `cloud. region`, `k8s. pod. name`, `container. id`.
- Resource attribute (obbligatorio): 'service. name`, `service. version`, `deployment. environment`.
Stabili lo schema tramite «schemaUrl» nelle risorse SDK/Raccettore.
4) Sampling: head, tail, adattativo
Head-based (SDK): risolve in anticipo, a basso costo; Bene per l'high-QPS, ma potrebbe saltare le piste «interessanti».
Tail-based (in Collettore) - Risolve una volta completata la pista; consente le regole di stato, latitanza, attributi.
Adattativo/Dinamico - aumenta la quota di sample in caso di errori/altezza p95.
Ricetta di livello prod: Head 1-5% globale + Tail selezione «importante»: «status = ERROR», «latency> p95», «rotte di denaro», errori PSP/KYC.
5) Correlazione: metriche, fogli, roulotte
Excplars: etichette con «trace _ id» negli istogrammi delle metriche (salto veloce verso la pista).
Loghi: aggiungi «trace _ id »/« span _ id» e passa dai fogli alla pista.
SpanMetrics (processor) - Aggrega da tracciati le metriche RED ('richiesti, errors, duration') per gli alert SLO.
6) Architettura di installazione
L'agente (DaemonSet) su ciascun nodo raccoglie da applicazioni (OTLP) e OTLP.
Gateway (Cluster/Region) è un Collettore centrale (molte repliche) con pipline di routing/sampling/arricchimento.
OTLP: gRPC `4317`, HTTP `4318`; Accendete il TLS/mTLS.
Agenti + gateway: isolamento, buffering, backpressure locali, rete semplificata.
7) OpenTelemetry Raccoglitore - Modello di base (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 e RED per SLO
Aggiungi processore: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] }
Ora ci sono «traces _ spanmetrics _ calls {service, route, code}» e «duration _ bucket» per gli alert/SLO.
9) K8s: installazione di Raccoglitore (DaemonSet + Deployment)
Agente (DaemonSet) sezione: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) - più repliche, Servizio ClusterIP/Ingress, HPA CPU/QPS.
10) Sicurezza e privacy
TLS/mTLS между SDK → Agent → Gateway → Backend.
Autenticazione (Basic/OAuth/Headers) all'ingresso di Gateway; limitare le origini.
Revisione PII - Filtra/maschera gli attributi ('user. email, card, nel processore Collector.
Limiti - In SDK, limitare la dimensione dell'evento al numero di attributi (protezione contro la radicalità).
RBAC in backand + singoli Neimspace progetti/tenenti.
yaml processors:
attributes/redact:
actions:
- key: user. email action: delete
- key: payment. card action: delete
11) Strumenti: avviamenti rapidi
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) Asincroncia: code, pneumatici, cron
PRODUCER/CONSUMER tramite «links» (i messaggi hanno il loro ciclo di vita).
Esplora il contesto nelle intestazioni dei messaggi ('traceparent'/' baggage').
Quando si utilizza batch, creare uno span per messaggio o aggregare con l'attributo'messaging '. batch. size`.
Per cron/jobs: nuovo trace per avviare + links agli eventi primari (se disponibile).
13) Baggage e targeting
Memorizzare un minimo di chiavi stabili («tenant _ id», «region», «vip _ tier») in baggage; Vietate il PII.
Fare clic su gateway/gateway-logger per aggregare le metriche in base ai segmenti.
14) Integrazione con release e SLO-gating
I passi canarini controllano «traces _ spanmetrics _» attraverso i percorsi/yuse-segmenti.
In caso di degrado (5xx/p95) - Auto-stop e rientro (Argo Rollouts + ).
Le istanze di metriche conducono direttamente alle piste «cattive» dell'intervallo di lancio.
15) Limiti e prestazioni
Ограничивайте: `OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT`, `OTEL_SPAN_EVENT_COUNT_LIMIT`, `OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT`.
Samplite eccezioni/stacktrace per probabilità/frequenza.
Processore Batch in SDK e Collettore tenete le code per non perdere le piste in caso di picchi.
16) Compatibilità e migrazione
Visualizzatori: usa W3C; supportare la lettura di B3/X-Ray durante la migrazione (dual-propagation).
Esportazione: OTLP → APM (Jaeger/Tempo/Elastic/X-Ray, ecc.).
Versioni stabili semconv - Fissa «schemaUrl» e pianifica gli upgrade.
17) Anti-pattern
Alta radicalità degli attributi ('user _ id' in label, chiavi dinamiche).
Non c'è alcuna correlazione tra i loghi senza «trace _ id».
Esporta direttamente dalle applicazioni a Internet APM (senza gateway, senza TLS/mTLS).
Raccogliere solo il 100% in vendita è costoso e inutile.
Dump di query SQL con dati utente in db. statement`.
Nome del servizio/versione incoerente - Le metriche vengono dissolte.
18) Assegno foglio di implementazione (0-45 giorni)
0-10 giorni
Abilita SDK/Automazione su 2-3 servizi critici.
Configura Agente (DaemonSet) + Gateway (Deployment), OTLP 4317/4318 con TLS.
Aggiungi 'service. name`, `service. version`, `deployment. environment dappertutto.
11-25 giorni
Tail-sampling per errori/latitanza/percorsi» monetari».
SpanMetrics → Prometheus, includere Exemplars e dashboard RED/SLO.
Informare W3C tramite API gateway/NGINX/mesh; Correlare i loghi.
26-45 giorni
Coprire code/database/cache; links per async.
Criteri di revisione PII in Collector; limiti di attributi SDK.
Integrare le release SLO-Gate e il ritorno automatico.
19) Metriche di maturità
La copertura delle richieste in entrata è ≥ al 95% (con sampling head/tail).
La percentuale di metriche con Exceplars è pari all '80%.
Il tempo RCA «da metrica a pista» è di 2 minuti (p50).
0 fuoriuscite PII in attributi/eventi (scanner).
Tutti i servizi hanno un servizio. name/variante/environment "e semantica coerente.
20) Applicazioni: frammenti utili
Promemoria 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: proibizione degli attributi PII (pseudonimo-linter)
yaml forbid_attributes:
- user. email
- payment. card
- personal.
21) Conclusione
OpenTelemetry trasforma l'osservabilità in un tracciato standardizzato e controllato: semantica unificata, insorgenza sicura, sampling intelligente e forte correlazione con metriche e loghi. Costruisci un agente + gateway, aggiungi tail-sampling, spanmetrics ed Excempars, tieni d'occhio la PII e la cardinalità - e il tracciamento diventerà uno strumento non solo per il debug, ma anche per le soluzioni SRE/Release automatizzate, riducendo MTTR e i rischi in ogni comunicato.