向Flask的app.logger提供额外信息

Not*_* ID 15 python flask

Flask 0.10 的默认调试日志格式

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

如何将其更改为:

'-------------------------------------------------------------------------\n%
work_id %(levelname)s in %(module)s [%(pathname)s:%(lineno)d]:\n%(message)s
\n-------------------------------------------------------------------------'
Run Code Online (Sandbox Code Playgroud)

其中work_id是每个请求的随机生成的UUID.

如果记录器是由我自己创建的,我可以使用a logging.LoggerAdapter并提供额外信息作为dict {'work_id': some_uuid},然后我可以使用在日志记录中访问它record.work_id.

但是这app.logger是由create_logger()Flasklogging.py创建,我是否必须修改Flask源来实现我想要的?

我也想过app.logger用我自己的记录器覆盖,就像app.logger = my_logger,它似乎不对.

chf*_*hfw 11

通过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)
Run Code Online (Sandbox Code Playgroud)

例:

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()
Run Code Online (Sandbox Code Playgroud)

通过标准记录模块的Handler和Formatter

Flask以任何方式使用日志记录,因此您可以使用logging.Handlerlogging.Formatter来实现Flask外部.这里可以找到一个通用的例子.日志配置的高级主题可以在doccookbook中找到

针对您的问题的定制示例是:

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()
Run Code Online (Sandbox Code Playgroud)

通过覆盖logging.Logger类

通过覆盖默认记录器类可以实现相同的目标.结合烧瓶请求上下文堆栈,您将能够在日志中获得自己的字段:

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()
Run Code Online (Sandbox Code Playgroud)