为每个应用程序实例分隔记录器名称

时间:2009-12-29 17:30:56

标签: python logging

我的python应用程序由主程序和几个模块组成。每个模块都包含

import logging
log = logging.getLogger('myapp.mymodule')

在全球范围内。处理程序和其他在主程序中初始化的东西,通常所有消息都转发到syslog。

现在我想启动多个应用程序实例(具有实例名称的配置文件可以指定为命令行参数)。问题是:如何将实例名称传递给每个导入的模块?我希望记录器名称看起来像'myappinstance.mymodule'或'myapp.instance.module'。我不想在每个模块中搞乱配置文件解析,因为这需要硬编码的配置路径。

3 个答案:

答案 0 :(得分:2)

这是我能想到的解决方案:

在主程序中,设置名为myapp

的记录器的格式化程序
import logging
logger = logging.getLogger("myapp")
formatter = logging.Formatter("%(asctime)s - instance_name - %(levelname)s - %(message)s")
ch = logging.SysLogHandler()
ch.setFormatter(formatter)
logger.addHandler(ch)

然后,使用记录器myapp.*的所有导入模块将在记录消息中包含instance_name。

答案 1 :(得分:0)

好吧,描述问题确实有助于解决它:)只是想过使用环境变量来传递所有模块的参数:

main.py:

import os
os.environ['instance'] = 'blah'
import a

a.py:

import os
import b
print 'a:', os.environ['instance']

b.py:

import os
print 'b:', os.environ['instance']

$ python main.py

b: blah
a: blah

对于这个的任何其他想法或批评者?

答案 2 :(得分:0)

只需编写您自己的日志包装器,它将为您提供正确的名称(根据需要进行调整以获得您想要的实例名称):

def get_logger(obj=None):
    if isinstance(obj, str):
        return logging.getLogger(obj) 
    elif obj is not None:
        logger_name ="%s.%s" % (obj.__class__.__module__, obj.__class__.__name__)
        return logging.getLogger(logger_name)
    else:
        return logging.getLogger()

class Foo(object):

    def __init__(self):
        self._log = get_logger(self)

或者,如果进程ID足够好,只需在格式化程序中使用它:

http://www.python.org/doc/2.5.4/lib/node421.html

formatter = logging.Formatter("%(process)d - %(asctime)s - %(levelname)s - %(message)s")

显然,这将唯一地标识每个进程,但不会提供与实例相关的任何内容。