Rastreabilidade
Rastreabilidade em sistemas distribuídos: correlation IDs, tracing distribuído e logging estruturado para acompanhar o percurso de cada operação entre serviços.
Por que a rastreabilidade é essencial
Em um monolito, acompanhar o fluxo de uma operação é relativamente simples: tudo acontece no mesmo processo, com um único log. Em um sistema distribuído, uma única ação do usuário pode atravessar 5 ou mais serviços, cada um com seus próprios logs, tempos e possíveis falhas.
Sem rastreabilidade, diagnosticar um problema se torna como procurar uma agulha em um palheiro distribuído. A rastreabilidade permite reconstruir o caminho completo de uma operação através de todos os serviços envolvidos.
Os três pilares da rastreabilidade
1. Correlation ID
Um identificador único que acompanha uma operação desde sua origem até o último serviço que a processa. Todos os logs, eventos e métricas relacionados a essa operação compartilham o mesmo correlation ID.
2. Distributed Tracing
Um sistema que registra o tempo e a relação entre as operações em cada serviço, permitindo visualizar o fluxo completo como uma árvore de spans.
3. Logging estruturado
Logs em formato estruturado (JSON) que incluem o correlation ID e metadados contextuais, facilitando a busca e a correlação.
Correlation ID em ação
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)
Como o Correlation ID se propaga
- O frontend gera um UUID único ao iniciar a operação (ou o API Gateway o gera, caso não venha)
- Ele é incluído no header HTTP
X-Correlation-ID - Cada serviço o extrai da requisição de entrada e o inclui em:
- Todos os seus logs
- Todas as chamadas HTTP de saída
- Todos os eventos que publica no Event Bus
- Todas as métricas que registra
- Os consumidores de eventos o extraem do payload do evento
Regra fundamental
Nunca gere um novo correlation ID em um serviço intermediário. Se um serviço recebe uma requisição sem correlation ID, ele pode gerar um. Mas se já vier um, ele deve propagá-lo como está.
Distributed Tracing
O tracing distribuído vai além do correlation ID. Ele registra a estrutura temporal do fluxo: qual serviço chamou qual, quanto tempo levou cada operação e onde ocorreu um erro.
Conceitos-chave
Trace: representa o fluxo completo de uma operação, da origem até o fim. Um trace contém múltiplos spans.
Span: representa uma operação individual dentro de um serviço. Possui um início, um fim, um nome e metadados.
Parent-Child: os spans se organizam em uma árvore. O span do BFF é pai do span do microsserviço que ele invoca.
Exemplo de um 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 mostra que:
- A requisição total levou 50ms (Gateway → BFF → ms-orders)
- A operação de banco de dados no ms-orders levou 8ms
- O processamento assíncrono no inventário levou 20ms adicionais
Ferramentas de tracing
As ferramentas mais comuns para tracing distribuído são:
| Ferramenta | Tipo | Características |
|---|---|---|
| Jaeger | Open source | Visualização de traces, análise de latência |
| Zipkin | Open source | Leve, boa integração com Spring |
| OpenTelemetry | Padrão | Vendor-neutral, combina traces, métricas e logs |
| AWS X-Ray | Managed | Integrado com serviços AWS |
| Datadog APM | SaaS | Traces + métricas + logs em uma plataforma |
O OpenTelemetry está se tornando o padrão de facto porque é vendor-neutral e permite trocar de ferramenta sem modificar o código de instrumentação.
Logging estruturado
Por que logs estruturados
Os logs em texto simples são difíceis de buscar e correlacionar:
2024-01-15 10:30:00 INFO Order created successfully for customer 789
Os logs estruturados em JSON permitem buscas 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 padrão em cada log
Todos os serviços devem incluir estes campos em cada entrada de log:
| Campo | Descrição |
|---|---|
timestamp | Momento exato (ISO 8601 com timezone) |
level | Severidade (DEBUG, INFO, WARN, ERROR) |
service | Nome do serviço que gera o log |
correlationId | ID de correlação da operação |
traceId | ID do trace distribuído |
spanId | ID do span atual |
message | Descrição legível do evento |
context | Dados adicionais relevantes |
Centralização de logs
Em um sistema distribuído, os logs de cada serviço devem ser enviados a um sistema centralizado onde possam ser buscados e correlacionados:
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]
Rastreabilidade em fluxos assíncronos
A rastreabilidade em fluxos assíncronos é mais complexa porque não há uma conexão HTTP direta entre o publicador e o consumidor do evento.
Propagação por eventos
O correlation ID e o trace ID devem ser incluídos no payload do evento:
{
"type": "OrderPlaced",
"metadata": {
"correlationId": "abc-123",
"traceId": "trace-456",
"parentSpanId": "span-789",
"timestamp": "2024-01-15T10:30:00Z",
"source": "ms-orders"
},
"payload": { ... }
}
Quando o consumidor processa o evento, ele cria um novo span filho do span original, mantendo a cadeia de rastreabilidade.
Desafio: latência entre publicação e consumo
Em fluxos assíncronos, pode se passar um tempo entre a publicação e o consumo. O trace pode mostrar um gap temporal que é normal e esperado.
Diagnóstico de problemas com rastreabilidade
Cenário: o usuário reporta que seu pedido não foi confirmado
- Obter o correlation ID do pedido (a partir do frontend ou dos logs do BFF)
- Buscar todos os logs com esse correlation ID
- Visualizar o trace distribuído
- Identificar onde o fluxo parou:
- O evento
OrderPlacedfoi publicado? - O serviço de inventário o recebeu?
- Houve um erro no processamento?
- O evento de resposta foi publicado?
- O evento
Sem rastreabilidade, esse diagnóstico exigiria revisar os logs de cada serviço manualmente, buscando por timestamp e torcendo para encontrar algo relevante.
Resumo
A rastreabilidade é o que torna um sistema distribuído operável. O correlation ID conecta todas as operações de um fluxo, o tracing distribuído mostra a estrutura temporal e as dependências, e o logging estruturado permite buscar e correlacionar de forma eficiente. Sem esses três pilares, diagnosticar problemas em produção se torna uma tarefa quase impossível.