2015-01-05 9 views
10

Die default debug log format für Flask 0.10 istSorgt für zusätzliche Informationen zu Flask des app.logger

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

Wie kann ich es so weit ändern:

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

wo work_id eine für jede Anforderung zufällig generierte UUID ist.

Wenn der Logger selbst erstellt wird, kann ich nur eine logging.LoggerAdapter verwenden und geben Sie die zusätzlichen Informationen als dict {'work_id': some_uuid}, dann kann ich es in der Log-Aufzeichnung zugreifen record.work_id verwenden.

Aber die app.logger wird erstellt von create_logger() in Flask'slogging.py, muss ich die Kolbenquelle ändern, um zu erreichen, was ich will?

Ich dachte auch gerade überschreiben app.logger mit meinem eigenen Logger, wie app.logger = my_logger, scheint es nicht richtig.

Antwort

8

Via Flask.debug_log_format

dies nur tun:

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) 

Beispiel:

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 und Formatter von Standardprotokollierungsmodul

Flask verwendet Protokollierung in beliebiger Weise, so dass Sie logging.Handler und logging.Formatter verwenden können, um außerhalb von Flask zu erreichen. Ein generisches Beispiel kann here gefunden werden.

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 zwingende logging.Logger Klasse

Das gleiche Ziel kann sein: Erweiterte Thema Protokollkonfiguration kann in the doc und in der cookbook

Ein maßgeschneidertes Beispiel in Bezug auf Ihre Frage gefunden werden erreicht durch Überschreiben der Standard-Logger-Klasse. Die Kombination der flask request context stack, würden Sie in der Lage sein, Ihr eigenes Feld im Protokoll zu erhalten:

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

Wie kann ich die 'work_id' passieren Rekord zu protokollieren, Da formatter nicht auf den Protokolldatensatz zugreifen kann, kann er nicht darauf zugreifen, was bedeutet, dass Ihre erste Lösung überhaupt nicht funktioniert hat. –

+0

@NotanID siehe meine Updates. – chfw

+0

Das würde funktionieren. Aber ich suche nach einer Möglichkeit, den 'app.logger' direkt zu ändern, also muss ich diese umgebrochenen Protokollfunktionen nicht als globale Variablen importieren.Danke trotzdem :) –

1

Hier ist ein weiteres Beispiel eines benutzerdefinierte mit Formatter. Dank @chfw und this

Ich mag die Verwendung von flask.has_request_context() hier, so dass die Protokollierung nicht in der Art und Weise der Einheit bekommt testet

 
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') 
Verwandte Themen