engineering7 min de leitura

O que o Sentry revelou: observabilidade, estabilidade e o custo variável do monitoramento do próprio código

Erros em produção expuseram uma divergência de esquema, uma recuperação de transação que falhou e registros pouco úteis. Veja como uma equipe pequena usou o Sentry para corrigir falhas no backend, preparar o monitoramento do navegador e controlar o ruído dos alertas.

K
Ken Jo

Antigamente, as equipes de engenharia ou investiam demais em observabilidade — uma equipe SRE inteira conectava painéis que ninguém consultava — ou simplesmente a ignoravam — só descobriam que o serviço estava fora do ar quando um cliente mandava um e-mail. Em 2026, nenhum dos extremos é aceitável. É preciso saber o que está falhando, sem pagar preços empresariais por um produto independente.

Este relato mostra como nossa integração com o Sentry revelou erros em produção, o que mudamos em resposta e como configuramos o monitoramento para controlar ruído e consumo. Também analisa a evolução das ferramentas de observabilidade para pequenas equipes de engenharia.

Por que os alertas não mostravam falhas no navegador

O backend está conectado ao Sentry desde março. O DSN fica no Google Secret Manager, o segredo é montado no Cloud Run e sentry_sdk.init é executado a cada inicialização. Os alertas por e-mail chegavam. De fora, parecia tudo certo.

Por dentro, não estava. O frontend não tinha conexão com o Sentry. Exceções do navegador, erros de hidratação e falhas no carregamento de chunks eram invisíveis. Além disso, o backend enviava erros de Python para um projeto chamado javascript-nextjs, pois era o único projeto da organização. Os rastreamentos se acumulavam no lugar errado, o agrupamento não ajudava e o painel misturava eventos de várias linguagens.

Para corrigir essa lacuna, era necessário separar falhas do navegador dos erros do backend antes de tratar bugs individuais.

O que os dados mostraram

Analisamos os eventos de erro dos últimos noventa dias. Alguns padrões se destacaram:

Um incidente histórico que já havia sido corrigido

O erro mais frequente no período era um StringDataRightTruncation do Postgres: dezesseis eventos em vinte e dois segundos, vindos do endpoint de cadastro social. A causa era uma divergência clássica de esquema: a definição do modelo permitia uma biografia de 800 caracteres, mas a coluna do banco de produção ainda era VARCHAR(500) de uma migração anterior. Uma pessoa enviou uma biografia pouco acima de 500 caracteres, a camada Pydantic aceitou, e o INSERT falhou.

A migração para ampliar a coluna para 800 já havia sido escrita e foi implantada na manhã seguinte. Mas o problema fundamental — o modelo e o esquema do banco podem divergir sem que ninguém perceba até que um cliente esbarre nisso — continuava aberto.

Fizemos duas mudanças. Primeiro, reforçamos o esquema de requisição do cadastro social: definimos max_length explicitamente para e-mail, nome de exibição e token, para que entradas fora do padrão retornem um 422 limpo em vez de chegar ao banco. Segundo, ampliamos o script de integridade do banco para comparar information_schema.columns.character_maximum_length com os comprimentos esperados pela aplicação. Se uma migração futura reduzir uma coluna abaixo do que o modelo pode produzir, a próxima implantação falhará na verificação de integridade.

Uma sessão que não revertia a transação

Mais adiante havia uma sequência: um OperationalError: server closed the connection unexpectedly em POST /v1/upload, seguido por vários PendingRollbackError no mesmo caminho do código. O Postgres encerrou a conexão no meio de uma consulta, a sessão do SQLAlchemy ficou em estado inválido e o serviço de envio tentou salvar resultados parciais por cima dela. Cada operação seguinte naquela sessão propagava a falha.

A correção é pequena, mas fácil de errar. Quando o pipeline de envio captura uma exceção, a primeira coisa que faz agora é db.rollback(), protegido por seu próprio try/except para que uma falha no rollback não esconda o erro original. Depois, a lógica de salvamento parcial é executada em uma sessão limpa.

Registros que não diziam nada

O manipulador de conclusão do WebSocket registrava err=%s junto à exceção capturada. Para a maioria das exceções, isso imprime algo útil. Mas, para alguns tipos cuja função __str__ retorna uma string vazia, aparecia apenas err=. Recebíamos eventos do Sentry indicando que um salvamento havia falhado sem explicar o motivo.

Trocar para logger.exception(...) e err=%r não custou nada e tornou os próximos eventos autoexplicativos.

Ruído que não queríamos pagar

Os itens restantes na fila não eram bugs. Às vezes, o uvloop gera RuntimeError: unable to perform operation on <TCPTransport closed=True> quando um cliente se desconecta durante o SSL. Esse comportamento é correto e não há o que corrigir; com a cota gratuita de 5.000 erros por mês, porém, ele desperdiça orçamento. Adicionamos um filtro before_send para descartar eventos com esses padrões específicos de exceção e valor. Aplicamos a mesma ideia no frontend a ResizeObserver loop limit exceeded e a ruídos semelhantes do navegador.

Ajustes para o plano gratuito

Em 13 de outubro de 2026, o plano Developer do Sentry inclui gratuitamente 5.000 erros, 5 milhões de spans de rastreamento e 50 reproduções por mês. O rastreamento é medido em spans, não pela antiga cota de unidades de desempenho. Confira o plano atual e estime um orçamento separado para rastreamento; ative-o com uma taxa de amostragem adequada. Preços do Sentry

Nossas configurações:

  • tracesSampleRate: 0 no backend e no frontend. O rastreamento distribuído é realmente útil, mas o volume de spans precisa de um orçamento próprio, baseado no uso medido. Podemos ativá-lo com uma taxa de amostragem baixa quando precisarmos investigar um problema específico.
  • profilesSampleRate: 0 no backend, pelo mesmo motivo.
  • Session Replay desativado no frontend. Mantivemos o código de integração, mas deixamos as duas taxas de amostragem em zero. Se um bug crítico precisar do contexto de reprodução para ser depurado, podemos mudar replaysOnErrorSampleRate para 0.05 por um dia e desativá-lo novamente.
  • Filtros before_send nos dois ambientes para descartar eventos que já sabemos não exigir ação.

As mudanças no backend reduziram o ruído de erros que exigem ação, enquanto a configuração do SDK do navegador ficou preparada para ativação. São etapas diferentes: o código e as configurações de amostragem, por si só, não provam que os eventos do navegador estejam chegando ao projeto correto.

O que está mudando no mercado de observabilidade

Configuramos tudo para o plano gratuito porque o plano gratuito do Sentry é especialmente generoso para um produto hospedado, mas vale entender o cenário mais amplo: a economia dessas ferramentas está mudando.

Algumas coisas mudaram nos últimos doze a dezoito meses:

  • Padrões abertos reduzem o trabalho de migração, mas não o eliminam. Instrumentação compatível com OTLP pode reduzir a dependência de um backend de monitoramento. Consultas, painéis, regras de alerta e recursos específicos do SDK de cada fornecedor ainda exigem planejamento e testes na mudança de plataforma.
  • Hospedagem própria muda a conta de custos. Opções como GlitchTip e pilhas nativas de OTLP oferecem outra rota de monitoramento. Compare armazenamento, backups, atualizações e horas de engenharia com o plano hospedado, não apenas o custo de uma máquina virtual com o preço da assinatura.
  • A depuração assistida por IA amplia o fluxo de trabalho. O Seer do Sentry sugere causas-raiz e correções, enquanto uma integração MCP autorizada pode levar o contexto de erros a um assistente de programação. Toda correção sugerida ainda precisa de reprodução e testes de regressão antes do lançamento.
  • Os limites do plano merecem tanta atenção quanto os recursos. Volume de erros, retenção, amostragem e acesso da equipe podem afetar a conta. Comece pelos sinais necessários e por um orçamento medido de eventos; depois compare os planos com essa carga de trabalho.

Neste retrato da versão, o Sentry atendia às nossas necessidades imediatas de monitoramento de erros. Usar interfaces abertas quando disponíveis oferece mais opções no futuro, mas ainda seria preciso verificar o roteamento dos projetos, alertas, dados retidos e recursos específicos de cada fornecedor antes de migrar.

Verificações de implantação completam o monitoramento

No retrato desta publicação, de 17 de maio de 2026, ainda faltavam duas tarefas de implantação:

  1. Criar um projeto Sentry dedicado a Python para que os erros do backend deixassem de ser registrados em javascript-nextjs. O DSN seria trocado na mesma entrada do Secret Manager que o backend já lê.
  2. Adicionar o DSN do frontend às configurações do projeto na Vercel para que os erros do lado do cliente começassem a chegar. O código já estava presente e era inicializado condicionalmente; faltava apenas a variável de ambiente.

Em qualquer lançamento de monitoramento, envie um evento de teste controlado de cada ambiente e confirme projeto, ambiente, agrupamento e contexto antes de considerar a integração concluída. Projetos separados e uma variável de ambiente são etapas de configuração, não provas de que os eventos chegaram.

Por que isso importa

Quando não se consegue ver o que está falhando, investe-se demais em código defensivo ou de menos e os bugs chegam à produção. As duas situações custam caro. Observabilidade acessível e confiável permite que uma equipe pequena trabalhe como uma maior: detectar regressões antes que os clientes percebam, corrigi-las sem adivinhação e dedicar as horas de engenharia a construir coisas novas.

A lição útil é verificar as duas partes: as correções da aplicação e o caminho de monitoramento que deve revelar a próxima regressão.


← Voltar ao blog