2015-01-05 14 views
10

Il default debug log format per Flask 0.10 èFornire informazioni in più per app.logger di Flask

debug_log_format = 
'-------------------------------------------------------------------------\n% 
%(levelname)s in %(module)s [%(pathname)s:%(lineno)d]:\n%(message)s 
\n-------------------------------------------------------------------------' 

Come faccio a cambiare a questo:

'-------------------------------------------------------------------------\n% 
work_id %(levelname)s in %(module)s [%(pathname)s:%(lineno)d]:\n%(message)s 
\n-------------------------------------------------------------------------' 

dove work_id è un UUID generato in modo casuale per ogni richiesta.

Se il registratore è stato creato da me, posso solo usare un logging.LoggerAdapter e fornire le informazioni supplementari come dict {'work_id': some_uuid}, allora posso accedervi nel record di registro utilizzando record.work_id.

Ma lo app.logger è stato creato da create_logger() in Flask'slogging.py, devo modificare la sorgente Flask per ottenere quello che voglio?

Ho anche pensato di ignorare lo app.logger con il mio logger, come app.logger = my_logger, non sembra giusto.

risposta

8

Via Flask.debug_log_format

solo fare questo:

app.debug = True 
app.debug_log_format = """------------------------------------------------------------------------- 
%(worker_id)s (levelname)s in %(module)s [%(pathname)s:%(lineno)d]:\n%(message)s 
-------------------------------------------------------------------------""" 
app.logger.log("test", extra={"worker_id": request.your_uuid_property) 

Esempio:

import logging 
from flask import Flask, request 
app = Flask(__name__) 

# please replace "request.uuid" with your actual property 
log = lambda msg: app.logger.info(msg, extra={'worker_id': "request.uuid" }) 

@app.route("/") 
def hello(): 
    log("hello world") 
    return "Hello World!" 

if __name__ == "__main__": 
    app.debug_log_format = """------------------------------------------------------------------------- 
    %(worker_id)s in %(module)s [%(pathname)s:%(lineno)d]: 
    %(message)s 
    -------------------------------------------------------------------------""" 
    app.debug = True 
    log("hello world") 
    app.run() 

Via Handler e di formattazione del modulo di registrazione standard di

Flask utilizza la registrazione in qualsiasi modo, quindi è possibile utilizzare logging.Handler e logging.Formatter per ottenere il pallone esterno. Un esempio generico può essere trovato here. argomento avanzato di configurazione della registrazione può essere trovato in the doc e nel cookbook

Un esempio su misura per quanto riguarda la tua domanda è:

import logging 
from flask import Flask 
app = Flask(__name__) 

class CustomFormatter(logging.Formatter): 
    def format(self, record): 
     record.worker_id = "request.uuid" # replace this with your variable 
     return super(CustomFormatter,self).format(record) 

@app.route("/") 
def hello(): 
    app.logger.info("hello world") 
    return "Hello World!" 

if __name__ == "__main__": 
    custom_format = """------------------------------------------------------------------------- 
    %(worker_id)s in %(module)s [%(pathname)s:%(lineno)d]: 
    %(message)s 
    -------------------------------------------------------------------------""" 
    app.debug = True 
    ch = logging.StreamHandler() 
    ch.setFormatter(CustomFormatter(fmt=custom_format)) 
    app.logger.addHandler(ch) 
    app.logger.debug("hello world") 
    app.run() 

Via override classe logging.Logger

Lo stesso obiettivo può essere raggiunto sovrascrivendo la classe di logger predefinita. Combinando il flask request context stack, si sarebbe in grado di ottenere il proprio campo nel registro:

import logging 
from flask import Flask 
app = Flask(__name__) 
from flask import _request_ctx_stack 

CUSTOM_FORMAT = """------------------------------------------------------------------------- 
%(worker_id)s in %(module)s [%(pathname)s:%(lineno)d]: 
%(message)s 
-------------------------------------------------------------------------""" 

class MyLogger(logging.Logger): 
    def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None): 
     ctx = _request_ctx_stack.top 
     custom_extra = dict(
      worker_id="request.uuid" 
     ) 
     if ctx is not None: 
      url = ctx.request.url # please replace this with your own field 
      custom_extra["worker_id"] = url 

     if extra is not None: 
      extra.update(custom_extra) 
     else: 
      extra = custom_extra 
     return super(MyLogger,self).makeRecord(name, level, fn, lno, msg, args, exc_info, func=func, extra=extra) 

logging.setLoggerClass(MyLogger) 

@app.route("/") 
def hello(): 
    app.logger.info("hello world") 
    return "Hello World!" 

if __name__ == "__main__": 
    app.debug_log_format = CUSTOM_FORMAT 
    app.debug = True 
    app.logger.debug("hello world") 
    app.run() 
+0

Come faccio a passare il 'work_id' al record di log, perché senza passarlo al log record, il formattatore non può accedervi, il che significa che la prima soluzione non ha funzionato affatto. –

+0

@NotanID si prega di consultare i miei aggiornamenti. – chfw

+0

Ciò funzionerebbe. Ma sto cercando un modo per modificare direttamente 'app.logger', quindi non devo importare queste funzioni di registro avvolto come globali.Grazie comunque :) –

1

Ecco un altro esempio utilizzando una consuetudine Formatter. Grazie alla @chfw e this

mi piace l'uso di flask.has_request_context() qui, in modo che la registrazione non ottiene nel modo di unità di test

 
import logging 
from logging import StreamHandler 
import flask 
from flask import Flask, g, request 

logger = logging.getLogger(__name__) 
logger.setLevel(logging.DEBUG) 
app = flask.Flask(__name__) 


class CustomFormatter(logging.Formatter): 
    def format(self, record): 
     record.uuid = None 
     if flask.has_request_context(): 
      record.uuid = g.uuid if hasattr(g, 'uuid') else None 
      record.path = request.path 
      record.endpoint = request.endpoint 
      record.remote_addr = request.remote_addr 
     return super(CustomFormatter, self).format(record) 

custom_format = '''%(levelname)s %(name)s %(uuid)s %(path)s %(endpoint)s %(remote_addr)s %(message)s''' 
handler = StreamHandler() 
handler.setFormatter(CustomFormatter(fmt=custom_format)) 
logger.addHandler(handler) 


with app.test_request_context(): 
    g.uuid = 'foo' 
    logger.fatal('help') 
Problemi correlati