2015-01-05 54 views
10

default debug log format爲0.10瓶是提供額外的信息,以瓶的app.logger

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

我怎麼就改成這樣:

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

其中work_id是爲每個請求隨機生成的UUID。

如果記錄器是由我自己創建的,我可以使用logging.LoggerAdapter並提供額外信息作爲字典{'work_id': some_uuid},然後我可以在日誌記錄中使用record.work_id訪問它。

app.logger是由create_logger() in Flask'slogging.py創建的,我必須修改Flask源代碼來實現我想要的嗎?

我也認爲只是用我自己的記錄器覆蓋app.logger,如app.logger = my_logger,它似乎不正確。

回答

8

通過Flask.debug_log_format

只是這樣做:

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) 

例子:

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() 

通過標準的日誌模塊的處理程序和格式化

燒瓶使用任何方式記錄,因此您可以使用logging.Handlerlogging.Formatter來實現燒瓶外部。一個通用的例子可以找到here。日誌記錄配置的高級主題可以the doc被發現在cookbook

關於你的問題量身定製的例子是:

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() 

通過覆蓋logging.Logger類

同樣的目標可以通過覆蓋默認的記錄器類來實現。結合flask request context stack,你就可以獲取該日誌在自己的領域:

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

如何通過'work_id'日誌記錄,因爲如果不將它傳遞給日誌記錄,格式化程序將無法訪問它,這意味着您的第一個解決方案根本不起作用。 –

+0

@NotanID請參閱我的更新。 – chfw

+0

這將工作。但我正在尋找直接修改'app.logger'的方法,所以我不必將這些包裝的日誌函數作爲全局變量導入。無論如何,謝謝:) –

1

下面是使用自定義Formatter另一個例子。由於@chfw和this

我喜歡使用的flask.has_request_context()這裏,使記錄不會在單元的方式獲得測試

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