当前位置: 首页 > 知识库问答 >
问题:

如何使日志记录模块函数使用不同的日志记录程序?

江德润
2023-03-14

我可以创建一个命名的子记录器,以便该记录器输出的所有日志都用它的名称标记。我可以只在函数/类/任何东西中使用记录器。

但是,如果该代码调用了另一个模块中的函数,该模块仅使用日志模块函数(根记录器的代理)进行日志记录,我如何确保这些日志消息通过相同的记录器(或者至少以相同的方式记录)?

例如:

main.py

import logging

import other

def do_stuff(logger):
    logger.info("doing stuff")
    other.do_more_stuff()

if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger("stuff")
    do_stuff(logger)

其他.py

import logging

def do_more_stuff():
    logging.info("doing other stuff")

产出:

$ python main.py 
INFO:stuff:doing stuff
INFO:root:doing other stuff

我希望能够使两个日志行都标记为名称'stuff',我希望能够做到这一点,只改变main.py。

如何在不更改模块的情况下使other.py中的日志记录调用使用不同的日志记录程序?

共有1个答案

璩无尘
2023-03-14

这是我想出的解决方案:

使用线程本地数据存储上下文信息,并在根记录器处理程序上使用筛选器在发出日志记录之前将这些信息添加到日志记录中。

context = threading.local()                                                      
context.name = None                                                              

class ContextFilter(logging.Filter):                                             

    def filter(self, record):                                                    
        if context.name is not None:                                             
            record.name = "%s.%s" % (context.name, record.name)              
        return True                                                              

这对我来说很好,因为我使用记录器名称来指示当记录此消息时正在执行什么任务。

然后,我可以使用上下文管理器或修饰器,使特定代码段的日志记录看起来就像是从特定子记录器中记录的一样。

@contextlib.contextmanager                                                       
def logname(name):                                                               
    old_name = context.name                                                      
    if old_name is None:                                                         
        context.name = name                                                      
    else:                                                                        
        context.name = "%s.%s" % (old_name, name)                                

    try:                                                                                 
        yield                                                                        
    finally:                                                                         
        context.name = old_name                                                      

def as_logname(name):                                                            
    def decorator(f):                                                            
        @functools.wraps(f)                                                      
        def wrapper(*args, **kwargs):                                            
            with logname(name):                                                  
                return f(*args, **kwargs)                                        
        return wrapper                                                           
    return decorator                                                             

那么,我可以:

with logname("stuff"):
    logging.info("I'm doing stuff!")
    do_more_stuff()

或:

@as_logname("things")
def do_things():
    logging.info("Starting to do things")
    do_more_stuff()

关键在于,do_more_stuff()所做的任何日志记录都将被记录,就像它是用“stuff”或“things”子记录器记录的一样,而根本不需要更改do_more_stuff()

如果您要在不同的子记录器上使用不同的处理程序,则此解决方案将会出现问题。

 类似资料:
  • 我正在使用python日志记录我的程序。所有日志当前都打印在stdout上,但我希望使用POST REST调用将它们发送到远程日志服务器。当前,我的程序发出了多个日志记录的POST请求。有没有更优化的方式发送日志,我可以捆绑多个日志在一个POST请求?

  • 我想在我的应用程序中使用SLF4J+logback用于两个目的--日志和审计。 14:41:57.978[main]信息AUDIT_LOGGER-110欢迎使用main 如何确保审核消息在审核记录器下只出现一次?

  • 我试图从log4j1更改为log4j2。我所做的: 已删除旧配置文件log4j。xml 创建了新的配置文件log4j2。xml 创建了jboss部署结构。xml 编辑的pom 环境:野蝇10 1 EAR 4 WAR文件中没有使用web.xml。以前的log4j配置日志在EAR中(仅) Log4j2配置文件 Jboss部署结构 新的maven依赖关系 我之前说过我在SLF4j中使用log4j1。这些

  • 问题内容: 我正在考虑将Redis用于Web应用程序日志记录目的。我用谷歌搜索,有人将日志转储到Redis队列/列表中,然后将计划的工作人员转储到磁盘中。 http://nosql.mypopescu.com/post/8652869828/another-redis-use-case- centralized-logging 我希望寻求理解,为什么不直接使用Redis持久化到磁盘?如果我分配了一

  • logging 模块自 2.3 版以来一直是 Python 标准库的一部分。在 PEP 282 中有对它的简洁描述。除了 基础日志教程 之外,这些文档是非常难以阅读的。 日志记录一般有两个目的: 诊断日志 记录与应用程序操作相关的日志。例如,当用户遇到程序报错时, 可通过搜索诊断日志以获得上下文信息。 审计日志 为商业分析而记录的日志。从审计日志中,可提取用户的交易信息, 并结合其他用户资料构成用

  • 问题内容: 我正在使用python记录器。以下是我的代码: 我的问题是我在每个呼叫的日志文件中都有多个条目。我该如何解决? 问题答案: 该已经是一个单例。(文件) 问题在于,每次调用时,都会向实例添加另一个处理程序,这将导致日志重复。 也许像这样?