Handler di Log in Python: gestione dei messaggi di log
Gli handler
dei log in Python, presenti all'interno del modulo logging
,
rappresentano una parte fondamentale della libreria. Gli handler
sono
utilizzati per gestire l'output dei messaggi dei log. Gli handler
determinano dove e come i messaggi dei log vengono inviati.
Un logger
può avere associato a se un numero indefinito di handler
. Alla
scrittura di un messaggio di log, ogni handler
si occupa di capire se il
messaggio è di sua competenza e a chi deve inviarlo.
Ad ogni nuovo messaggio di log inviato su un logger, ogni handler
verifica se
il messaggio ha un livello adeguato del log e successivamente, se il livello è
soddisfatto, spedisce il messaggio alla destinazione stabilita.
Il modulo di logging
offre una molteplicità di handler
predefiniti che
soddisfano la maggior parte delle esigenze degli sviluppatori. In questo
articolo vedrai un elenco degli handler
a disposizione con una spiegazione
del funzionamento di ciascuno.
Prerequisiti
Per la lettura del seguente articolo è opportuno che tu abbia conoscenza del logging in Python e di cosa sono i livelli di log. Per studiare o ripassare questi argomenti puoi leggere gli articoli, Guida Completa al Logging in Python dalla Configurazione di Base alla Configurazione Avanzata e Livelli di Log in Python: Tutto Quello che Devi Sapere per un Logging Efficace.
StreamHandler
Uno StreamHandler
invia i messaggi di log ad uno stream. Il caso più comune è
l'invio alla console sys.stdout
e sys.stderr
, che nei sistemi Unix-like
sono le console predefinite per lo StandardOutput
e StandardError
.
Ogni messaggio scritto sul logger sarà inviato dall'handler
sulla console, a
patto che il livello di log definito sia rispettato.
import logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
logger.addHandler(handler)
logger.debug("pippo")
Nel precedente esempio, l'handler
stampa su console il messaggio pippo
.
FileHandler
Un FileHandler
invia i messaggi di log ad un file. Questo handler
consente
quindi la scrittura dei messaggi su un file prestabilito. Questo tipo di
handler
molto utile poiché in qualsiasi momento consente allo sviluppatore di
capire se il software sta o meno funzionando.
import logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
handler = logging.FileHandler('filehandler.log')
logger.addHandler(handler)
logger.debug("pippo")
La sintassi è molto simile allo StreamHandler
, cambia solo la classe con la
quale creare l'oggetto.
RotatingFileHandler
Il RotatingFileHandler
invia e scrive i messaggi di log su file, così come
avviene nel FileHandler
, ma aggiunge il supporto alla rotazione dei file,
quando raggiungono una dimensione specificata.
Il funzionamento prevede che all'arrivo dei messaggi di log, l'handler prima di scrivere il messaggio sul file controlla in primo luogo se il livello di log è consentito ed in secondo luogo se la dimensione del file di log consente la scrittura del messaggio; se la dimensione è consentita, allora scrive il messaggio nel file di log, altrimenti crea un nuovo file all'interno del quale scrive il messaggio. Contestualmente alla creazione del nuovo file di log, tutti i file precedenti vengono ruotati ossia vengono rinominati con un suffisso numerico che è incrementato di uno.
Dato il seguente frammento di codice:
import logging
from logging.handlers import RotatingFileHandler
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
handler = RotatingFileHandler('filehandler.log', maxBytes=1024, backupCount=5)
logger.addHandler(handler)
logger.debug("Prova Rotating File Handler")
il file di log si chiama filehandler.log
. Ad ogni rotazione il file di log
sul quale l'handler scrive è sempre lo stesso, ma le rotazioni creano i file
con i nomi: filehandler.log.1
, filehandler.log.2
e così via per un numero
massimo imposto dal parametro backupCount
.
I parametri inviati all'oggetto RotatingFileHandler
sono:
- nomefile
maxBytes
: dimensione massima del file di log (oltre la quale il file sarà ruotato)backupCount
: numero di file di backup
TimedRotatingFileHandler
Questo handler
ha lo stesso comportamento del RotatingFileHandler
con la
differenza che la rotazione dei file avviene su intervalli temporali piuttosto
che sulla dimensione dei file.
Supponiamo il seguente esempio:
import logging
from logging.handlers import TimedRotatingFileHandler
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
handler = TimedRotatingFileHandler(
'filehandler.log', when='midnight', interval=1
)
logger.addHandler(handler)
logger.debug("Prova Rotating File Handler")
La rotazione dei log avviene tutte le sere a mezzanotte a prescindere dalla dimensione dei file.
SMTPHandler
L'handler
invia i messaggi di log tramite per email. Questo handler
è molto
utile per gli amministratori di sistema poiché possono essere avvertiti tramite
email che è avvenuto qualche grave malfunzionamento.
import logging
from logging.handlers import SMTPHandler
logger = logging.getLogger(__name__)
handler = SMTPHandler(mailhost=('smtp.example.com', 587),
fromaddr='from@example.com',
toaddrs=['to@example.com'],
subject='Log Message',
credentials=('username', 'password'),
secure=())
handler.setLevel(logging.ERROR)
logger.addHandler(handler)
Il precedente esempio mostra chiaramente la necessità di impostare i parametri
per l'invio della mail, ed inoltre mostra che l'handler
lavora solo con
messaggi con livello di log minimo pari a ERROR
.
HTTPHandler
L'HTTPHandler
invia i messaggi di log ad un server web tramite richieste
HTTP POST
o HTTP GET
. Questo handler
è utile quando si ha necessità di
centralizzare la gestione dei log su un sistema remoto o quando si devono
integrare i propri log con sistemi di terze parti.
import logging
from logging.handlers import HTTPHandler
logger = logging.getLogger(__name__)
handler = HTTPHandler('www.example.com', '/log', method='POST')
logger.addHandler(handler)
SysLogHandler
Il SysLogHandler
invia i messaggi ad un syslog
server. Per utilizzare
questo handler
occorre che sia installato e configurato un server syslog
.
import logging
from logging.handlers import SysLogHandler
logger = logging.getLogger(__name__)
handler = SysLogHandler(address='/dev/log')
logger.addHandler(handler)
SockerHandler
Il SocketHandler
invia i messaggi tramite socket. Questo handler
è utile
quando hai bisogno di inviare i log ad un server remoto tramite socket TCP o
UDP.
Questo handler è molto flessibile e può essere utilizzato per integrare il logging in applicazioni distribuite o per inviare i log a un sistema di logging centralizzato.
import logging
from logging.handlers import SocketHandler
logger = logging.getLogger(__name__)
handler = SocketHandler('localhost', logging.handlers.DEFAULT_TCP_LOGGING_PORT)
logger.addHandler(handler)
QueueHandler
Il QueueHandler
invia i messaggi tramite coda. I messaggi possono essere
gestiti sia con scrittura su file sia su console. L'approccio seguito
dall'handler
è quello di inviare i messaggi ad una coda che si occupa di
inviare gli stessi ad altri handler
per la scrittura.
Il processo di scrittura è perfettamente asincrono e pertanto questo tipo di log non impatta le performance applicative.
import logging
from logging.handlers import QueueHandler
import queue
log_queue = queue.Queue()
logger = logging.getLogger(__name__)
handler = QueueHandler(log_queue)
logger.addHandler(handler)
Conclusioni
Gli handler
dei log in Python offrono una flessibilità significativa per
indirizzare i messaggi di log in diverse destinazioni. Comprendere come
configurare e utilizzare questi handler
ti permette di creare applicazioni
robuste con una gestione efficace dei log.
In questo articolo hai visto gli handler
messi a disposizione dal modulo
Python. Potrai utilizzare questi handler
all'interno dei tuoi progetti per
gestire al meglio il tuo software.