Immagina questa situazione: stai lavorando con un database, gestisci un sacco di transazioni, ma qualcosa va storto. L’utente si lamenta, il business urla, e tu nemmeno riesci a capire cosa sia successo davvero. Ecco dove entra in gioco il logging degli errori fatto bene. Serve a:
- Salvare gli errori nel database per analizzarli dopo.
- Recuperare facilmente i dettagli dell’errore: quando è successo, il messaggio e i dati collegati.
- Migliorare il tuo codice lavorando sugli errori tipici che puoi trovare analizzando i log.
Insomma, il logging è come una telecamera di sorveglianza per il tuo database: vedi tutto quello che è andato storto e quando è successo.
Creiamo la tabella error_log
Partiamo, come si dice, dalle basi. Dobbiamo creare una tabella dove salveremo le info sugli errori. La tabella avrà questi campi:
id— identificatore unico dell’errore.error_message— testo dell’errore.error_time— quando è successo l’errore.- (Opzionale)
context— contesto dell’errore, se ci servono dettagli extra.
CREATE TABLE error_log (
id SERIAL PRIMARY KEY, -- Identificatore unico dell’errore
error_message TEXT NOT NULL, -- Messaggio di testo dell’errore
error_time TIMESTAMP NOT NULL DEFAULT NOW(), -- Momento in cui è avvenuto l’errore
context JSONB -- Dati aggiuntivi sull’errore
);
Cosa succede qui?
id SERIAL PRIMARY KEY— questo campo crea un identificatore unico per ogni record in automatico.error_message TEXT NOT NULL— qui ci va il testo dell’errore. Campo obbligatorio.error_time TIMESTAMP NOT NULL DEFAULT NOW()— campo che registra quando è successo l’evento. Se non metti niente, salva l’ora attuale grazie aDEFAULT NOW().context JSONB— opzionale, per salvare info extra, tipo dati sull’operazione dove è successo l’errore.
Dopo aver lanciato il comando CREATE TABLE avrai la struttura pronta per salvare i log nel tuo database.
Esempio di salvataggio errori nella tabella
Ora che la tabella c’è, passiamo alla pratica: salviamo le info sugli errori nella tabella. Scriviamo una funzione che salva il testo dell’errore e il suo timestamp in error_log.
Esempio di funzione per salvare gli errori
CREATE OR REPLACE FUNCTION log_error(p_error_message TEXT, p_context JSONB DEFAULT NULL)
RETURNS VOID AS $$
BEGIN
INSERT INTO error_log (error_message, context)
VALUES (p_error_message, p_context);
END;
$$ LANGUAGE plpgsql;
p_error_message— parametro di input dove passi il testo dell’errore.p_context— parametro opzionale per passare dati extra. Di default èNULL.INSERT INTO error_log (error_message, context)— aggiunge un nuovo record nella tabellaerror_log.DEFAULT NULL— se non passi il contesto, il campo viene riempito conNULL.
Ora, se vuoi salvare un messaggio di errore, puoi chiamare la funzione così:
SELECT log_error('Errore durante l’esecuzione della query', '{"query": "SELECT * FROM data"}');
Questo aggiungerà un nuovo record nella tabella error_log.
Logging automatico degli errori
Scrivere ogni volta SELECT log_error(...) a mano può essere scomodo. Automatizziamo il processo usando la gestione delle eccezioni.
Esempio di funzione con gestione delle eccezioni.
CREATE OR REPLACE FUNCTION divide_numbers(a NUMERIC, b NUMERIC)
RETURNS NUMERIC AS $$
DECLARE
result NUMERIC;
BEGIN
-- Proviamo a fare la divisione
result := a / b;
-- Restituiamo il risultato
RETURN result;
EXCEPTION
WHEN division_by_zero THEN
-- Logghiamo l’errore e passiamo il contesto
PERFORM log_error('Divisione per zero', jsonb_build_object('a', a, 'b', b));
-- Generiamo un’eccezione per l’utente
RAISE EXCEPTION 'Divisione % per % impossibile — il divisore è zero', a, b;
END;
$$ LANGUAGE plpgsql;
- Controllo della divisione: viene eseguito
result := a / b. Seb = 0, PostgreSQL lancia l’eccezionedivision_by_zero. - Gestore delle eccezioni (
EXCEPTION) intercetta l’errore. - Dentro il gestore chiamiamo la funzione
log_errorper salvare l’errore nella tabella insieme ai parametri che hanno causato il problema. - Dopo aver salvato l’errore, con
RAISE EXCEPTIONviene lanciato un nuovo messaggio di errore così anche l’utente viene avvisato.
Esempio di chiamata:
SELECT divide_numbers(10, 0);
Risultato:
- L’utente vedrà l’errore:
Divisione 10 per 0 impossibile — il divisore è zero. - Nella tabella
error_logcomparirà un record sulla divisione per zero.
GO TO FULL VERSION