在某些请求期间将标识符添加到 python 记录器的惯用方法?

Mat*_*sen 8 python logging

我有一个被许多客户使用的服务器。为了更轻松地查找日志条目,我希望允许客户端为每个请求提供一个 UUID,然后在请求期间在每个日志消息前面添加该 UUID。这样做的好处是,如果客户遇到一些错误,他们可以向我提供 ID,这样我就可以在日志中快速找到它。我认为这是相当标准的;在Python中有完成这个任务的惯用语吗?

我可以通过手动将 uuid 添加到每条日志消息中来天真地做到这一点:

import uuid
import logging
logger = logging.getLogger(__name__)

def request(*args, **kwargs):
    _id = args.get("_id", str(uuid.uuid4()))
    logger.info("{} - {}".format(_id, "Starting request"))
Run Code Online (Sandbox Code Playgroud)

我还可以为每个请求创建一个新的记录器,并更改formatter以照顾我的前缀:

import uuid
import logging

def build_logger(_id):
    logger = logging.getLogger(_id)
    # ...
    formatter = logging.Formatter('%(name)s - %(message)s')
    # ...
    return logger

import uuid
def request(*args, **kwargs):
   _id = args.get("_id", str(uuid.uuid4()))
    logger = build_logger(_id)
Run Code Online (Sandbox Code Playgroud)

然后我想我也许可以创建一个代理类,它将拦截对 、 、 等的调用infodebugexception在前面添加 uuid。就像是:

import uuid
import logging
logger = logging.getLogger(__name__)

class Logger(object):
    """Naive Proxy class for logger"""
    def __init__(self, _id):
        self._id = _id
    def debug(self, msg):
        logger.debug("{} - {}".format(self._id, msg)
    def info(self, msg):
        logger.info("{} - {}".format(self._id, msg)
    # and etc. for each level and `exception`

def request(*args, **kwargs):
    _id = args.get("_id", str(uuid.uuid4()))
    logger = Logger(_id)
Run Code Online (Sandbox Code Playgroud)

为什么不使用__getattr__装饰器来折叠这些呢?

import uuid
import logging
logger = logging.getLogger(__name__)

def loggerator(_id):
    """
    Decorator to intercept `info`, `debug`, etc. and prepend the `_id`
    Used in the Logger Proxy class
    """
    def _loggerator(func):
        def __loggerator(msg):
            return func("{} - {}".format(_id, msg))
        return __loggerator
    return _loggerator

class Logger(object):
    """Proxy class for logger"""
    def __init__(self, _id):
        self._id = _id
    def __getattr__(self, item):
        if item == '_id':
            return object.__getattribute__(self, item)
        if item in ('debug', 'info', 'warn', 'warning', 'error', 'critical', 'fatal', 'exception'):
            return loggerator(self._id)(getattr(logger, item))
        return getattr(logger, item)

def request(*args, **kwargs):
    _id = args.get("_id", str(uuid.uuid4()))
    logger = Logger(_id)
Run Code Online (Sandbox Code Playgroud)

Vin*_*jip 2

如何执行此操作记录在Logging Cookbook中,它是 Python 文档的一部分。