我有一个被许多客户使用的服务器。为了更轻松地查找日志条目,我希望允许客户端为每个请求提供一个 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)
然后我想我也许可以创建一个代理类,它将拦截对 、 、 等的调用info,debug并exception在前面添加 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)