executing-plans
executing-plans
Use when executing an implementation plan in the current session as the implementer yourself — your human partner chose inline execution, or no subagent tool is available
instrument-distributed-tracingInstrumenta aplicaciones con OpenTelemetry para rastreo distribuido, incluyendo instrumentación automática y manual, propagación de contexto, estrategias de muestreo e integración con Jaeger o Tempo. Útil para depurar problemas de latencia en sistemas distribuidos, comprender el flujo de solicitudes entre microservicios, correlacionar trazas con logs y métr…
Independent GitHub snapshot · Automated classification · Original documentation governs
Implementa rastreo distribuido con OpenTelemetry para rastrear solicitudes entre microservicios e identificar cuellos de botella de rendimiento.
Consulta Ejemplos Extendidos para archivos de configuración completos y plantillas.
Despliega Jaeger o Grafana Tempo para recibir y almacenar trazas.
Opción A: Jaeger todo-en-uno (desarrollo/pruebas):
# docker-compose.yml
version: '3.8'
services:
jaeger:
image: jaegertracing/all-in-one:1.51
ports:
- "5775:5775/udp" # Zipkin compact thrift
- "6831:6831/udp" # Jaeger compact thrift
- "6832:6832/udp" # Jaeger binary thrift
- "5778:5778" # Serve configs
- "16686:16686" # Jaeger UI
- "14268:14268" # Jaeger HTTP thrift
- "14250:14250" # Jaeger GRPC
- "9411:9411" # Zipkin compatible endpoint
environment:
- COLLECTOR_ZIPKIN_HOST_PORT=:9411
- COLLECTOR_OTLP_ENABLED=true
restart: unless-stopped
Opción B: Grafana Tempo (producción, escalable):
# docker-compose.yml
version: '3.8'
services:
tempo:
image: grafana/tempo:2.3.0
command: ["-config.file=/etc/tempo.yaml"]
volumes:
- ./tempo.yaml:/etc/tempo.yaml
- tempo-data:/tmp/tempo
ports:
- "3200:3200" # Tempo HTTP
- "4317:4317" # OTLP gRPC
- "4318:4318" # OTLP HTTP
- "9411:9411" # Zipkin
restart: unless-stopped
volumes:
tempo-data:
Configuración de Tempo (tempo.yaml):
server:
http_listen_port: 3200
distributor:
receivers:
jaeger:
# ... (see EXAMPLES.md for complete configuration)
Para producción con almacenamiento S3:
storage:
trace:
backend: s3
s3:
bucket: tempo-traces
endpoint: s3.amazonaws.com
region: us-east-1
wal:
path: /tmp/tempo/wal
pool:
max_workers: 100
queue_depth: 10000
Esperado: Backend de rastreo accesible, listo para recibir trazas vía OTLP, la interfaz de Jaeger o Grafana muestra "no traces" inicialmente.
En caso de fallo:
netstat -tulpn | grep -E '(4317|16686|3200)'docker logs jaeger o docker logs tempocurl http://localhost:4318/v1/traces -vtempo -config.file=/etc/tempo.yaml -verify-configUsa la auto-instrumentación de OpenTelemetry para frameworks comunes para minimizar cambios de código.
Python con Flask:
pip install opentelemetry-distro opentelemetry-exporter-otlp
opentelemetry-bootstrap -a install
# app.py
from flask import Flask
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
# ... (see EXAMPLES.md for complete configuration)
Go con framework Gin:
go get go.opentelemetry.io/otel
go get go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc
go get go.opentelemetry.io/otel/sdk/trace
go get go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin
package main
import (
"context"
"github.com/gin-gonic/gin"
"go.opentelemetry.io/otel"
# ... (see EXAMPLES.md for complete configuration)
Node.js con Express:
npm install @opentelemetry/api \
@opentelemetry/sdk-node \
@opentelemetry/auto-instrumentations-node \
@opentelemetry/exporter-trace-otlp-grpc
// tracing.js
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { Resource } = require('@opentelemetry/resources');
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
# ... (see EXAMPLES.md for complete configuration)
Esperado: Las trazas de los servicios instrumentados aparecen en la interfaz de Jaeger o Grafana, las solicitudes HTTP crean spans automáticamente.
En caso de fallo:
OTEL_EXPORTER_OTLP_ENDPOINT=http://tempo:4317OTEL_LOG_LEVEL=debug (Python), OTEL_LOG_LEVEL=DEBUG (Node.js)Crea spans personalizados para lógica de negocio, consultas de base de datos y llamadas externas.
Spans manuales en Python:
from opentelemetry import trace
tracer = trace.get_tracer(__name__)
def process_order(order_id):
# Create a span for the entire operation
# ... (see EXAMPLES.md for complete configuration)
Spans manuales en Go:
import (
"context"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
# ... (see EXAMPLES.md for complete configuration)
Buenas prácticas para atributos de span:
http.method, http.status_code, db.system, db.statementuser.id, order.id, product.categoryinstance.id, region, availability_zonespan.RecordError(err) y span.SetStatus(codes.Error, message)span.AddEvent("cache_miss")Esperado: Los spans personalizados aparecen en la vista de traza, las relaciones padre-hijo son correctas, los atributos son visibles en los detalles del span, los errores están resaltados.
En caso de fallo:
defer span.End() en Go, bloques with en Python)Asegúrate de que el contexto de traza fluya a través de los límites de servicio y operaciones asíncronas.
Propagación de encabezados HTTP (W3C Trace Context):
# Client side (Python with requests)
import requests
from opentelemetry import trace
from opentelemetry.propagate import inject
tracer = trace.get_tracer(__name__)
# ... (see EXAMPLES.md for complete configuration)
// Server side (Go with Gin)
import (
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/propagation"
)
# ... (see EXAMPLES.md for complete configuration)
Propagación de cola de mensajes (Kafka):
# Producer
from opentelemetry.propagate import inject
from kafka import KafkaProducer
producer = KafkaProducer(bootstrap_servers=['kafka:9092'])
# ... (see EXAMPLES.md for complete configuration)
# Consumer
from opentelemetry.propagate import extract
def process_message(msg):
# Extract trace context from Kafka headers
headers = {k: v.decode('utf-8') for k, v in msg.headers}
ctx = extract(headers)
# Continue the trace
with tracer.start_as_current_span("process_order_event", context=ctx):
order_id = json.loads(msg.value)['order_id']
handle_order(order_id)
Operaciones asíncronas (Python asyncio):
import asyncio
from opentelemetry import trace, context
async def async_operation():
# Capture current context
token = context.attach(context.get_current())
try:
with tracer.start_as_current_span("async_database_query"):
await asyncio.sleep(0.1) # Simulated async work
return "result"
finally:
context.detach(token)
Esperado: Las trazas abarcan múltiples servicios, los IDs de traza son consistentes entre límites de servicio, las relaciones padre-hijo se preservan.
En caso de fallo:
otel.propagation.set_global_textmap(TraceContextTextMapPropagator())traceparentImplementa el muestreo para reducir el volumen de trazas y el costo mientras se mantiene la visibilidad.
Estrategias de muestreo:
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.sampling import (
ParentBased,
TraceIdRatioBased,
StaticSampler,
Decision
# ... (see EXAMPLES.md for complete configuration)
Muestreo basado en cola con Tempo:
Configurar en tempo.yaml:
overrides:
defaults:
metrics_generator:
processors: [service-graphs, span-metrics]
storage:
path: /tmp/tempo/generator/wal
remote_write:
- url: http://prometheus:9090/api/v1/write
send_exemplars: true
# Tail sampling (requires tempo-query)
ingestion_rate_limit_bytes: 5000000
ingestion_burst_size_bytes: 10000000
Usar TraceQL de Grafana Tempo para muestreo dinámico:
# Sample traces with errors
{ status = error }
# Sample slow traces (>1s)
{ duration > 1s }
# Sample specific services
{ resource.service.name = "checkout-service" }
Esperado: El volumen de trazas se reduce al porcentaje objetivo, las trazas con errores siempre se muestrean, la decisión de muestreo es visible en los metadatos de la traza.
En caso de fallo:
ingestion_burst_size_bytes)otel_traces_dropped_totalVincula las trazas con métricas y logs para observabilidad unificada.
Agregar IDs de traza a logs (Python):
import logging
from opentelemetry import trace
# Custom log formatter with trace context
class TraceFormatter(logging.Formatter):
def format(self, record):
# ... (see EXAMPLES.md for complete configuration)
Generar métricas desde trazas (Tempo):
# tempo.yaml
metrics_generator:
registry:
external_labels:
cluster: production
storage:
# ... (see EXAMPLES.md for complete configuration)
Esto genera métricas de Prometheus:
traces_service_graph_request_total - recuento de solicitudes entre serviciostraces_span_metrics_duration_seconds - histograma de duración de spanstraces_spanmetrics_calls_total - recuentos de llamadas de spanConsultar trazas desde métricas (Grafana):
Agrega soporte de exemplar a la fuente de datos de Prometheus en Grafana:
datasources:
- name: Prometheus
type: prometheus
url: http://prometheus:9090
jsonData:
exemplarTraceIdDestinations:
- name: trace_id
datasourceName: Tempo
En el dashboard de Grafana, habilitar los exemplares:
{
"fieldConfig": {
"defaults": {
"custom": {
"showExemplars": true
}
}
}
}
Esperado: Al hacer clic en los exemplares de métricas se abre la traza, los logs muestran los IDs de traza, las trazas enlazan a los logs, depuración unificada entre señales.
En caso de fallo:
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) and on() exemplarcontext a las llamadas posteriores rompe las trazas. Siempre pasar el contexto explícitamente.defer span.End() (Go) o bloques with (Python) causa que los spans permanezcan abiertos y pérdidas de memoria.span.RecordError() pierde información valiosa de depuración. Siempre registrar errores en los spans.ParentBased para respetar el muestreo ascendente.correlate-observability-signals - Depuración unificada con métricas, logs y trazas vinculadas por IDs de trazasetup-prometheus-monitoring - Generar métricas desde trazas usando el generador de métricas de Tempoconfigure-log-aggregation - Agregar IDs de traza a los logs para correlación con trazas distribuidasbuild-grafana-dashboards - Visualizar métricas derivadas de trazas y vínculos de exemplares en dashboards