Estratégias de observabilidade em sistemas distribuídos

1. Fundamentos da observabilidade em sistemas distribuídos

1.1. Definição de observabilidade vs. monitoramento tradicional

Observabilidade não é sinônimo de monitoramento. Enquanto o monitoramento tradicional responde a perguntas conhecidas ("o serviço X está no ar?"), a observabilidade permite fazer perguntas que você não sabia que precisava fazer. Em sistemas distribuídos, onde dezenas ou centenas de serviços interagem, o monitoramento clássico falha porque não consegue capturar a complexidade das interações.

A observabilidade é a capacidade de inferir o estado interno de um sistema a partir de seus dados externos (saídas). Isso significa que, quando algo dá errado, você deve ser capaz de descobrir o que, onde e por que aconteceu, sem precisar adivinhar antecipadamente quais métricas monitorar.

1.2. Os três pilares: métricas, logs e tracing distribuído

Os três pilares da observabilidade são:

  • Métricas: dados numéricos agregados ao longo do tempo (taxa de requisições, latência, erros)
  • Logs: registros textuais de eventos discretos, idealmente estruturados
  • Tracing distribuído: rastreamento do fluxo de uma requisição através de múltiplos serviços

Cada pilar cobre uma dimensão diferente. Métricas mostram o que está acontecendo, logs mostram o que aconteceu em detalhe, e tracing mostra por onde passou e quanto tempo cada etapa levou.

1.3. Desafios específicos de sistemas distribuídos

Sistemas distribuídos introduzem desafios únicos:

  • Latência de rede: chamadas remotas podem sofrer timeouts ou retransmissões
  • Falhas parciais: um serviço pode falhar enquanto outros continuam funcionando
  • Inconsistência de dados: réplicas podem estar dessincronizadas
  • Dificuldade de correlação: sem IDs únicos, é impossível ligar eventos entre serviços

2. Coleta e instrumentação de métricas

2.1. Métricas de infraestrutura vs. métricas de aplicação (RED e USE)

Dois frameworks dominam a coleta de métricas:

  • USE (Utilization, Saturation, Errors): focado em infraestrutura. Para cada recurso (CPU, memória, disco, rede), meça utilização, saturação e erros.
  • RED (Rate, Errors, Duration): focado em aplicações. Para cada serviço, meça taxa de requisições, taxa de erros e duração (latência).

Exemplo de métrica RED para um serviço de pagamento:

# HELP http_requests_total Total de requisições HTTP
# TYPE http_requests_total counter
http_requests_total{service="payment", method="POST", endpoint="/charge", status="200"} 1024
http_requests_total{service="payment", method="POST", endpoint="/charge", status="500"} 12

# HELP http_request_duration_seconds Latência das requisições HTTP
# TYPE http_request_duration_seconds histogram
http_request_duration_seconds_bucket{service="payment", le="0.1"} 800
http_request_duration_seconds_bucket{service="payment", le="0.5"} 950
http_request_duration_seconds_bucket{service="payment", le="1.0"} 1010
http_request_duration_seconds_bucket{service="payment", le="+Inf"} 1036

2.2. Ferramentas de agregação e armazenamento (Prometheus, Thanos)

Prometheus é o padrão de facto para métricas em cloud native. Ele coleta dados via pull, armazena em TSDB e oferece PromQL para consultas. Para ambientes multi-cluster ou de longa retenção, Thanos estende o Prometheus com armazenamento em object storage e consultas globais.

2.3. Estratégias de cardinalidade e dimensionalidade de métricas

Cardinalidade alta (muitos valores únicos para labels, como user_id) pode explodir o armazenamento. Estratégias:

  • Agregação prévia: em vez de http_requests_total{user_id="123"}, use http_requests_total{tenant="acme"}
  • Amostragem: para labels de alta cardinalidade, registre apenas uma fração
  • Separação de métricas: métricas de alta cardinalidade vão para sistemas especializados (como logs)

3. Gerenciamento e estruturação de logs

3.1. Logs estruturados e contextos enriquecidos (correlation IDs)

Logs não estruturados são inúteis em escala. Sempre use formato JSON ou key=value. Inclua sempre um correlation ID que atravessa todos os serviços.

Exemplo de log estruturado:

{"timestamp":"2025-01-15T10:30:00Z","level":"ERROR","service":"order-service","trace_id":"abc123","user_id":"456","message":"Falha ao processar pagamento","error":"timeout","duration_ms":3200}

3.2. Centralização de logs com Elastic Stack e Loki

Elastic Stack (Elasticsearch, Logstash, Kibana) oferece busca full-text e agregações complexas. Loki, do Grafana Labs, é mais leve e integra nativamente com Prometheus e Grafana. Loki indexa apenas metadados (labels), não o conteúdo do log, reduzindo custos.

3.3. Políticas de retenção, rotação e amostragem de logs

  • Retenção: logs críticos (erros, warnings) mantidos por 30-90 dias; logs de debug por 7 dias
  • Rotação: arquivos de log girados por tamanho (100MB) ou tempo (diariamente)
  • Amostragem: em alta carga, registre apenas 10% dos logs de info; 100% dos erros

4. Distributed tracing como espinha dorsal da observabilidade

4.1. Conceitos de spans, traces e contextos de propagação (W3C Trace Context)

Um trace representa uma requisição completa. Cada span é uma unidade de trabalho dentro do trace (chamada HTTP, consulta a banco). O W3C Trace Context (headers traceparent e tracestate) propaga o contexto entre serviços.

4.2. Implementação com OpenTelemetry e Jaeger

OpenTelemetry é o padrão aberto para instrumentação. Exemplo de configuração para enviar traces a Jaeger:

OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger-collector:4318
OTEL_SERVICE_NAME=payment-service
OTEL_TRACES_SAMPLER=parentbased_traceidratio
OTEL_TRACES_SAMPLER_ARG=0.1

4.3. Amostragem inteligente: cabeça, cauda e amostragem probabilística

  • Amostragem de cabeça: decide amostrar no início do trace (simples, mas perde traces longos)
  • Amostragem de cauda: decide após o trace terminar (captura erros, mas requer buffer)
  • Amostragem probabilística: amostra uma fração fixa (ex: 10%) de todos os traces

5. Correlação entre os três pilares

5.1. Unificação de métricas, logs e traces com service graphs

Service graphs mostram a topologia do sistema e sobrepõem métricas (latência, erros) nas arestas. Clicar em uma aresta leva aos traces, e cada trace leva aos logs.

5.2. Uso de dashboards integrados (Grafana + Tempo)

Grafana unifica Prometheus (métricas), Loki (logs) e Tempo (traces). Um dashboard típico:

Painel 1: Taxa de requisições (PromQL: rate(http_requests_total[5m]))
Painel 2: Latência P99 (PromQL: histogram_quantile(0.99, ...))
Painel 3: Últimos erros (Loki: {service="payment"} |= "ERROR")
Painel 4: Traces lentos (Tempo: traceQL para duração > 2s)

5.3. Alertas baseados em SLIs e SLOs com correlação automática

Defina SLOs (Service Level Objectives) e monitore SLIs (Service Level Indicators). Quando um alerta dispara, a correlação automática busca traces e logs relacionados.

6. Estratégias avançadas para ambientes complexos

6.1. Observabilidade em malhas de serviço (service mesh) com Istio

Istio injeta proxies sidecar que geram métricas e traces automaticamente. Comando para visualizar métricas:

istioctl dashboard prometheus
istioctl dashboard jaeger

6.2. Redução de custos: amostragem adaptativa e compressão de dados

  • Amostragem adaptativa: aumente a taxa de amostragem quando erros ou latência alta são detectados
  • Compressão: use formatos columnar (Parquet) para armazenamento de traces
  • Downsampling: métricas antigas são agregadas em resolução menor

6.3. Observabilidade serverless e em funções efêmeras (AWS Lambda)

Funções efêmeras exigem envio assíncrono de telemetria. Use OpenTelemetry Lambda Layer e envie para um coletor central. Exemplo de configuração:

OTEL_TRACES_EXPORTER=otlp
OTEL_METRICS_EXPORTER=otlp
OTEL_LOGS_EXPORTER=otlp
OTEL_EXPORTER_OTLP_ENDPOINT=https://collector.example.com:4318

7. Cultura e boas práticas de implementação

7.1. Adoção de padrões abertos (OpenTelemetry, OpenMetrics)

Evite lock-in de fornecedor. OpenTelemetry cobre os três pilares e é suportado por todos os principais players (Datadog, New Relic, Grafana, AWS, GCP, Azure).

7.2. Estratégias de rollout e versionamento de instrumentação

  • Comece com serviços críticos (gateway, autenticação, pagamento)
  • Use feature flags para ativar/desativar instrumentação
  • Versione a instrumentação junto com o código (semantic versioning)

7.3. Treinamento de equipes e runbooks orientados a observabilidade

Cada runbook deve incluir:
- Quais dashboards consultar
- Quais queries de métricas/logs/traces executar
- Como correlacionar os três pilares
- Procedimentos de escalonamento

Referências