CherryPy 将上下文信息添加到日志记录

CherryPy add contextual information to logging

我正在使用 CherryPy 3.7.0 构建一个小型网络应用程序。

我的问题是我不知道如何将上下文信息添加到它的日志输出中。

尽管我已经多次浏览它的文档,但仍不清楚如何实现这样的事情。 我有兴趣在记录器中添加一个 task 属性,以便在我的一个视图中我应该能够写:

logger.info('Processing finished', extra={'task': 'jashgd-765273-ehdfiuh'})

我应该怎么做?

提前致谢

试试这个...

import cherrypy
from cherrypy import log

class MyApp(object):
    def index(self):
        log.error(msg='This is My Error ', context='HTTP', severity=20, traceback=True)
        return "Hello World!"    
    index.exposed = True

cherrypy.tree.mount(MyApp(), "/")

cherrypy.config.update({'tools.staticdir.on': True,
    'tools.staticdir.dir': 'C:\Documents and Settings\d\My Documents\Aptana Studio 3 Workspace\ScratchPad',
    'log.access_file' : "access.log",
    'log.error_file' : "error.log",
    'log.screen' : False,
    'tools.sessions.on': True,
    })


cherrypy.engine.start()
cherrypy.engine.block()

希望对您有所帮助!

阅读文档

以下是 logging.debug 的文档中关于 extra 关键字参数的内容:

The third optional keyword argument is extra which can be used to pass a dictionary which is used to populate the __dict__ of the LogRecord created for the logging event with user-defined attributes. These custom attributes can then be used as you like. For example, they could be incorporated into logged messages. For example:

FORMAT = '%(asctime)-15s %(clientip)s %(user)-8s %(message)s'
logging.basicConfig(format=FORMAT)
d = {'clientip': '192.168.0.1', 'user': 'fbloggs'}
logging.warning('Protocol problem: %s', 'connection reset', extra=d)

extra 不会神奇地自动记录 -- 您需要提供适当的格式化程序。

这是 CherryPy 的例程 cherrypy._cplogging.LogManager.error ,它有效地将数据传递给 stdlib 的记录器:

def error(self, msg='', context='', severity=logging.INFO, traceback=False):
    """...
    This is not just for errors! Applications may call this at any time
    to log application-specific information.
    ...
    """
    if traceback:
        msg += _cperror.format_exc()
    self.error_log.log(severity, ' '.join((self.time(), context, msg)))

另请查看 cherrypy._cplogging 的文档字符串。它解释了 CherryPy 日志记录的预期扩展。

写代码

从上面的部分我们得到了结果。简单的回答是你不能直接这样做。另外@AndrewKloos 的答案实际上并不是答案,因为你不能将 dict 按顺序传递给 str.join。此外,您甚至不能传递 extra 关键字参数,因为签名中没有这样的正式参数。即使可以,为格式化程序提供额外的占位符也会导致任何 CherryPy 的正常日志记录中的字符串插值错误(显然不提供任何额外的键)。

因此最好的折衷办法就是:

cherrypy.log('Processing finished ' + str({'task': 'jashgd-765273-ehdfiuh'}))

其他选项:

  • 除了错误和访问日志之外,创建自己的记录器,
  • 直接调用cherrypy.log.error_log.info
  • Monkeypatch cherrypy.logcherrypy._GlobalLogManager
  • 的子类

更新

Introspect Python logging with logging_tree 是一篇不错的文章(和包),它解释了 CherryPy 应用程序示例中的日志记录层次结构和消息传递。