Python日志记录:属于一个请求的组日志 [英] Python Logging: Group logs which belong to one request
问题描述
是否可以对属于一个Web请求的python Web应用程序的日志进行分组?
Is there a way to group logs of a python web application which belong to one web request?
示例:
2015-02-11 13:06:32 myapp.middleware.MYAPPMiddleware: INFO Login of user foo was successful
2015-02-11 13:06:32 myapp.middleware.MYAPPMiddleware: INFO Login of user bar failed
2015-02-11 13:06:32 myapp.send_mails: INFO failed to send mail to someone@example.com
以上日志行彼此无关.
The above log lines are unrelated to each other.
如何用Python方式解决这个问题?
How can you solve this the pythonic way?
推荐答案
日志条目的本质是相互独立的.
将它们连接在一起的正确方法是将一些上下文信息包含在条目中,以便以后查看日志时进行过滤.
Log entries in their essence are designed to be independent from each other.
The correct way to connect them together is to include some contextual information into the entries to filter by when looking through the logs later.
下面是一个Sharepoint日志记录的示例,其中包含以下信息:
Here's a example of a Sharepoint log record with such information:
Timestamp Process TID Area Category EventID Level Message Correlation
02/26/2015 17:49:19.65 w3wp.exe (0x1F40) 0x2358 SharePoint Foundation Logging Correlation Data xmnv Medium Name=Request (POST:http://reserver2:80/pest/_vti_bin/sitedata.asmx) d1e2b688-e0b2-481e-98ce-497a11acab44
在Python logging
文档中, 将上下文信息添加到日志记录输出中 建议使用以下两种方法之一:使用LoggerAdapter
或Filter
.
In Python logging
docs, Adding contextual information to your logging output recommends either of two methods: using a LoggerAdapter
or a Filter
.
LoggerAdapter
的用法如下(示例基于文档中的示例):
LoggerAdapter
is used like this (examples are based on those in the docs):
class AddConnIdAdapter(logging.LoggerAdapter):
def process(self, msg, kwargs):
return <augment_message(msg,arbitrary_info)>, kwargs
la = AddConnIdAdapter(<logger>,extra=<parameters, saved in self.extra>)
<...>
la.info(<message>)
Filter
的用法如下:
#Either all messages should have custom fields
# or the Formatter used should support messages
# both with and without custom fields
logging.basicConfig(<...>,format='%(asctime)-15s %(name)-5s %(levelname)-8s IP: %(ip)-15s User: %(user)-8s %(message)s')
class AddClientInfo(logging.Filter):
#override __init__ or set attributes to specify parameters
def filter(self, record):
record.ip = <get_client_ip()>
record.user = <get_client_name()>
return True #do not filter out anything
l=<logger()>
l.addFilter(AddClientInfo()) #can attach to either loggers or handlers
<...>
l.info('message')
如您所见,区别是LoggerAdapter
是不透明的,而Filter
是透明的.在示例中,前者修改消息文本,而后者设置自定义属性(实际上,编写它们需要使用Formatter
的配合),但实际上,两者都可以.
As you can see, the difference is LoggerAdapter
is non-transparent while Filter
is transparent. In the examples, the former modifies the message text while the latter sets custom attributes (and actually writing them requires cooperation of the Formatter
used) but in fact, both can do both.
因此,如果只需要将上下文添加到某些消息中,而前者更适合于扩展所记录的全部或大部分消息,则前者更为有用.
So, the former is more useful if you only need to add the context to some messages while the latter is more fit to augment all, or a large portion of, the messages being logged.
这篇关于Python日志记录:属于一个请求的组日志的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!