Home Comunidade Eventos YouTube Networks Desafios // produtos Academy News CTI | CVE Contato

02 - Logs Centralizados (ELK, Loki, CloudWatch Logs)

#cloudwatch#elk#logs#loki#observabilidade
video explicativo
Video explicativoEspaco reservado para o video desta anotação — adicione video: https://youtu.be/... no frontmatter da nota.

Logs Centralizados (ELK, Loki, CloudWatch Logs)

Logs centralizados são o registro detalhado e ordenado de tudo que aconteceu em um sistema, coletado de todas as instâncias e serviços para um destino único, pesquisável e retido por política. Em produção, a centralização é obrigatória porque aplicação em múltiplos contêineres efêmeros torna o acesso a arquivos locais impraticável: o pod morre e leva o histórico junto. A stack de observabilidade de referência open source combina Loki para logs e Prometheus para métricas, enquanto o conjunto ELK, formado por Elasticsearch, Logstash e Kibana, segue como alternativa consolidada para busca full-text pesada, e o CloudWatch Logs cobre cargas ancoradas na AWS. Logs são o lado mais caro da observabilidade por volume, por isso decisões de formato, coleta, indexação e retenção têm impacto direto no custo mensal. Um pipeline bem desenhado transforma logs em ferramenta de investigação rápida; um pipeline mal desenhado transforma em desperdício silencioso.

O problema que a centralização resolve

A busca distribuída por arquivos de log em dezenas de instâncias, via SSH, é lenta, não escalável e não deixa trilha de auditoria de quem acessou o quê. Correlacionar um erro que atravessa três serviços exige contexto compartilhado, como um identificador de correlação, que só funciona se os logs estiverem agregados em um lugar único. A centralização também habilita casos de uso que não existem com arquivos espalhados: alertas baseados em padrões de log, detecção de anomalias, auditoria de acesso e análise de custo por time. Por fim, requisitos regulatórios de retenção e de proteção de dados pessoais precisam de um ponto único de política, em vez de regras manuais em cada servidor.

Logs estruturados e correlation id

O formato estruturado é a decisão de maior impacto em todo o pipeline. Em vez de texto livre que exige parsing frágil, cada linha é um documento JSON com campos previsíveis, o que permite filtrar, agregar e indexar sem expressões regulares. O identificador de correlação, normalmente o trace id da requisição, é o campo que conecta todas as entradas de um mesmo fluxo entre serviços diferentes. O exemplo abaixo mostra o padrão recomendado de linha de log.

{
  "timestamp": "2025-05-12T14:03:22.481Z",
  "level": "ERROR",
  "service": "checkout-api",
  "version": "2.14.1",
  "environment": "production",
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "span_id": "00f067aa0ba902b7",
  "correlation_id": "ped-88213",
  "logger": "PagamentoService",
  "message": "Falha ao autorizar pagamento no provedor",
  "error_type": "PaymentGatewayTimeout",
  "order_id": "ped-88213",
  "latency_ms": 3200
}

Três regras sustentam esse formato: o trace id deve ser propagado de ponta a ponta e impresso em todas as linhas do fluxo; campos sensíveis, como tokens e dados pessoais, devem ser mascarados na biblioteca de logging, nunca no pipeline, onde o vazamento já aconteceu; e exceções devem ser serializadas com stack trace em campo próprio, evitando quebras de linha que fragmentam o documento.

Pipeline de coleta e indexação

O pipeline típico tem quatro estágios: geração na aplicação, coleta por um agente, processamento e entrega ao armazenamento, e indexação para consulta. O agente roda ao lado da aplicação, como sidecar no pod ou DaemonSet no nó, lê stdout e stderr dos contêineres, aplica rotação, compressão e envio em lote. No caminho ELK, o Logstash ou o Fluente Bit processam os eventos, aplicam parsing e roteamento, e o Elasticsearch indexa cada campo em índices invertidos, o que torna qualquer busca muito rápida e o armazenamento caro. No caminho Loki, apenas os labels são indexados, como serviço, ambiente e nível, e o conteúdo completo é comprimido em chunks de objeto, consultado apenas quando a consulta já seleciona os labels. Essa é a diferença arquitetural central entre as duas abordagens e explica a diferença de custo.

# Configuração do Promtail (agente do Loki) para coletar logs de pods
scrape_configs:
  - job_name: kubernetes-pods
    kubernetes_sd_configs:
      - role: pod
    relabel_configs:
      # Promove metadados do pod a labels indexados do Loki
      - source_labels: [__meta_kubernetes_namespace]
        target_label: namespace
      - source_labels: [__meta_kubernetes_pod_label_app]
        target_label: app
    pipeline_stages:
      # Faz o parsing do corpo JSON da linha de log
      - json:
          expressions:
            level: level
            trace_id: trace_id
      # Exceções de runtime viram labels de baixa cardinalidade
      - labels:
          level:

A regra de ouro do Loki é indexar somente labels de cardinalidade baixa e finita, porque cada combinação de labels cria um fluxo separado. Colocar trace id como label quebra o modelo e degrada a performance; o caminho correto é filtrar por labels e usar filtros de linha sobre o conteúdo.

ELK versus Loki versus CloudWatch Logs

As três plataformas resolvem o mesmo problema com compromissos diferentes de custo, busca e operação. A escolha depende do perfil de consulta do time: busca livre em qualquer campo, ou consultas ancoradas em labels de serviço.

Aspecto ELK (Elasticsearch) Loki CloudWatch Logs
Modelo de índice Índice invertido de todos os campos Apenas labels; corpo comprimido Índice por log group e timestamps
Custo por volume Alto, armazenamento e memória caros Baixo, chunks comprimidos em objeto Médio, por GB ingerido e armazenado
Consulta Lucene, KQL, busca full-text poderosa LogQL com métricas sobre logs CloudWatch Logs Insights
Operação Complexa, cluster, shards, JVM tuning Simples, peça única sem cluster pesado Nula, serviço gerenciado
Alertas Watchers, integrado ao stack Suporte nativo via rules Alarmes de métrica de log
Cenário ideal Busca livre pesada, segurança e auditoria Times Kubernetes com custo controlado Cargas AWS sem equipe de plataforma

Uma combinação comum em arquiteturas mistas usa Loki para logs operacionais de aplicação, com retenção curta e consulta por trace id, e Elasticsearch dedicado a domínios que exigem busca semântica, como segurança da informação e logs de acesso HTTP.

Consulta na prática

A consulta é o que transforma o arquivo centralizado em ferramenta de investigação, e cada plataforma tem sua linguagem. O padrão de investigação é o mesmo: filtrar por serviço e janela de tempo, reduzir por erro e saltar para o trace id relacionado. Os exemplos abaixo mostram o mesmo objetivo nas duas linguagens principais.

# Loki: todas as linhas de erro do checkout na última hora
{app="checkout-api", level="ERROR"} |= "PaymentGatewayTimeout"

# Loki: taxa de erros por minuto, calculada sobre o conteúdo dos logs
sum(rate({app="checkout-api", level="ERROR"}[5m])) by (level)

# Loki: listar trace ids distintos que falharam, base do salto para o tracing
{app="checkout-api", level="ERROR"} | json | trace_id != "" | line_format "{{ .trace_id }}"
-- CloudWatch Logs Insights: distribuição de erros por tipo na última hora
fields @timestamp, error_type, trace_id
| filter level = "ERROR"
| stats count() as falhas by error_type
| sort falhas desc
| limit 20

A consulta por trace id é a ponte mais valiosa do ecossistema de observabilidade, porque conecta a linha de log com o span correspondente no tracing. Times maduros linkam automaticamente essas consultas nos painéis, com o trace id como variável de template.

Retenção e custo

Retenção é decisão econômica, não técnica. Cada dia retido multiplica a fatura, por isso o padrão maduro é em camadas: dados quentes de 7 a 30 dias em índice de busca rápida, dados frios de 90 dias em armazenamento comprimido de custo reduzido, e arquivos de longo prazo, quando exigidos por regulação, em objetos quase imutáveis como S3 Glacier. O CloudWatch permite exportar para S3 automaticamente, e o Loki mantém chunks antigos em storage de objeto nativamente. Reduzir volume na origem rende mais do que negociar preço no destino: descartar logs de debug em produção, amestrar logs de sucesso de rotinas repetitivas e filtrar eventos redundantes no agente corta a maior parte do custo sem perda de capacidade de investigação.

Níveis de log e disciplina de escrita

Níveis existem para permitir filtragem progressiva, e a disciplina de uso é o que mantém os níveis úteis.

  • ERROR deve significar intervenção humana necessária ou falha de um fluxo de negócio, e nunca erro esperado de validação, que é WARNING.
  • WARNING registra degradação e situações anormais recuperadas, como retry bem-sucedido após timeout, e merece revisão periódica por padrões recorrentes.
  • INFO conta eventos de negócio relevantes, como pedido criado e pagamento confirmado, em volume controlado, e é o nível padrão em produção.
  • DEBUG detalha o fluxo interno e deve ser ativável em produção por amostragem ou por flag dinâmica, sem necessidade de redeploy.

O anti-padrão mais custoso é registrar a mesma informação em vários níveis ou logar objetos inteiros com dados pessoais; o objetivo é que cada linha responda uma pergunta específica de investigação.

Erros comuns

Os deslizes abaixo concentram a maior parte dos problemas observados em pipelines de log reais.

  • Logs não estruturados em texto livre, que forçam parsing frágil no agente e impedem agregação eficiente por campo.
  • Ausência de trace id nas linhas, o que torna impossível seguir um fluxo entre serviços e obriga investigação manual por timestamp.
  • Dados sensíveis em log, como senhas, cartões e CPF, criando passivo regulatório que nenhum índice caro consegue compensar.
  • Índices criados para todos os campos sem necessidade, gerando custo ELK desproporcional ao valor analítico entregue.
  • Nível ERROR usado para erros esperados, treinando o time a ignorar alertas e escondendo os erros verdadeiros.

Boas práticas

As práticas a seguir consolidam um pipeline sustentável do ponto de vista técnico e financeiro.

  • Padronize o esquema JSON em uma biblioteca interna de logging, com trace id, nome do serviço, versão e ambiente obrigatórios em toda linha.
  • Envie stdout para o agente de coleta e trate arquivos locais como fallback de emergência, nunca como destino primário em contêineres.
  • Defina política de retenção em camadas com custo revisitado trimestralmente, incluindo descarte de eventos sem consumo comprovado.
  • Use o trace id do OpenTelemetry como correlation id, garantindo que logs, métricas e traces apontem para o mesmo fluxo.
  • Monitore o próprio pipeline de log, com alertas de atraso de ingestão e de descarte de eventos, porque pipeline cego é blackout na investigação.