Trazabilidad
Trazabilidad en sistemas distribuidos: correlation IDs, tracing distribuido y logging estructurado para seguir el recorrido de cada operación entre servicios.
Por qué la trazabilidad es esencial
En un monolito, seguir el flujo de una operación es relativamente simple: todo ocurre en el mismo proceso, con un único log. En un sistema distribuido, una sola acción del usuario puede atravesar 5 o más servicios, cada uno con sus propios logs, tiempos y posibles fallos.
Sin trazabilidad, diagnosticar un problema se convierte en buscar una aguja en un pajar distribuido. La trazabilidad permite reconstruir el camino completo de una operación a través de todos los servicios involucrados.
Los tres pilares de la trazabilidad
1. Correlation ID
Un identificador único que acompaña a una operación desde su origen hasta el último servicio que la procesa. Todos los logs, eventos y métricas relacionados con esa operación comparten el mismo correlation ID.
2. Distributed Tracing
Un sistema que registra el tiempo y la relación entre las operaciones en cada servicio, permitiendo visualizar el flujo completo como un árbol de spans.
3. Logging estructurado
Logs en formato estructurado (JSON) que incluyen el correlation ID y metadata contextual, facilitando la búsqueda y correlación.
Correlation ID en acción
sequenceDiagram
participant FE as Frontend
participant GW as API Gateway
participant BFF as BFF
participant MS1 as ms-orders
participant MS2 as ms-inventory
participant EB as Event Bus
FE->>GW: POST /orders (X-Correlation-ID: abc-123)
GW->>BFF: Forward (X-Correlation-ID: abc-123)
BFF->>MS1: Crear orden (X-Correlation-ID: abc-123)
MS1->>EB: OrderPlaced (correlationId: abc-123)
EB->>MS2: OrderPlaced (correlationId: abc-123)
MS2->>MS2: Reservar stock (log: abc-123)
Cómo se propaga el Correlation ID
- El frontend genera un UUID único al iniciar la operación (o lo genera el API Gateway si no viene)
- Se incluye en el header HTTP
X-Correlation-ID - Cada servicio lo extrae del request entrante y lo incluye en:
- Todos sus logs
- Todas las llamadas HTTP salientes
- Todos los eventos que publica al Event Bus
- Todas las métricas que registra
- Los consumidores de eventos lo extraen del payload del evento
Regla fundamental
Nunca generar un nuevo correlation ID en un servicio intermedio. Si un servicio recibe un request sin correlation ID, puede generar uno. Pero si ya viene uno, debe propagarlo tal cual.
Distributed Tracing
El tracing distribuido va más allá del correlation ID. Registra la estructura temporal del flujo: qué servicio llamó a cuál, cuánto tardó cada operación y dónde se produjo un error.
Conceptos clave
Trace: representa el flujo completo de una operación, desde el origen hasta el final. Un trace contiene múltiples spans.
Span: representa una operación individual dentro de un servicio. Tiene un inicio, un fin, un nombre y metadata.
Parent-Child: los spans se organizan en un árbol. El span del BFF es padre del span del microservicio que invoca.
Ejemplo de un trace
Trace: abc-123
├── [Gateway] POST /orders (5ms)
│ └── [BFF] createOrder (45ms)
│ ├── [ms-orders] createOrder (30ms)
│ │ └── [DB] INSERT INTO orders (8ms)
│ └── [ms-orders] publishEvent (5ms)
└── [ms-inventory] handleOrderPlaced (20ms) ← asíncrono
└── [DB] UPDATE stock (6ms)
Este trace muestra que:
- El request total tardó 50ms (Gateway → BFF → ms-orders)
- La operación de base de datos en ms-orders tardó 8ms
- El procesamiento asíncrono en inventario tardó 20ms adicionales
Herramientas de tracing
Las herramientas más comunes para tracing distribuido son:
| Herramienta | Tipo | Características |
|---|---|---|
| Jaeger | Open source | Visualización de traces, análisis de latencia |
| Zipkin | Open source | Ligero, buena integración con Spring |
| OpenTelemetry | Estándar | Vendor-neutral, combina traces, métricas y logs |
| AWS X-Ray | Managed | Integrado con servicios AWS |
| Datadog APM | SaaS | Traces + métricas + logs en una plataforma |
OpenTelemetry se está convirtiendo en el estándar de facto porque es vendor-neutral y permite cambiar de herramienta sin modificar el código de instrumentación.
Logging estructurado
Por qué logs estructurados
Los logs en texto plano son difíciles de buscar y correlacionar:
2024-01-15 10:30:00 INFO Order created successfully for customer 789
Los logs estructurados en JSON permiten búsquedas precisas:
{
"timestamp": "2024-01-15T10:30:00Z",
"level": "INFO",
"service": "ms-orders",
"correlationId": "abc-123",
"traceId": "trace-456",
"spanId": "span-789",
"message": "Order created successfully",
"context": {
"orderId": "order-456",
"customerId": "cust-789",
"totalAmount": 150.00
}
}
Campos estándar en cada log
Todos los servicios deben incluir estos campos en cada entrada de log:
| Campo | Descripción |
|---|---|
timestamp | Momento exacto (ISO 8601 con timezone) |
level | Severidad (DEBUG, INFO, WARN, ERROR) |
service | Nombre del servicio que genera el log |
correlationId | ID de correlación de la operación |
traceId | ID del trace distribuido |
spanId | ID del span actual |
message | Descripción legible del evento |
context | Datos adicionales relevantes |
Centralización de logs
En un sistema distribuido, los logs de cada servicio deben enviarse a un sistema centralizado donde se puedan buscar y correlacionar:
graph LR
MS1[ms-orders] --> AGG[Log Aggregator]
MS2[ms-inventory] --> AGG
MS3[ms-payments] --> AGG
BFF[BFF] --> AGG
AGG --> STORE[Elasticsearch / CloudWatch / Loki]
STORE --> UI[Kibana / Grafana]
Trazabilidad en flujos asíncronos
La trazabilidad en flujos asíncronos es más compleja porque no hay una conexión HTTP directa entre el publicador y el consumidor del evento.
Propagación por eventos
El correlation ID y el trace ID deben incluirse en el payload del evento:
{
"type": "OrderPlaced",
"metadata": {
"correlationId": "abc-123",
"traceId": "trace-456",
"parentSpanId": "span-789",
"timestamp": "2024-01-15T10:30:00Z",
"source": "ms-orders"
},
"payload": { ... }
}
Cuando el consumidor procesa el evento, crea un nuevo span hijo del span original, manteniendo la cadena de trazabilidad.
Desafío: latencia entre publicación y consumo
En flujos asíncronos, puede pasar tiempo entre la publicación y el consumo. El trace puede mostrar un gap temporal que es normal y esperado.
Diagnóstico de problemas con trazabilidad
Escenario: el usuario reporta que su orden no se confirmó
- Obtener el correlation ID de la orden (desde el frontend o los logs del BFF)
- Buscar todos los logs con ese correlation ID
- Visualizar el trace distribuido
- Identificar dónde se detuvo el flujo:
- ¿El evento
OrderPlacedse publicó? - ¿El servicio de inventario lo recibió?
- ¿Hubo un error en el procesamiento?
- ¿El evento de respuesta se publicó?
- ¿El evento
Sin trazabilidad, este diagnóstico requeriría revisar logs de cada servicio manualmente, buscando por timestamp y esperando encontrar algo relevante.
Resumen
La trazabilidad es lo que hace que un sistema distribuido sea operable. El correlation ID conecta todas las operaciones de un flujo, el tracing distribuido muestra la estructura temporal y las dependencias, y el logging estructurado permite buscar y correlacionar de forma eficiente. Sin estos tres pilares, diagnosticar problemas en producción se vuelve una tarea casi imposible.