gpt4 book ai didi

python - 为每个线程定义一个记录器

转载 作者:太空宇宙 更新时间:2023-11-04 06:22:33 26 4
gpt4 key购买 nike

我有一个用于处理 XMLRPC 请求的服务器应用程序。每个连接都创建自己的线程。我想设置日志记录,以便某些线程/连接特定信息进入日志。我可以做类似的事情:

import logging

@add_unique_request_id
def thread_top(request_id):
logging.info('thread %d says: hello'%request_id)
logging.error('thread %d says: darn!!'%request_id)

并按照我的意愿设置全局根记录器,但我不喜欢这个解决方案。我想要以下内容:

import logging

@setup_logger
def thread_top():
logging.info('hello')
logging.error('darn!!')

但我不知道 setup_logger deco 应该是什么样子。我想出了一个解决方法,为每个请求使用单独的进程,然后在每个进程中设置根记录器将完全按照我的要求进行。有没有什么方法可以在不被迫使用多处理的情况下完成这项工作?

谢谢!

最佳答案

我正在使用自定义格式化程序和线程本地存储来执行此操作:

from collections import defaultdict
import logging
import threading

class ContextAwareFormatter(logging.Formatter):
"""
Makes use of get_context() to populate the record attributes.
"""

def format(self, record):
# Using defaultdict to avoid KeyErrorS when a key is not in the context.
def factory():
return ""
record.__dict__ = defaultdict(factory, record.__dict__)

for k, v in get_context().iteritems():
if not hasattr(record, k):
setattr(record, k, v)
return logging.Formatter.format(self, record)

THREADLOCAL_ATTR = "logging_context"
_threadlocal = threading.local()

def get_context():
result = getattr(_threadlocal, THREADLOCAL_ATTR, None)
if result is None:
result = {}
setattr(_threadlocal, THREADLOCAL_ATTR, result)
return result

def set_context(**context):
c = get_context()
c.clear()
c.update(**context)
return c

def update_context(**context):
c = get_context()
c.update(**context)
return c

然后在记录器配置中:

"formatters": {
"default": {
"()": "log.ContextAwareFormatter",
"format": "%(asctime)s %(levelname)s [%(request_id)s] %(message)s (%(module)s:%(lineno)d)",
},
}

在记录上下文之前填充:

update_context(request_id=request_id)

您可能希望对应用程序的不同部分使用不同的格式化程序,您可能不需要在日志记录中使用 request_id

关于python - 为每个线程定义一个记录器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10994235/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com