Home Projetos & Releases BigBangcraft Blog Sobre & Carreira
Arquitetura & CTO 7 min de leitura 12 visualizações
Raw .md

O mínimo de observabilidade para descobrir o que quebrou sem pagar a conta do New Relic

PD

Pedro Dalben

CTO no Integrar Plus • Publicado em 24 de September de 2026

O mínimo de observabilidade para descobrir o que quebrou sem pagar a conta do New Relic

Toda vez que a fatura de uma plataforma de APM chega no fim do mês, alguém na equipe repete a mesma frase para justificar o rombo: não dá para operar produção às cegas. A promessa dessas ferramentas proprietárias sempre parece irresistível na página de vendas. Você instala um agente no runtime da aplicação, ele espalha ganchos em cada biblioteca do ecossistema e cospe dezenas de painéis automáticos com tracing distribuído, tempos de resposta por camada e gráficos de dispersão. Pouco tempo depois, o custo dessa telemetria começa a rivalizar com a despesa de todos os servidores de processamento e banco somados. O pior momento, contudo, acontece quando o sistema cai em pleno sábado e a equipe passa meia hora perdida entre centenas de abas coloridas sem saber exatamente qual componente travou.

Nas discussões sobre monitoramento, vejo dois grupos muito barulhentos defendendo caminhos opostos. O primeiro é o time corporativo da instrumentação total, que afirma que qualquer arquitetura moderna precisa de OpenTelemetry completo, amostragem densa de traces e alertas complexos baseados em anomalias estatísticas. Para esse grupo, quem não rastreia cada método individual dentro de um monólito está operando no escuro. O segundo grupo é o dos minimalistas do terminal, que insistem que conectar via terminal no servidor, olhar o consumo de memória no topo dos processos e rodar filtros manuais nos arquivos de log resolve qualquer incidente.

Discordo profundamente das duas posturas. A instrumentação exaustiva terceiriza para o fornecedor SaaS a obrigação de entender o próprio sistema, cobrando preços abusivos por um volume gigantesco de dados que ninguém jamais consulta fora de incidentes raros. Por outro lado, a aposta ingênua no terminal puro falha assim que o tráfego cresce. Tentar caçar uma lentidão intermitente abrindo arquivos de texto de vários gigabytes enquanto o pool de conexões do banco esgota é uma receita infalível para prolongar o tempo de indisponibilidade.

Na minha rotina operando monólitos em Ruby on Rails e PostgreSQL dentro de servidores virtuais dedicados, percebi que a grande maioria das falhas graves não exige correlações estatísticas exóticas. Elas se concentram em três origens conhecidas: exceções não capturadas no código, contenção no banco de dados ou saturação de recursos da máquina. Para responder à pergunta que realmente importa durante uma crise, que é entender o que quebrou e onde a execução parou, você precisa de um conjunto modesto e direto de sinais técnicos.

Rastreamento de exceções com contexto de execução

Saber que o servidor web começou a devolver respostas com código 500 é útil para acordar quem está de plantão, mas não serve para corrigir o defeito. O primeiro componente que precisa existir em qualquer aplicação séria é um capturador centralizado de exceções, como o Sentry (seja hospedado em instância própria ou no plano inicial gerenciado) ou alternativas enxutas da comunidade.

O papel dessa camada não é registrar texto livre. O capturador precisa registrar o stack trace completo, os parâmetros sanitizados da requisição que disparou o erro, o identificador do usuário que sofreu o problema e, principalmente, a versão do deploy.

Quando um release novo sobe e uma tela quebra, eu não quero investigar métricas de latência de rede. Eu preciso abrir uma única tela, ver que a linha 42 do arquivo de conciliação tentou chamar um método nulo e verificar qual commit alterou aquela rotina nas últimas duas horas. Ter esse contexto estruturado reduz o tempo de diagnóstico de quarenta minutos para três minutos.

O banco de dados entrega a causa raiz

Em monólitos tradicionais, a camada de aplicação costuma ser relativamente simples de escalar horizontalmente adicionando processos ou nós de processamento. O estrangulamento quase sempre mora na camada de persistência.

A maior parte das lentidões que os APMs caros tentam pintar como gargalos complexos de código são, na verdade, duas coisas triviais no PostgreSQL: uma transação segurando lock exclusivo em uma tabela ou consultas mal planejadas consumindo todo o I/O do disco após um deploy sem índice.

Você não precisa de um agente externo interceptando queries para enxergar isso. O próprio PostgreSQL possui ferramentas nativas prontas para essa finalidade:

A extensão pg_stat_statements precisa estar ligada em qualquer banco de produção. Ela mantém um registro consolidado das consultas executadas, agregando chamadas similares, tempo total gasto, tempo médio e chamadas ao buffer de disco. Com três consultas simples nessa visão administrativa, você descobre quais comandos consomem 80% do tempo de processamento do banco.

Em conjunto com isso, a configuração log_min_duration_statement no arquivo de parâmetros do banco grava diretamente no log qualquer instrução que demore mais do que um limiar estabelecido, por exemplo duzentos milissegundos. Se uma rotina disparou um produto cartesiano acidental ou um encadeamento descontrolado de consultas repetidas, o próprio arquivo de log do banco avisa imediatamente com o texto exato da query.

Logs estruturados com identificador de ponta a ponta

O erro clássico de quem tenta economizar em observabilidade é deixar a aplicação despejar texto desestruturado no disco e esperar que comandos de busca no terminal salvem o dia.

A solução econômica exige apenas disciplina na formatação. O Rails e a maioria dos frameworks web conseguem emitir logs em formato JSON contendo carimbos de data, severidade, controlador, ação e um identificador único de requisição.

Quando esse identificador de requisição é repassado para as filas de processamento assíncrono em segundo plano, o ciclo se fecha. Se um usuário clica em um botão na interface e o trabalho pesado é despachado para um worker, o mesmo identificador precisa acompanhar a execução da tarefa.

Para coletar isso sem gastar fortunas em plataformas analíticas na nuvem, agentes coletores extremamente leves conseguem ler esses arquivos locais e encaminhá-los para um armazenamento centralizado como o Grafana Loki ou até mesmo um servidor dedicado de agregação de texto. Quando um erro acontece, a equipe copia o identificador da requisição fornecido pelo capturador de erros e pesquisa no agregador para ver exatamente a ordem dos acontecimentos que antecederam a falha.

Métricas de máquina sem inventar moda

Por fim, você precisa saber se o servidor está sufocado. Para isso, agentes consolidados do ecossistema do Prometheus, como o coletor de nós do sistema operacional, raspam os sinais vitais da máquina consumindo frações irrisórias de memória e processamento.

Quatro gráficos bastam para o dia a dia: uso de processador, pressão de memória e swap, taxa de utilização de leitura e escrita em disco e saturação de conexões de rede e banco. Não há necessidade de criar telas com trinta visões diferentes de latência de garbage collector se a máquina simplesmente atingiu cem por cento de I/O em virtude de um backup concorrente com o pico de acesso.

Admito que montar essa estrutura exige esforço inicial de configuração, entendimento real do sistema operacional e desenho criterioso de limites de alerta. Um APM de grife vende a ilusão de que basta colocar uma chave de API para ter clareza total sobre o sistema, mas cobra um preço desproporcional por gráficos genéricos que raramente mostram onde a ferida está aberta. Quando o sistema falha, eu não preciso de telemetria cinematográfica. Eu preciso saber a linha do erro, a consulta que travou o banco e o recurso que esgotou. Isso cabe em poucas ferramentas bem ajustadas, sem inflar o custo da infraestrutura.

PD

Sobre Pedro Dalben

CTO e arquiteto full stack especializado em Ruby on Rails, Vue.js, sistemas multi-tenant e infraestrutura distribuída.