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

  1. O frontend gera um UUID único ao iniciar a operação (ou o API Gateway o gera, caso não venha)
  2. Ele é incluído no header HTTP X-Correlation-ID
  3. 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
  4. 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:

FerramentaTipoCaracterísticas
JaegerOpen sourceVisualização de traces, análise de latência
ZipkinOpen sourceLeve, boa integração com Spring
OpenTelemetryPadrãoVendor-neutral, combina traces, métricas e logs
AWS X-RayManagedIntegrado com serviços AWS
Datadog APMSaaSTraces + 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:

CampoDescrição
timestampMomento exato (ISO 8601 com timezone)
levelSeveridade (DEBUG, INFO, WARN, ERROR)
serviceNome do serviço que gera o log
correlationIdID de correlação da operação
traceIdID do trace distribuído
spanIdID do span atual
messageDescrição legível do evento
contextDados 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

  1. Obter o correlation ID do pedido (a partir do frontend ou dos logs do BFF)
  2. Buscar todos os logs com esse correlation ID
  3. Visualizar o trace distribuído
  4. Identificar onde o fluxo parou:
    • O evento OrderPlaced foi publicado?
    • O serviço de inventário o recebeu?
    • Houve um erro no processamento?
    • O evento de resposta foi publicado?

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.