modulo 20 di 24 / Ore 41-60

Moduli 17-24 / Checkpoint 60 ore

Esercizio: ricostruire un errore dai log

Leggere una sequenza di log del Registro del laboratorio, ricostruire cosa è successo e individuare dove si è verificato l'errore senza guardare il codice sorgente.

25 minArchitettura del software

Esercizio: ricostruire un errore dai log

Questa lezione appartiene al Modulo 20 — Logging e osservabilità minima.

Cos’è questo esercizio

Hai a disposizione una sequenza di log prodotti dal Registro durante una sessione reale. Devi rispondere a tre domande senza guardare il codice sorgente:

  1. Cosa stava facendo l’utente?
  2. Dove si è verificato l’errore?
  3. Cosa ha causato l’errore?

Questo è il lavoro dell’osservabilità: i log devono essere abbastanza informativi da permettere la diagnosi senza accedere al codice.

Log da analizzare — Scenario A

Leggi questa sequenza di log nell’ordine in cui appare nella console:

[INFO]  prestito_avviato       { strumentoId: "str-042", origine: "ui" }
[INFO]  strumento_trovato      { strumentoId: "str-042", stato: "disponibile" }
[INFO]  regola_verificata      { strumentoId: "str-042", esito: "ok" }
[ERROR] salvataggio_fallito    { operazione: "salva_prestito", errore: "ARCHIVIO_NON_DISPONIBILE" }
[INFO]  messaggio_utente       { testo: "Non riesco a salvare i dati. Riprova tra poco." }

Domande:

  1. Quale operazione stava eseguendo l’utente?
  2. Il dominio ha trovato qualcosa di sbagliato? Come lo sai?
  3. Dove si è verificato l’errore? In quale livello?
  4. L’utente ha ricevuto un messaggio comprensibile?
  5. Cosa faresti per diagnosticare l’errore infrastrutturale?

Log da analizzare — Scenario B

[INFO]  prestito_avviato       { strumentoId: "str-017", origine: "ui" }
[ERROR] strumento_non_trovato  { strumentoId: "str-017" }
[INFO]  messaggio_utente       { testo: "Strumento non trovato. Controlla l'ID." }

Domande:

  1. L’errore è di dominio, applicativo o infrastrutturale?
  2. Quale passo del caso d’uso non ha trovato il dato?
  3. Cosa suggeriresti all’utente per risolvere?
  4. Questo log è sufficiente per diagnosticare il problema senza guardare il codice?

Log da analizzare — Scenario C (log mal fatto)

[INFO]  click ricevuto
[ERROR] Uncaught TypeError: Cannot read properties of undefined (reading 'stato')
        at registraPrestito (application/registraPrestito.js:14)
        at HTMLButtonElement.<anonymous> (presentation/ui.js:32)
[INFO]  operazione completata

Domande:

  1. Questo log permette di capire cosa stava facendo l’utente? Perché no?
  2. Quale informazione manca nel primo [INFO]?
  3. Lo stack trace è utile per il debugging — ma è adatto a essere mostrato all’utente?
  4. L’ultimo [INFO] operazione completata è accurato? Cosa è andato storto?
  5. Come riscriveresti il logging di questo scenario?

Come costruire log leggibili

Dopo aver analizzato i tre scenari, puoi costruire un pattern di logging per il tuo Registro.

Un buon log ha:

  • evento — cosa è successo (prestito_avviato, strumento_non_trovato)
  • contesto — i dati minimi per capire di cosa si tratta (strumentoId, prestitoId)
  • livelloINFO per eventi normali, ERROR per fallimenti
  • mai dati personali — no nomi di studenti, no testo libero dell’utente
// Logger minimale per il Registro (wrapper di console)
const logger = {
  info: (evento, dati = {}) => {
    console.log(`[INFO]  ${evento}`, dati);
  },
  error: (evento, dati = {}) => {
    console.error(`[ERROR] ${evento}`, dati);
  }
};

// Uso nei casi d'uso
async function registraPrestito(comando) {
  logger.info("prestito_avviato", { strumentoId: comando.strumentoId });

  const strumento = await archivioStrumenti.trovaPerId(comando.strumentoId);
  if (!strumento) {
    logger.error("strumento_non_trovato", { strumentoId: comando.strumentoId });
    throw new Error("STRUMENTO_NON_TROVATO");
  }

  logger.info("strumento_trovato", { strumentoId: strumento.id, stato: strumento.stato });
  // ...resto del caso d'uso
}

Procedura guidata

  1. Leggi ogni scenario di log dall’alto in basso, come una storia.
  2. Identifica il punto in cui la storia cambia: dove compare il primo [ERROR]?
  3. Rispondi alle domande per iscritto — senza aprire il codice.
  4. Confronta le tue risposte con il gruppo o col docente.
  5. Per lo Scenario C: riscrivi il logging come vorresti che fosse.

Attività in classe

## Analisi log — mie risposte

Scenario A:
  1. Operazione: 
  2. Problema nel dominio: 
  3. Livello dell'errore: 
  4. Messaggio utente adeguato (sì/no): 
  5. Prossimo passo di diagnosi: 

Scenario B:
  1. Tipo di errore: 
  2. Passo che ha fallito: 
  3. Suggerimento all'utente: 
  4. Log sufficiente (sì/no): 

Scenario C:
  1. Informazione mancante: 
  2. Riscrittura proposta del logging: 

Spiegazione guidata per studiare

Leggere i log è una competenza pratica. Un log ben scritto permette di capire cosa è successo senza riaprire il codice — come un medico che legge un referto invece di riesaminare il paziente da zero.

Il punto centrale è: il log deve raccontare una storia. Ogni riga è un evento. La sequenza degli eventi ricostruisce l’operazione. Il primo [ERROR] indica dove la storia si è interrotta.

Il rischio tipico è il log troppo vago ("click ricevuto", "operazione completata") o il log che espone stack trace tecnici — utili per il developer, non per la diagnosi in produzione. Il punto di equilibrio è: evento + contesto + livello, senza dati personali.

Passo per passo nel progetto

  1. Apri la console del browser mentre usi il tuo Registro.
  2. Esegui tre operazioni: registra uno strumento, apri un prestito, segnala un guasto.
  3. Leggi i log prodotti: raccontano la storia dell’operazione? Si capisce dove sono nel codice?
  4. Se i log sono assenti o confusi, aggiungi logger.info nei casi d’uso principali.
  5. Prova a provocare un errore (strumento inesistente) e verifica che il log lo registri chiaramente.

Esempio da leggere lentamente

// Log di una sessione con due operazioni: una ok, una fallita

[INFO]  strumento_registrato   { strumentoId: "str-051", categoria: "Elettrico" }
[INFO]  prestito_avviato       { strumentoId: "str-051" }
[INFO]  strumento_trovato      { stato: "disponibile" }
[INFO]  regola_verificata      { esito: "ok" }
[INFO]  prestito_salvato       { prestitoId: "pre-001" }
[INFO]  strumento_aggiornato   { stato: "in_prestito" }

[INFO]  prestito_avviato       { strumentoId: "str-999" }
[ERROR] strumento_non_trovato  { strumentoId: "str-999" }

Dalla seconda sequenza si capisce immediatamente: l’utente ha tentato di prestare uno strumento con ID str-999 che non esiste nell’archivio. Nessun dato personale, nessuno stack trace — solo l’evento e il contesto minimo.

Prova di comprensione

  • Riesci a ricostruire la storia dello Scenario A senza guardare il codice?
  • Cosa rende il log dello Scenario C inutilizzabile per la diagnosi?
  • Quale informazione aggiungeresti al log prestito_avviato per renderlo più utile?

Errori da evitare

  • scrivere log così vaghi da non poter ricostruire nulla ("errore", "ok");
  • includere nomi di studenti o testo libero dell’utente nei log;
  • mostrare stack trace completi all’utente nella UI;
  • non loggare nulla e scoprire in retrospettiva di non poter diagnosticare il problema.

Prodotto da consegnare

Può essere:

  • le risposte scritte ai tre scenari di log;
  • la riscrittura del log dello Scenario C;
  • un logger minimale aggiunto al progetto con almeno tre eventi registrati nei casi d’uso principali.

Checklist di chiusura

  • Ho risposto per iscritto alle domande dei tre scenari
  • Ho identificato il livello dell’errore in ogni scenario
  • Ho riscritto il logging dello Scenario C in modo più leggibile
  • Il mio Registro produce log che permettono di ricostruire le operazioni principali
  • I log non contengono nomi di studenti o dati personali

Domande per la revisione

  • Guardando i log del tuo Registro, riesci a ricostruire l’ultima sessione di test?
  • C’è qualche operazione che non produce nessun log? Quale?
  • Come distingueresti un errore applicativo da uno infrastrutturale leggendo solo i log?

Risultato atteso

Alla fine lo studente deve saper dire:

Nello Scenario A, l'errore è [tipo] e si è verificato nel livello [X] perché [motivo].
Nello Scenario C, il log è mal scritto perché [motivo] — lo riscriverei così: [proposta].
Nel mio Registro, ho aggiunto log per [eventi principali].

Se questa spiegazione non è possibile, la lezione non è ancora davvero conclusa.