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.
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: 0no 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: 0no 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
replaysOnErrorSampleRatepara0.05por um dia e desativá-lo novamente. - Filtros
before_sendnos 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:
- 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ê. - 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.