如何装饰python日志记录输出?

时间:2020-06-11 14:38:00

标签: python python-3.x logging

我使用import logging模块在​​带有Python 3.7运行时的AWS lambda内部进行登录。

我想在将日志语句刷新到stdout之前对它们进行某些操作,例如将消息包装为json并添加跟踪数据,以便Kibana解析器可以解析它们。

我不想为此编写自己的装饰器,因为这对于基础依赖项无效。

理想情况下,它应该类似于为记录器配置的回调 这样它将为我完成以下工作:

    log_statement = {}
    log_statement['message'] = 'this is the message'
    log_statement['X-B3-TraceId'] = "76b85f5e32ce7b46"
    log_statement['level'] = 'INFO'
    sys.stdout.write(json.dumps(log_statement) + '\n')

仍然logger.info('this is the message')的时候。

我该怎么做?

1 个答案:

答案 0 :(得分:1)

回答我自己的问题:

  1. 我必须使用LoggerAdapter,它非常适合用于预处理日志语句:
import logging

class CustomAdapter(logging.LoggerAdapter):

    def process(self, msg, kwargs):
        log_statement = '{"X-B3-TraceId":"%s", "message":"%s"}' % (self.extra['X-B3-TraceId'], msg) + '\n'
        return log_statement, kwargs

请参阅:https://docs.python.org/3/howto/logging-cookbook.html#using-loggeradapters-to-impart-contextual-information

  1. 通常,下一步就是像这样插入适配器:
import logging
...
logging.basicConfig(format='%(message)s')
logger = logging.getLogger()
logger.setLevel(LOG_LEVEL)
custom_logger = CustomAdapter(logger, {'X-B3-TraceId': "test"})
...
custom_logger.info("test")

注意:我只需要将格式设置为message,因为我需要将整个语句作为JSON字符串获取。不幸的是,因此我丢失了一些预定义的日志语句部分,例如aws_request_id。这是LoggerAdapter#process的局限性,因为它仅处理message部分。如果有人在这里有更好的方法,请提出建议。

  1. AWS lambda python运行时似乎以某种方式干扰了日志记录功能,并且无法像上面那样更改格式。所以我还必须这样做:
FORMAT = "%(message)s"
logger = logging.getLogger()
for h in logger.handlers:
    h.setFormatter(logging.Formatter(FORMAT))

请参阅:https://gist.github.com/niranjv/fb95e716151642e8ca553b0e38dd152e

相关问题