Pular para conteúdo

RFC-008: Observability e Monitoring Standards

Campo Valor
Status Draft
Author Time de Tecnologia
Created 2026-02-05
Updated 2026-02-05
Reunião A ser agendada
Deciders Todo o time técnico

Status

🟡 Draft - RFC em elaboração, aguardando apresentação

Contexto e Problema

CloudWatch documentado em docs/observability/, mas falta:

  • SLOs/SLAs definidos formalmente
  • Golden Signals padronizados (Latency, Traffic, Errors, Saturation)
  • Dashboard standards para todos os serviços
  • Alert thresholds baseados em dados
  • Correlation IDs obrigatórios em todos os logs

Por que resolver isso agora?

  • Dificuldade em diagnosticar problemas rapidamente
  • Alarmes ruidosos ou ausentes
  • Falta visibilidade end-to-end
  • SLOs não são medidos consistentemente
  • Logs sem correlation dificulta debugging

Impacto de não resolver

  • MTTR (Mean Time To Recovery) alto
  • Incidentes não detectados rapidamente
  • Debugging lento e manual
  • SLOs não mensuráveis
  • Customer experience degradada sem visibilidade

Documentação relacionada: - docs/observability/monitoring.md - Dashboards atuais - docs/observability/cloudwatch.md - Logs e métricas - docs/observability/alerting.md - Alarmes e severidade - docs/observability/troubleshooting.md - Guias - docs/architecture/aws-services.md - Serviços AWS

Proposta de Solução

Observability baseada em Golden Signals, SLOs formais, e correlation IDs obrigatórios.

Golden Signals (Obrigatórios)

1. Latency (quanto tempo leva) - P50, P95, P99 latency por endpoint - Target: P95 < 500ms, P99 < 1s

2. Traffic (quanto está sendo usado) - Requests por segundo (RPS) - Concurrent users - Baseline e trends

3. Errors (o que está falhando) - Error rate % - 4xx vs 5xx - Target: < 1% error rate

4. Saturation (quão cheio está) - Lambda concurrent executions - Database connections - Memory/CPU usage - Target: < 70% utilization

SLOs (Service Level Objectives)

Availability: - Target: 99.9% uptime - Medição: % de requests com status 2xx ou 3xx - Erro budget: 43.2 minutos/mês de downtime

Latency: - Target: P95 < 500ms - Medição: Response time do API Gateway - Por endpoint

Error Rate: - Target: < 0.1% errors - Medição: % de 5xx responses - Excluindo 4xx (client errors)

Dashboards Padronizados

Dashboard: Lambda Function

Widgets:
  - Invocations (count)
  - Duration (P50, P95, P99)
  - Errors (count, %)
  - Throttles (count)
  - Concurrent Executions
  - Memory utilization

Dashboard: API Endpoints

Widgets:
  - Request count por endpoint
  - Latency (P50, P95, P99) por endpoint
  - Status codes (2xx, 4xx, 5xx)
  - Error rate %

Dashboard: Database (RDS)

Widgets:
  - CPU utilization
  - Database connections
  - Read/Write IOPS
  - Disk space
  - Slow queries

Dashboard: SQS Queues

Widgets:
  - Messages visible
  - Messages in flight
  - Age of oldest message
  - DLQ messages

Structured Logging

Formato obrigatório (JSON):

import structlog

# Configuração
structlog.configure(
    processors=[
        structlog.stdlib.filter_by_level,
        structlog.stdlib.add_logger_name,
        structlog.stdlib.add_log_level,
        structlog.stdlib.PositionalArgumentsFormatter(),
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.processors.StackInfoRenderer(),
        structlog.processors.format_exc_info,
        structlog.processors.UnicodeDecoder(),
        structlog.processors.JSONRenderer()
    ],
    wrapper_class=structlog.stdlib.BoundLogger,
    logger_factory=structlog.stdlib.LoggerFactory(),
    cache_logger_on_first_use=True,
)

logger = structlog.get_logger()

# Uso
logger.info(
    "user_login_successful",
    user_id=user.id,
    email=user.email,
    ip_address=request.client.host,
    correlation_id=request.headers.get("X-Correlation-ID")
)

# Output:
{
  "event": "user_login_successful",
  "user_id": 123,
  "email": "user@example.com",
  "ip_address": "192.168.1.1",
  "correlation_id": "550e8400-e29b-41d4-a716-446655440000",
  "timestamp": "2026-02-05T14:30:00.123456Z",
  "level": "info",
  "logger": "app.auth"
}

Correlation IDs

Geração e propagação:

# Middleware FastAPI
from fastapi import Request
import uuid

@app.middleware("http")
async def add_correlation_id(request: Request, call_next):
    # Obter ou gerar correlation ID
    correlation_id = request.headers.get("X-Correlation-ID") or str(uuid.uuid4())

    # Adicionar ao contexto de logging
    with structlog.contextvars.bind_contextvars(correlation_id=correlation_id):
        # Adicionar ao response
        response = await call_next(request)
        response.headers["X-Correlation-ID"] = correlation_id
        return response

Propagação para downstream services:

async def call_external_service(url: str):
    correlation_id = structlog.contextvars.get_contextvars()["correlation_id"]

    response = await httpx.get(
        url,
        headers={"X-Correlation-ID": correlation_id}
    )
    return response

Busca de logs por correlation ID:

# CloudWatch Logs Insights
fields @timestamp, @message
| filter correlation_id = "550e8400-e29b-41d4-a716-446655440000"
| sort @timestamp desc

X-Ray Tracing

Instrumentação:

from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.ext.flask.middleware import XRayMiddleware

# FastAPI
from aws_xray_sdk.core import patch_all
patch_all()  # Patches boto3, requests, etc

@app.middleware("http")
async def xray_middleware(request: Request, call_next):
    with xray_recorder.in_segment('fastapi'):
        response = await call_next(request)
        return response

# Subsegments personalizados
@xray_recorder.capture('database_query')
async def get_user(user_id: int):
    # Query é automaticamente traced
    return await db.query(User).get(user_id)

Alerting

Alarmes obrigatórios:

# Lambda Error Rate
ErrorRateAlarm:
  Metric: Errors / Invocations
  Threshold: > 5%
  Period: 5 minutes
  Severity: P1
  Action: SNS → Slack + Email

# API Latency
LatencyAlarm:
  Metric: P95 Duration
  Threshold: > 1000ms
  Period: 5 minutes
  Severity: P2
  Action: SNS → Slack

# Database CPU
DatabaseCPUAlarm:
  Metric: CPUUtilization
  Threshold: > 80%
  Period: 5 minutes
  Evaluation: 2 datapoints
  Severity: P1
  Action: SNS → Slack + Email

# DLQ Messages
DLQAlarm:
  Metric: ApproximateNumberOfMessagesVisible
  Threshold: >= 1
  Period: 1 minute
  Severity: P0
  Action: SNS → PagerDuty + Slack

Alternativas Consideradas

Opção 1: Datadog ao invés de CloudWatch

Prós: - Interface melhor - Mais features - APM integrado

Contras: - Custo alto ($15-50/host/mês) - Lock-in de vendor - CloudWatch já está disponível

Por que não escolhemos: CloudWatch + X-Ray é suficiente e já está pago (AWS).

Opção 2: Prometheus + Grafana

Prós: - Open source - Flexível - Grafana poderoso

Contras: - Infraestrutura adicional para manter - Overhead de gestão - CloudWatch já integrado

Por que não escolhemos: Overhead não justificado para serverless.

Opção 3: Logs em plain text

Prós: - Mais simples - Legível para humanos

Contras: - Difícil de query - Parsing manual - Não escalável

Por que não escolhemos: JSON structured logs são necessários para CloudWatch Insights.

Análise de Impacto

Impacto Técnico

  • Structured logging obrigatório
  • Correlation IDs em todos requests
  • X-Ray tracing habilitado
  • Dashboards padronizados

Impacto em Negócio

  • ✅ MTTR reduzido em 50%
  • ✅ Problemas detectados proativamente
  • ✅ SLOs mensuráveis e reportáveis
  • ✅ Debugging muito mais rápido
  • ⚠️ Custo CloudWatch aumenta ~$50-100/mês

Riscos

Risco: Overhead de performance por logging

Mitigação: Logging assíncrono, sampling de X-Ray traces.

Plano de Implementação

Fase 1: Structured Logging (Semana 1)

  • Configurar structlog
  • Migrar logs principais
  • Adicionar correlation IDs

Fase 2: Dashboards (Semana 2)

  • Criar dashboards padronizados
  • Golden Signals para serviços principais
  • Documentar

Fase 3: Alerting (Semana 3)

  • Configurar alarmes obrigatórios
  • Integrar com Slack
  • Testar

Fase 4: X-Ray (Semana 4)

  • Habilitar X-Ray tracing
  • Instrumentar código
  • Treinamento do time

Métricas de Sucesso

Após 1 mês: - ✅ 100% logs estruturados (JSON) - ✅ Correlation IDs em todos requests - ✅ Dashboards funcionais

Após 3 meses: - ✅ MTTR reduzido em 50% - ✅ SLOs medidos e reportados - ✅ Zero incidentes não detectados

Referências