为每个应用实例分离日志记录器名称

1 投票
3 回答
1131 浏览
提问于 2025-04-15 17:27

我的Python应用程序由主程序和几个模块组成。每个模块在全局范围内包含

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

的内容。处理程序和其他东西在主程序中初始化,通常所有的消息都会转发到系统日志。

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

3 个回答

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")

显然,这样可以唯一标识每个进程,但不会提供与实例相关的信息。

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.* 的导入模块在日志信息中都会包含实例名称。

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

还有其他的想法或者批评意见吗?

撰写回答