Pacchetto iniziale di osservabilità in produzione per il giorno uno: i log, le metriche e i trace minimi da aggiungere, più un semplice flusso di triage per segnalazioni “è lento”.

La prima cosa che si rompe raramente è l'intera app. Di solito è un singolo passo che all'improvviso si sovraccarica, una query che andava bene nei test, o una dipendenza che comincia a dare timeout. Gli utenti reali portano varietà reale: telefoni più lenti, reti instabili, input strani e picchi di traffico nei momenti meno opportuni.
Quando qualcuno dice “è lento”, può significare cose molto diverse. La pagina può impiegare troppo a caricarsi, le interazioni possono laggare, una singola chiamata API può andare in timeout, i job in background possono accumularsi, o un servizio di terze parti può trascinare tutto giù.
Per questo servono segnali prima delle dashboard. Il giorno uno non ti servono grafici perfetti per ogni endpoint. Ti servono abbastanza log, metriche e trace per rispondere in fretta a una domanda: dove va il tempo?
C'è anche un rischio reale nel sovra-strumentare troppo presto. Troppi eventi creano rumore, costano soldi e possono persino rallentare l'app. Peggio ancora, i team smettono di fidarsi della telemetria perché sembra disordinata e incoerente.
Un obiettivo realistico per il giorno uno è semplice: quando ricevi un report “è lento”, devi poter trovare il passo lento in meno di 15 minuti. Dovresti essere in grado di dire se il collo di bottiglia è nel rendering client, nell'handler API e nelle sue dipendenze, nel database o nella cache, o in un worker in background o servizio esterno.
Esempio: un nuovo flusso di checkout sembra lento. Anche senza montagne di tooling, vuoi poter dire “il 95% del tempo è nelle chiamate al provider di pagamenti” oppure “la query del carrello sta scansionando troppe righe”. Se costruisci app velocemente con strumenti come Koder.ai, quella baseline del giorno uno conta ancora di più, perché la velocità di rilascio serve a poco se non riesci a fare debug rapidamente.
Un buon pacchetto iniziale di osservabilità in produzione usa tre diverse “viste” della stessa app, perché ognuna risponde a una domanda diversa.
I log raccontano la storia. Dicono cosa è successo per una richiesta, un utente o un job in background. Una riga di log può dire “payment failed for order 123” o “DB timeout after 2s”, più dettagli come request ID, user ID e il messaggio di errore. Quando qualcuno segnala un problema isolato, i log sono spesso il modo più veloce per confermare che è successo e chi ne è stato coinvolto.
Le metriche sono il tabellone. Sono numeri che puoi trendare e su cui impostare alert: rate di richieste, tasso di errori, percentili di latenza, CPU, profondità delle code. Le metriche ti dicono se qualcosa è raro o diffuso e se sta peggiorando. Se la latenza è salita per tutti alle 10:05, le metriche lo mostreranno.
I trace sono la mappa. Un trace segue una singola richiesta mentre attraversa il sistema (web -> API -> database -> terze parti). Mostra dove si spende il tempo, passo dopo passo. Questo è importante perché “è lento” quasi mai è un grande mistero: di solito è un singolo hop lento.
Durante un incidente, un flusso pratico assomiglia a questo:
Una regola semplice: se dopo pochi minuti non riesci a indicare un singolo collo di bottiglia, non ti servono più alert. Ti servono trace migliori e ID coerenti che colleghino trace e log.
La maggior parte degli incidenti “non riusciamo a trovarlo” non è causata da dati mancanti. Succede perché la stessa cosa viene registrata in modo diverso tra i servizi. Alcune convenzioni condivise sin dal giorno uno fanno collimare log, metriche e trace quando hai bisogno di risposte rapide.
Inizia scegliendo un nome servizio per ogni unità deployable e mantienilo stabile. Se “checkout-api” diventa “checkout” in metà delle dashboard, perdi storico e rompi gli alert. Fai lo stesso per le etichette d'ambiente. Scegli un piccolo set come prod e staging e usali ovunque.
Poi rendi ogni richiesta facile da seguire. Genera un request ID al bordo (API gateway, web server o primo handler) e trasportalo nelle chiamate HTTP, nelle code di messaggi e nei job in background. Se un ticket di supporto dice “era lento alle 10:42”, un singolo ID ti permette di estrarre i log e il trace esatti senza indovinare.
Un set di convenzioni che funziona bene il giorno uno:
Accordati sulle unità di tempo fin da subito. Scegli i millisecondi per la latenza API e i secondi per i job più lunghi, e mantienili. Le unità miste creano grafici che sembrano corretti ma raccontano la storia sbagliata.
Un esempio concreto: se ogni API registra duration_ms, route, status e request_id, allora un report come “checkout è lento per il tenant 418” diventa un filtro rapido, non un dibattito da dove partire.
Se puoi fare una sola cosa nel tuo pacchetto iniziale di osservabilità in produzione, rendi i log facili da cercare. Questo inizia con log strutturati (di solito JSON) e gli stessi campi in tutti i servizi. I log in testo libero vanno bene per lo sviluppo locale, ma diventano rumore quando hai traffico reale, retry e istanze multiple.
Una buona regola: registra quello che userai davvero durante un incidente. La maggior parte dei team deve rispondere a: Qual era la richiesta? Chi l'ha fatta? Dove ha fallito? Cosa ha toccato? Se una riga di log non aiuta con una di queste domande, probabilmente non dovrebbe esistere.
Per il giorno uno, mantieni un piccolo set coerente di campi così puoi filtrare e unire eventi tra i servizi:
Quando avviene un errore, loggalo una sola volta, con contesto. Includi un tipo di errore (o codice), un messaggio breve, uno stack trace per gli errori server e la dipendenza a monte coinvolta (per esempio: postgres, payment provider, cache). Evita di ripetere lo stesso stack trace a ogni retry. Invece, allega il request_id così puoi seguire la catena.
Esempio: un utente segnala che non riesce a salvare le impostazioni. Una sola ricerca per request_id mostra un 500 su PATCH /settings, poi un timeout downstream verso Postgres con duration_ms. Non ti servivano i payload completi, solo la route, user/session e il nome della dipendenza.
La privacy è parte del logging, non un compito futuro. Non registrare password, token, header di auth, corpi di richiesta completi o PII sensibili. Se devi identificare un utente, registra un ID stabile (o un valore hashato) invece di email o numeri di telefono.
Se costruisci app su Koder.ai (React, Go, Flutter), vale la pena integrare questi campi in ogni servizio generato fin dall'inizio così non finisci per “sistemare i log” durante il primo incidente.
Un buon pacchetto iniziale di osservabilità in produzione parte con un piccolo set di metriche che rispondono a una domanda veloce: il sistema è sano ora, e se no, dove fa male?
La maggior parte dei problemi in produzione si manifesta con quattro “segnali d'oro”: latenza (risposte lente), traffico (carico cambiato), errori (fallimenti) e saturazione (una risorsa condivisa è al massimo). Se vedi questi quattro segnali per le parti principali della tua app, puoi triageare la maggior parte degli incidenti senza indovinare.
La latenza va fatta vedere con percentili, non con medie. Traccia p50, p95 e p99 così vedi quando un piccolo gruppo di utenti ha problemi. Per il traffico, inizia con richieste al secondo (o job al minuto per i worker). Per gli errori, separa 4xx e 5xx: un aumento dei 4xx spesso indica comportamento client o cambi di validazione; un aumento dei 5xx punta alla tua app o alle sue dipendenze. La saturazione è il segnale “stiamo esaurendo qualcosa” (CPU, memoria, connessioni DB, backlog della coda).
Un set minimo che copre la maggior parte delle app:
Un esempio concreto: se gli utenti segnalano “è lento” e la p95 API sale mentre il traffico rimane stabile, controlla la saturazione. Se l'uso del pool DB è vicino al massimo e i timeout aumentano, hai probabilmente trovato un collo di bottiglia. Se il DB sembra a posto ma la profondità delle code cresce rapidamente, il lavoro in background potrebbe consumare risorse condivise.
Se costruisci app su Koder.ai, tratta questa checklist come parte della definizione di fatto del giorno uno. È più facile aggiungere queste metriche quando l'app è piccola che durante il primo incidente reale.
Se un utente dice “è lento”, i log spesso ti dicono cosa è successo e le metriche quanto spesso. I trace ti dicono dove è andato il tempo dentro una singola richiesta. Quella singola timeline trasforma un reclamo vago in una correzione chiara.
Inizia dal lato server. Strumenta le richieste in ingresso al bordo della tua app (il primo handler che riceve la richiesta) in modo che ogni richiesta possa generare un trace. Il tracing lato client può aspettare.
Un buon trace del giorno uno ha span che mappano alle parti che di solito causano lentezza:
Per rendere i trace ricercabili e comparabili, cattura alcuni attributi chiave e mantienili coerenti tra i servizi.
Per lo span della richiesta in ingresso, registra la route (usa un template come /orders/:id, non l'URL completo), il metodo HTTP, lo status code e la latenza. Per gli span DB, registra il sistema DB (PostgreSQL, MySQL), il tipo di operazione (select, update) e il nome della tabella se è facile da aggiungere. Per le chiamate esterne, registra il nome della dipendenza (payments, email, maps), l'host target e lo status.
Il sampling conta il giorno uno, altrimenti costi e rumore crescono in fretta. Usa una regola semplice head-based: traccia il 100% degli errori e delle richieste lente (se il tuo SDK lo supporta), e campiona una piccola percentuale del traffico normale (come 1–10%). Inizia più alto se il traffico è basso, poi riduci col crescere dell'uso.
Cosa significa “buono”: un trace dove puoi leggere la storia dall'inizio alla fine. Esempio: GET /checkout ha impiegato 2.4s, il DB ha speso 120ms, la cache 10ms e una chiamata di pagamento esterna ha preso 2.1s con un retry. Ora sai che il problema è la dipendenza, non il tuo codice. Questo è il nucleo di un pacchetto iniziale di osservabilità in produzione.
Quando qualcuno dice “è lento”, la vittoria più rapida è trasformare quella sensazione vaga in poche domande concrete. Questo flusso di triage del pacchetto iniziale funziona anche se la tua app è appena nata.
Inizia restringendo il problema, poi segui le prove in ordine. Non saltare subito al database.
Dopo aver stabilizzato, fai un piccolo miglioramento: annota cosa è successo e aggiungi un segnale mancante. Per esempio, se non riuscivi a dire se la lentezza era solo in una regione, aggiungi un tag di regione alle metriche di latenza. Se hai visto uno span DB lungo senza sapere quale query, aggiungi etichette di query con attenzione, o un campo “query name”.
Un esempio veloce: se la p95 di checkout sale da 400 ms a 3 s e i trace mostrano uno span di 2.4 s nella chiamata di pagamento, puoi smettere di discutere sul codice e concentrarti sul provider, sui retry e sui timeout.
Quando qualcuno dice “è lento”, puoi perdere un'ora solo per capire cosa intende. Un pacchetto iniziale di osservabilità in produzione è utile solo se ti aiuta a restringere il problema velocemente.
Inizia con tre domande chiarificatrici:
Poi guarda qualche numero che di solito ti indica dove andare dopo. Non cercare la dashboard perfetta. Vuoi solo segnali “peggiori del normale”.
Se la p95 è salita ma gli errori sono stabili, apri un trace per la route più lenta negli ultimi 15 minuti. Un singolo trace spesso mostra se il tempo è speso nel database, in una API esterna o in attese su lock.
Poi fai una ricerca nei log. Se hai un report utente specifico, cerca per request_id (o correlation ID) e leggi la timeline. Se non ce l'hai, cerca il messaggio di errore più comune nella stessa finestra temporale e verifica se coincide con la lentezza.
Infine, decidi se mitigare ora o approfondire. Se gli utenti sono bloccati e la saturazione è alta, una mitigazione rapida (scalare, rollback o disabilitare una feature non essenziale) può comprare tempo. Se l'impatto è ridotto e il sistema è stabile, continua l'indagine con trace e slow query log.
Poche ore dopo un rilascio, arrivano ticket di supporto: “Il checkout impiega 20–30 secondi.” Nessuno riesce a riprodurlo localmente, così iniziano le ipotesi. Qui il pacchetto iniziale ripaga.
Prima vai sulle metriche e confermi il sintomo. Il grafico della latenza p95 per le richieste HTTP mostra un picco chiaro, ma solo per POST /checkout. Altre route sono normali e il tasso di errori è stabile. Questo restringe il problema da “tutto il sito è lento” a “un endpoint è peggiorato dopo il rilascio”.
Poi apri un trace per una richiesta lenta POST /checkout. Il waterfall del trace rende l'autore del problema ovvio. Due esiti comuni:
PaymentProvider.charge impiega 18 secondi, con la maggior parte del tempo in attesa.DB: insert order è lento, mostrando una lunga attesa prima che la query ritorni.Ora valida con i log, usando lo stesso request ID del trace (o il trace ID se lo memorizzi nei log). Nei log di quella richiesta vedi avvisi ripetuti come “payment timeout reached” o “context deadline exceeded”, più retry aggiunti nella nuova release. Se è la strada del database, i log possono mostrare messaggi di lock o la query lenta che è stata registrata sopra la soglia.
Con tutti e tre i segnali allineati, la correzione diventa semplice:
La chiave è che non hai fatto caccia. Le metriche hanno indicato l'endpoint, i trace il passo lento e i log hanno confermato la modalità di errore con la richiesta esatta in mano.
La maggior parte del tempo di incidente si perde per gap evitabili: i dati ci sono, ma sono rumorosi, rischiosi o manca il dettaglio che ti collega sintomo e causa. Un pacchetto iniziale di osservabilità in produzione aiuta solo se resta utilizzabile sotto stress.
Una trappola comune è loggare troppo, specialmente i corpi delle richieste grezzi. Sembra utile finché non paghi enormi storage, le ricerche diventano lente e catturi accidentalmente password, token o dati personali. Preferisci campi strutturati (route, status code, latency, request_id) e logga solo piccoli frammenti di input esplicitamente permessi.
Un altro spreco di tempo è avere metriche apparentemente dettagliate ma impossibili da aggregare. Label ad alta cardinalità come user ID completi, email o numeri d'ordine unici possono esplodere il numero di serie metriche e rendere le dashboard inaffidabili. Usa label grossolane (route name, metodo HTTP, classe di status, nome dipendenza) e tieni le informazioni utente-specifiche nei log.
Errori che bloccano ripetutamente diagnosi rapide:
Un piccolo esempio pratico: se la p95 di checkout sale da 800ms a 4s, vuoi rispondere in pochi minuti a due domande: è iniziato subito dopo un deploy, e il tempo è speso nella tua app o in una dipendenza (DB, payment provider, cache)? Con percentili, un tag di release e trace con route e nomi dipendenza chiari, ci arrivi rapidamente. Senza, bruci tempo in discussioni e ipotesi.
Il vero vantaggio è la coerenza. Un pacchetto iniziale di osservabilità aiuta solo se ogni nuovo servizio viene spedito con le stesse basi, nominate nello stesso modo e facili da trovare quando qualcosa si rompe.
Trasforma le scelte del giorno uno in un template breve che il team riusa. Tienilo piccolo ma specifico.
Crea una vista “home” che chiunque possa aprire durante un incidente. Uno schermo dovrebbe mostrare richieste al minuto, tasso di errori, p95 di latenza e la tua metrica di saturazione principale, con filtri per environment e version.
Mantieni l'alerting minimo all'inizio. Due alert ne coprono molti: un picco di errori su una route chiave e un picco di p95 sulla stessa route. Se ne aggiungi altri, assicurati che ciascuno abbia un'azione chiara.
Infine, imposta una review mensile ricorrente. Rimuovi alert rumorosi, stringi la nomenclatura e aggiungi un segnale mancante che avrebbe fatto risparmiare tempo nell'ultimo incidente.
Per integrare questo nel processo di build, aggiungi una “porta di osservabilità” alla checklist di rilascio: niente deploy senza request ID, tag di versione, la vista home e i due alert di base. Se spedisci con Koder.ai, puoi definire questi segnali del giorno uno in modalità pianificazione prima del deploy, poi iterare in sicurezza usando snapshot e rollback quando devi adattare rapidamente.
Inizia dal primo punto dove gli utenti entrano nel sistema: il web server, l'API gateway o il tuo primo handler.
request_id e trasportalo in ogni chiamata interna.route, method, status e duration_ms per ogni richiesta.Questo di solito ti porta rapidamente a un endpoint specifico e a una finestra temporale precisa.
Punta a questo obiettivo di base: sii in grado di identificare il passo lento in meno di 15 minuti.
Non servono dashboard perfette il primo giorno. Ti servono segnali sufficienti per rispondere a:
Usali insieme, perché ciascuno risponde a una domanda diversa:
Durante un incidente: conferma l'impatto con le metriche, trova il collo di bottiglia con i trace, spiegalo con i log.
Scegli un piccolo insieme di convenzioni e applicale ovunque:
Preferisci log strutturati (spesso JSON) con le stesse chiavi ovunque.
Campi minimi che ripagano subito:
Inizia con le quattro “golden signals” per ogni componente principale:
Poi aggiungi una piccola checklist per componente:
Strumenta prima il lato server in modo che ogni richiesta in ingresso possa produrre un trace.
Un trace utile del giorno uno include span per:
Rendi gli span ricercabili con attributi coerenti come (in forma template), e un nome di dipendenza chiaro (per esempio , , ).
Una semplice impostazione sicura di default è:
Inizia con percentuali più alte quando il traffico è basso, poi riduci col crescere dell'uso.
L'obiettivo è mantenere i trace utili senza far esplodere costi o rumore, e avere comunque esempi del percorso lento per diagnosticarlo.
Usa un flusso ripetibile che segua le prove:
Questi errori consumano tempo (e talvolta soldi):
service_name stabile, environment (come prod/staging) e versionrequest_id generato al bordo e propagato in chiamate e jobroute, method, status_code e tenant_id (se multi-tenant)duration_ms)L'obiettivo è che un unico filtro funzioni attraverso i servizi invece di ricominciare ogni volta.
timestamp, level, service_name, environment, versionrequest_id (e trace_id se disponibile)route, method, status_code, duration_msuser_id o session_id (un ID stabile, non un'email)Registra gli errori una sola volta con contesto (tipo/codice dell'errore + messaggio + nome della dipendenza). Evita di ripetere lo stesso stack trace ad ogni retry.
routestatus_codepaymentspostgrescacheAnnota il segnale mancante che avrebbe reso tutto più veloce da diagnosticare e aggiungilo dopo.
Mantieni le cose semplici: ID stabili, percentili, nomi di dipendenze chiari e tag di versione ovunque.