Flask 0.10的default debug log format是
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
并以dict {'work_id': some_uuid}
的形式提供额外信息,然后我可以使用record.work_id
在日志记录中访问它
但是app.logger
是由create_logger()
in Flask'slogging.py
创建的,我是否必须修改Flask源代码以实现我想要的目标?
我还想过用我自己的记录器覆盖app.logger
,例如app.logger = my_logger
,它看起来不对。
答案 0 :(得分: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)
示例:
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()
通过标准日志记录模块的处理程序和格式化程序
Flask以任何方式使用记录,因此您可以使用logging.Handler和logging.Formatter来实现Flask外部。可以找到一个通用示例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()
答案 1 :(得分:2)
以下是使用自定义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')