获取 Flask 中错误记录的请求上下文?

Getting request context for error logging in Flask?

Flask 教程有一个发生错误时给自己发邮件的例子。我想从 request 添加一些信息,但一直收到错误消息:

RuntimeError: working outside of request context

这是我的资料:

if  __name__ == '__main__':
    if not app.debug:  

        # create mail handler
        import logging
        from logging.handlers import SMTPHandler
        mail_handler = SMTPHandler('127.0.0.1',
                               'server-error@example.com',
                               ['admin@example.com'], 'YourApplication Failed')

        # Log format
        from logging import Formatter
        mail_handler.setFormatter(Formatter('''
        Message type:       %(levelname)s
        Location:           %(pathname)s:%(lineno)d
        Module:             %(module)s
        Function:           %(funcName)s
        Time:               %(asctime)s

        Message:

        %(message)s
        ''' % request.headers ))   # Added request here

        # Attach log handler to app
        mail_handler.setLevel(logging.ERROR)
        app.logger.addHandler(mail_handler)

如何获取日志记录的请求上下文?

你实际上需要添加一个过滤器来将你想要的添加到记录器中:

import logging

class ContextualFilter(logging.Filter):
    def filter(self, log_record):
        log_record.url = request.path
        log_record.method = request.method
        log_record.ip = request.environ.get("REMOTE_ADDR")
        log_record.headers = request.headers

        return True

然后您可以使用应用程序的记录器注册过滤器

context_provider = ContextualFilter()
app.logger.addFilter(context_provider)

并使用您在格式化程序中添加到上下文的额外键:

mail_handler.setFormatter(Formatter('''
    Message type:       %(levelname)s
    Location:           %(pathname)s:%(lineno)d
    Module:             %(module)s
    Function:           %(funcName)s
    Time:               %(asctime)s
    URL:                %(url)s
    Method:             %(method)s
    Headers:            %(headers)s

    Message:

    %(message)s
    '''))

为什么我不能将 request.headers 添加到我的格式化程序

两个原因:

  1. 设置记录器时没有请求上下文,因为没有入站请求
  2. 即使有,该代码也不会真正执行您希望它执行的操作。当您设置记录器时,它将从范围内的请求中添加请求 headers(因此所有请求都将是第一个请求)。

另请参阅:https://realpython.com/blog/python/python-web-applications-with-flask-part-iii/