engineering7 min di lettura

Cosa ha rivelato Sentry: osservabilità, stabilità e il costo variabile del monitoraggio del proprio codice

Gli errori in produzione hanno rivelato una discrepanza nello schema, il mancato ripristino di transazioni e log poco utili. Ecco come un piccolo team ha usato Sentry per correggere i guasti del backend, preparare il monitoraggio del browser e contenere il rumore degli avvisi.

K
Ken Jo

Un tempo i team di ingegneria o investivano troppo nell'osservabilità — un intero reparto SRE collegava dashboard che nessuno consultava — oppure la ignoravano del tutto — si scopriva che il servizio era fermo quando scriveva un cliente. Nel 2026 nessuno dei due estremi è accettabile. Bisogna sapere cosa si rompe, senza però pagare tariffe da grande azienda per un prodotto indipendente.

Questo approfondimento mostra come la nostra integrazione con Sentry abbia fatto emergere errori di produzione, cosa abbiamo cambiato di conseguenza e come abbiamo configurato il monitoraggio per controllare rumore e consumi. Esamina anche l'evoluzione degli strumenti di osservabilità per i piccoli team di ingegneria.

Perché gli errori del browser non generavano avvisi

Il backend è collegato a Sentry da marzo. Il DSN si trova in Google Secret Manager, il segreto viene montato in Cloud Run e sentry_sdk.init viene eseguito a ogni avvio. Arrivavano avvisi via email. Dall'esterno sembrava tutto a posto.

In realtà, il frontend non era collegato a Sentry. Eccezioni del browser, errori di hydration e problemi nel caricamento dei chunk erano invisibili. Inoltre il backend inviava gli errori Python a un progetto chiamato javascript-nextjs, perché era l'unico progetto dell'organizzazione. Le stack trace finivano nel posto sbagliato, il raggruppamento non era utile e la dashboard mostrava eventi di linguaggi diversi mescolati.

Per colmare questa lacuna bisognava separare gli errori del browser da quelli del backend prima di intervenire sui singoli bug.

Cosa mostravano i dati

Abbiamo esaminato gli eventi di errore degli ultimi novanta giorni. Sono emersi alcuni schemi:

Un incidente storico che si era già risolto

L'errore più frequente nel periodo era un StringDataRightTruncation di Postgres: sedici eventi in ventidue secondi, provenienti dall'endpoint di registrazione social. La causa era una classica deriva dello schema: la definizione del modello consentiva una biografia di 800 caratteri, ma la colonna del database di produzione era ancora VARCHAR(500) da una migrazione precedente. Un utente aveva inviato una biografia appena oltre i 500 caratteri; il livello Pydantic l'aveva accettata e l'INSERT era fallito.

La migrazione per estendere la colonna a 800 era già stata scritta e distribuita la mattina seguente. Ma il problema alla radice — il modello e lo schema del database possono divergere senza che nessuno se ne accorga finché un cliente non lo provoca — restava irrisolto.

Abbiamo fatto due interventi. Primo, abbiamo rafforzato lo schema delle richieste per la registrazione social: max_length esplicito per email, nome visualizzato e token, così gli input anomali ricevono un 422 pulito invece di arrivare al database. Secondo, abbiamo esteso lo script d'integrità del database per confrontare information_schema.columns.character_maximum_length con le lunghezze previste dall'applicazione. Se una futura migrazione riduce una colonna al di sotto di ciò che il modello può generare, il controllo d'integrità del deploy successivo fallirà.

Una sessione che non riusciva a eseguire il rollback

Più in basso compariva una sequenza: un OperationalError: server closed the connection unexpectedly su POST /v1/upload, seguito da una serie di PendingRollbackError nello stesso percorso del codice. Postgres aveva chiuso la connessione durante una query, la sessione SQLAlchemy era rimasta in uno stato non valido e il servizio di caricamento aveva tentato di salvare risultati parziali al suo interno. Ogni operazione successiva in quella sessione propagava l'errore.

La correzione è piccola, ma facile da sbagliare. Quando la pipeline di caricamento intercetta un'eccezione, ora la prima operazione è db.rollback(), racchiusa in un proprio try/except affinché un errore durante il rollback non nasconda quello originale. Poi la logica di salvataggio parziale viene eseguita su una sessione pulita.

Log che non dicevano più nulla

Il gestore di completamento WebSocket registrava err=%s insieme a un'eccezione intercettata. Per la maggior parte delle eccezioni produce informazioni utili. Ma per alcuni tipi la cui funzione __str__ restituisce una stringa vuota, appariva solo err=. Ricevevamo eventi Sentry che segnalavano un salvataggio non riuscito senza spiegare il motivo.

Passare a logger.exception(...) e err=%r non è costato nulla e rende ogni evento futuro autoesplicativo.

Rumore che non volevamo pagare

Gli elementi rimanenti nella coda non erano bug. A volte uvloop solleva RuntimeError: unable to perform operation on <TCPTransport closed=True> quando un client si disconnette durante SSL. È un comportamento corretto, non qualcosa che possiamo risolvere; con una quota gratuita di 5.000 errori al mese, però, spreca budget. Abbiamo aggiunto un filtro before_send che scarta gli eventi con quei precisi schemi di eccezione e valore. Abbiamo adottato la stessa idea nel frontend per ResizeObserver loop limit exceeded e rumori simili del browser.

Configurazione per il piano gratuito

Al 13 ottobre 2026, il piano Developer di Sentry include gratuitamente 5.000 errori, 5 milioni di span di tracing e 50 replay al mese. Il tracing si misura in span, non con la vecchia quota di unità di prestazione. Verifica il piano corrente e prevedi un budget separato per il tracing; attivalo con una frequenza di campionamento adeguata. Prezzi Sentry

Le nostre impostazioni:

  • tracesSampleRate: 0 sia nel backend sia nel frontend. Il tracing distribuito è davvero utile, ma il volume degli span richiede un budget distinto, definito sulla base dell'uso misurato. Possiamo attivarlo con una frequenza di campionamento contenuta quando serve indagare un problema specifico.
  • profilesSampleRate: 0 nel backend, per lo stesso motivo.
  • Session Replay disattivato nel frontend. Abbiamo lasciato il codice d'integrazione, ma impostato a zero entrambe le frequenze di campionamento. Se un bug critico richiede il contesto di un replay per essere analizzato, possiamo portare replaysOnErrorSampleRate a 0.05 per un giorno e poi disattivarlo.
  • Filtri before_send in entrambi gli ambienti per scartare gli eventi che sappiamo già non richiedere interventi.

Le modifiche al backend hanno ridotto il rumore degli errori su cui intervenire, mentre la configurazione dell'SDK del browser è stata preparata per l'attivazione. Sono traguardi distinti: il codice e le impostazioni di campionamento, da soli, non dimostrano che gli eventi del browser raggiungano il progetto previsto.

Come sta cambiando il mercato dell'osservabilità

Abbiamo configurato tutto per il piano gratuito perché quello di Sentry è particolarmente generoso per un prodotto ospitato, ma vale la pena capire il quadro più ampio: l'economia di questi strumenti sta cambiando.

Negli ultimi dodici-diciotto mesi sono cambiate diverse cose:

  • Gli standard aperti riducono il lavoro di migrazione, ma non lo eliminano. Un'instrumentazione compatibile con OTLP può ridurre il legame con un backend di monitoraggio. Query, dashboard, regole di avviso e funzionalità SDK specifiche del fornitore richiedono comunque pianificazione e test quando si cambia piattaforma.
  • L'hosting autonomo cambia il calcolo dei costi. Soluzioni come GlitchTip e gli stack nativi OTLP offrono un'alternativa per il monitoraggio. Bisogna confrontare archiviazione, backup, aggiornamenti e tempo d'ingegneria con il piano ospitato, non soltanto la fattura di una macchina virtuale con il costo dell'abbonamento.
  • Il debugging assistito dall'IA estende il flusso di lavoro. Seer di Sentry propone cause principali e patch, mentre un'integrazione MCP autorizzata può portare il contesto degli errori in un assistente di programmazione. Ogni correzione proposta richiede comunque riproduzione e test di regressione prima del rilascio.
  • I limiti del piano meritano la stessa attenzione delle funzionalità. Volume degli errori, conservazione, campionamento e accesso del team possono influire sulla fattura. Conviene partire dai segnali necessari e da un budget misurato degli eventi, poi confrontare i piani con quel carico di lavoro.

In questa istantanea della release, Sentry soddisfaceva le nostre esigenze immediate di monitoraggio degli errori. Usare interfacce aperte dove disponibili lascia più opzioni al team in futuro, ma cambiare fornitore richiederebbe comunque di controllare instradamento dei progetti, avvisi, dati conservati e funzionalità specifiche del provider.

I controlli di deploy completano il monitoraggio

Nell'istantanea di questo articolo, datata 17 maggio 2026, restavano due attività di deploy:

  1. Creare un progetto Sentry dedicato a Python, così gli errori del backend non sarebbero più stati registrati sotto javascript-nextjs. Il DSN sarebbe stato sostituito nella stessa voce di Secret Manager già letta dal backend.
  2. Aggiungere il DSN del frontend alle impostazioni del progetto Vercel per iniziare a ricevere gli errori lato client. Il codice era già presente e inizializzato in modo condizionale; mancava soltanto la variabile d'ambiente.

Per ogni avvio del monitoraggio, invia un evento di prova controllato da ciascun ambiente e verifica progetto, ambiente, raggruppamento e contesto prima di dichiarare completa l'integrazione. Creare progetti separati e aggiungere una variabile d'ambiente sono passaggi di configurazione, non prove che gli eventi siano arrivati.

Perché è importante

Quando non si vede cosa si rompe, si investe troppo nel codice difensivo oppure troppo poco e si rilasciano bug. Entrambe le scelte costano. Un'osservabilità economica e affidabile permette a un piccolo team di lavorare come uno più grande: individuare regressioni prima che se ne accorgano i clienti, correggerle senza andare a tentativi e dedicare le ore d'ingegneria a costruire cose nuove.

La lezione utile è verificare entrambe le parti: le correzioni dell'applicazione e il percorso di monitoraggio che dovrebbe rivelare la prossima regressione.


← Torna al blog