AAAbel Aguiar
← Voltar para o blog
observabilidadelogsmétricastraces

Observabilidade para backend: logs, métricas e traces na prática

Como enxergar a saúde de um backend em produção usando sinais úteis para investigar lentidão, erros e gargalos reais

Abel Aguiar·
Observabilidade para backend: logs, métricas e traces na prática

Todo backend parece saudável quando olhamos apenas para o deploy verde. A aplicação subiu, o health check responde, o banco está de pé e ninguém recebeu alerta. Aí começa o problema: usuário reclama que uma tela demora, um job atrasa, uma integração externa falha de vez em quando e o time precisa descobrir o que aconteceu sem ter uma trilha clara.

Esse é o ponto em que observabilidade deixa de ser assunto de ferramenta e vira assunto de operação. Não basta ter um painel bonito. O sistema precisa produzir sinais que ajudem alguém a responder perguntas reais em produção.

Uma pergunta boa costuma ser simples: "por que esse pedido demorou tanto?". Se a resposta exige abrir servidor por servidor, procurar log por horário aproximado e tentar lembrar qual deploy saiu ontem, ainda falta observabilidade.

Observabilidade não começa no painel

Ferramentas ajudam muito, mas elas só mostram o que a aplicação emite. Se o código não registra contexto, não mede duração e não propaga identificadores, a ferramenta vira um depósito de dados incompletos.

Na prática, a base continua sendo logs, métricas e traces.

Logs contam eventos: uma validação falhou, um job começou, uma chamada externa retornou 503. Métricas mostram comportamento agregado: volume de requisições, latência, taxa de erro, tamanho de fila, conexões no banco. Traces mostram o caminho de uma requisição, com o tempo gasto em cada etapa.

O valor aparece quando esses sinais conversam entre si. Um alerta aponta aumento de latência em POST /checkout. A métrica mostra que o p95 saiu de 400ms para 4s. O trace revela que quase todo o tempo está em uma chamada para o antifraude. O log, com o mesmo traceId, mostra timeout em uma região específica. A investigação deixa de ser palpite.

OpenTelemetry é uma boa base para padronizar essa emissão de sinais. Ele não é uma tela final, mas um jeito consistente de instrumentar aplicação e exportar traces, métricas e logs para a stack que você escolher.

Log precisa contar uma história curta

Um log como "erro ao processar pedido" parece útil no momento em que você escreve, mas quase não ajuda quando o incidente chega duas semanas depois. Qual pedido? Qual etapa? Qual cliente? Qual integração? Qual tentativa?

Prefira logs estruturados, com campos que possam ser filtrados:

{
  "level": "error",
  "service": "billing-api",
  "operation": "charge_customer",
  "orderId": "9842",
  "customerId": "391",
  "traceId": "4fd0a9b8c2",
  "provider": "payments-acme",
  "message": "Payment provider timeout"
}

O texto humano ainda existe, mas os campos são o que permitem buscar, agrupar e criar alerta. Em uma stack com Grafana Loki ou Elastic, isso muda bastante a investigação. Você deixa de caçar frases soltas e passa a filtrar por serviço, rota, cliente, operação ou traceId.

Também vale escolher bem o nível do log. Se tudo é error, nada é urgente. Se falha esperada de validação vira erro técnico, o painel fica vermelho sem necessidade. Log bom separa evento de negócio, falha recuperável e falha que realmente exige ação.

Correlation ID é barato e salva horas

Um correlation ID conecta tudo que pertence ao mesmo fluxo. A requisição entra com um identificador, esse valor aparece nos logs, segue para chamadas internas, entra em mensagens de fila e volta na resposta de erro quando fizer sentido.

Sem isso, a investigação fica aproximada: procurar por usuário, horário, rota e mensagem parecida. Funciona em ambiente pequeno. Em produção com volume alto, vira tentativa e erro.

Em APIs, eu gosto de aceitar um cabeçalho como X-Correlation-ID quando o consumidor já manda um valor, ou gerar um novo no gateway ou middleware. Se o time usa tracing distribuído, o padrão traceparent também resolve bem porque carrega contexto entre serviços.

O importante é não deixar esse identificador morrer na primeira camada. Se a requisição cria um job, o job precisa carregar o mesmo contexto. Se chama uma API externa, o log dessa chamada precisa registrar o mesmo valor.

Métrica boa representa experiência

CPU, memória e disco são importantes, mas não explicam tudo. Um backend pode estar com CPU baixa enquanto o usuário espera dez segundos por uma consulta travada no banco.

Para API, comece por quatro sinais: volume, erro, latência e saturação. Quantas requisições chegam? Quantas falham? Quanto tempo demoram? Qual recurso está perto do limite?

Um exemplo simples com Prometheus seria acompanhar contadores de requisição por rota e histogramas de duração. Depois, no Grafana, você monta painéis que mostram taxa de erro e latência p95/p99 por endpoint.

Percentil importa porque média mascara sofrimento. Uma média de 200ms pode parecer ótima, mas se o p99 está em 8s, alguns usuários estão vivendo outra realidade. Em backend, p95 e p99 contam a parte da história que a média costuma esconder.

Também inclua métricas de domínio quando fizer sentido. Em um sistema de cobrança, "pagamentos aprovados por minuto" pode ser mais útil do que CPU. Em filas, "idade da mensagem mais antiga" costuma dizer mais que apenas "quantidade de mensagens".

Trace mostra onde o tempo foi gasto

Trace é especialmente útil quando uma requisição passa por várias etapas. Você vê o tempo no controller, no serviço, no banco, no cache, na fila e nas chamadas HTTP externas.

Imagine uma rota de emissão de documento. O usuário reclama de lentidão. Sem trace, o debate começa: talvez seja banco, talvez seja rede, talvez seja o serviço externo. Com trace, você enxerga que a API gastou 120ms validando dados, 80ms consultando banco e 5s aguardando o provedor de assinatura digital.

Esse tipo de visibilidade reduz discussão baseada em impressão. Em monolitos, traces ajudam a encontrar trechos lentos dentro do próprio processo. Em sistemas distribuídos, ajudam a entender como uma chamada atravessa vários serviços.

Ferramentas como Jaeger e Sentry Performance podem ser bons caminhos dependendo do tamanho do time e da stack. O mais importante é começar pelos fluxos críticos, não tentar instrumentar o sistema inteiro sem critério.

Alerta precisa pedir uma ação

Alerta ruim ensina o time a ignorar alerta. Ele toca de madrugada, ninguém sabe o que fazer, no dia seguinte alguém silencia e pronto: o sistema segue barulhento e pouco confiável.

Um alerta bom tem uma condição clara, impacto provável e uma ação esperada. "Latência p95 do checkout acima de 2s por 10 minutos" é melhor do que "CPU acima de 70%" quando o problema que importa é experiência do usuário. "Fila de emissão com mensagem mais antiga acima de 15 minutos" é melhor do que apenas "fila tem muitas mensagens".

Também é importante diferenciar sintoma de causa. Usuário não sente CPU. Usuário sente lentidão, erro, atraso, indisponibilidade. Alerta operacional pode usar recurso interno, mas precisa estar conectado a impacto real.

Grafana Alerting ajuda a criar regras em cima de métricas e logs, mas a parte difícil continua sendo escolher bons limites. Depois de cada incidente, revise alertas: o que avisou tarde, o que não avisou e o que avisou sem necessidade.

Dashboard não é decoração

Dashboard bom responde pergunta. Se ele só mostra vinte gráficos coloridos que ninguém usa durante incidente, ele é mais vitrine do que ferramenta.

Para backend, um painel inicial pode ser simples: HTTP, banco, filas e integrações externas. No bloco HTTP, acompanhe volume, erro e latência por rota. No banco, conexões, queries lentas e locks quando fizer sentido. Em filas, backlog, idade da mensagem mais antiga, taxa de processamento e DLQ. Em integrações, latência, erro e timeout por provedor.

O painel também precisa mostrar versão da aplicação ou marcação de deploy. Muitas investigações começam com uma pergunta direta: "isso começou depois da última versão?". Se o dashboard mostra deploy junto com latência e erro, a resposta aparece mais rápido.

Cuidado com dados sensíveis

Observabilidade não pode virar vazamento organizado. Logs e traces não devem carregar senha, token, documento completo, payload sensível ou dado pessoal sem necessidade.

Mascarar dados não é detalhe. Em sistemas críticos, defina política de retenção, controle de acesso e quais campos podem ser registrados. Um log bom ajuda a investigar sem expor mais informação do que precisa.

Uma regra prática: registre identificadores e contexto operacional, não cópias completas de dados sensíveis. Se precisar guardar payload para auditoria, trate como auditoria, com retenção e acesso próprios.

Um caminho pragmático

Se o backend ainda tem pouca observabilidade, eu começaria pequeno:

  1. Criar ou propagar correlation ID em toda requisição.
  2. Transformar logs importantes em JSON com campos estáveis.
  3. Medir latência, erro e volume por rota crítica.
  4. Instrumentar traces nos fluxos mais sensíveis.
  5. Monitorar filas por backlog, idade da mensagem e DLQ.
  6. Criar alertas apenas para condições que exigem ação.
  7. Revisar dashboards depois de incidentes reais.

Isso já muda a conversa. Em vez de "acho que foi o banco", o time passa a dizer "o p95 subiu no checkout, começou depois do deploy das 14h, os traces mostram timeout no provedor X e os logs têm o mesmo traceId nos jobs afetados".

Conclusão

Observabilidade é a capacidade de investigar produção com evidência. Logs contam eventos, métricas mostram comportamento e traces revelam caminho. Separados, ajudam. Conectados por contexto, viram uma ferramenta de operação muito mais forte.

Não precisa começar com a stack mais cara nem com dezenas de painéis. Comece pelos fluxos que mais machucam o usuário ou o negócio. Instrumente bem, crie poucos alertas acionáveis e melhore depois de cada incidente.

Com o tempo, o backend deixa de ser uma caixa fechada. Ele passa a contar o que está acontecendo, onde está doendo e qual caminho seguir para corrigir.

Posts relacionados