2015-06-12 3 views
5

In un'applicazione Flask, voglio aggiungere un campo user_id aggiunto a ogni record del log degli errori che viene prodotto, ogni volta che esiste uno user_id nello flask.session.Registrazione Python: come aggiungere un campo personalizzato a LogRecord e registrare un callback globale per impostarne il valore

mi si avvicinò con la soluzione qui di seguito, ma è hacker, dal momento che non consente la stringa di formato per guidare la formattazione del user_id, e dal momento che l'API di registrazione sembra fornisce modi per personalizzare la registrazione (LoggerAdapter, logging.makeRecord, ecc ...) Immagino che ci debba essere un modo più pulito.

Quale sarebbe il "modo Python" per farlo?

class CustomFormatter(Formatter): 
    def format(self, record): 
     from myapp.core import authenticationManager 
     user_id = authenticationManager.current_user_id_if_authenticated() 
     user_id = "unknown" if user_id is None else str(user_id) 
     return super(F,self).format(record) + ", user_id" + user_id 

risposta

5

Si potrebbe definire a custom filter che inietta un valore per record.user_id. Fatto in questo modo, è possibile definire un formato che comprende %(user_id)s proprio come altri attributi (standard) cronaca:

format='%(asctime)-15s %(name)-5s %(levelname)-8s user_id %(user_id)-15s: %(message)s') 

e poi tutte le chiamate di registrazione verranno automaticamente aggiungere il valore user_id.


import logging 

class UserIDFilter(logging.Filter): 
    """ 
    This is a filter which injects contextual information into the log. 
    """ 
    from myapp.core import authenticationManager 

    def filter(self, record): 
     user_id = authenticationManager.current_user_id_if_authenticated() 
     user_id = "unknown" if user_id is None else str(user_id) 
     record.user_id = user_id 
     return True 


logging.basicConfig(
    level=logging.DEBUG, 
    format='%(asctime)-15s %(name)-5s %(levelname)-8s user_id %(user_id)-15s: %(message)s') 

logger = logging.getLogger(__name__) 
filt = UserIDFilter() 
logger.addFilter(filt) 
+0

Grazie, funziona benissimo, ma dovrebbe essere restituito 1 invece di Vero, come la documentazione prescrivono: https: // docs .python.org/2/library/logging.html # filter-objects? –

+0

Qualsiasi oggetto che valuti su True in un contesto booleano farà. [Lo stato dei documenti] (https://docs.python.org/2/library/logging.html#logging.Logger.filter), "Applica i filtri di questo logger al record e restituisce un valore true se il record deve essere trasformati". Preferisco 'True' su' 1' qui perché enfatizza che stiamo usando la "boolean-ness" dell'oggetto. – unutbu

0

L'(Github page) pacchetto logaugment fa questo:

Per utilizzare:

import logaugment 

logaugment.set(logger, user_id='custom_value') 

Tutte le chiamate acquisizione con logger sarà ora possibile utilizzare il valore 'custom_value' per %(user_id)s nel messaggio di registrazione .

Per installare:

pip install logaugment 

(disclaimer: ho sviluppato questo pacchetto)

+0

È possibile chiamare ripetutamente logaugment.set senza problemi per modificare il valore. –

+0

In alternativa, è possibile specificare un callable che verrà chiamato ogni volta che viene effettuata una chiamata di registrazione. Ciò consentirebbe di calcolare/recuperare in modo dinamico l'ID utente (vedere l'esempio nel pacchetto README). –