记录器实例化的最佳实践是什么?目前,我正在使用它来创建一个记录器:

def create_logger(logger_name='default_logger_name', tags={"application": "default-app", "environment": "development"}):
    handler = logging_loki.LokiQueueHandler(
        Queue(-1),
        url="https://somewhere",
        tags=tags,
        auth=("some", "thing="),
        version="1",
    )

    logger = logging.getLogger(logger_name)
    logger.setLevel(logging.DEBUG)
    logger.addHandler(handler)
    logger.addHandler(get_console_handler())
    return logger

def get_console_handler():
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.DEBUG)
    log_format = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
    console_handler.setFormatter(log_format)

    return console_handler

然后打电话给

self.logger = create_logger(__name__)

在任何我想要记录的班级里. 这有两个问题.第一个问题是,我的班级突然与洛基联系在一起,这显然是糟糕的.第二个问题是,即使我没有使用任何使用额外模块的处理程序,我也注意到在单元测试期间,我必须在不同的测试之间显式地删除处理程序,否则第二次运行的测试的输出将是第二次运行的测试的2倍,第三次运行的测试的输出是第三次测试的3倍,以此类推,因为重复的处理程序不断被添加而从未被删除. 我应该使用哪种模式来避免这些问题?我想到的第一件事是在类构造函数中传递记录器创建方法.这解决了第一个问题,但没有解决必须删除处理程序的问题.第二种方法是传递一个记录器实例,并处理类外部的所有事情(比如在测试之间删除处理程序).然而,这仍然会让我不得不进行显式的处理程序删除,这感觉有点奇怪.

推荐答案

推荐的做法是只向根记录器添加处理程序,并且使用配置API(如logging.config.dictConfig)只添加一次,从main()函数或if __name__ == '__main__'子句调用.您可能需要工厂函数来实例化自定义处理程序,例如

def loki_handler_factory(url, tags, auth, version):
    return logging_loki.LokiQueueHandler(
        Queue(-1),
        url=url,
        tags=tags,
        auth=auth,
        version=version,
    )

然后,您可以通过如下配置使用它:

handlers:
  loki:
    '()' : mypkg.util.loki_handler_factory
    level   : INFO
    url: https://somewhere
    tags:
        application: 'default-app'
        environment: development
    auth: [some, 'thing=']
    version: '1'

而配置可能是

import logging.config
import yaml

if __name__ == '__main__':
    with open('logging_conf.yaml') as f:
        d = yaml.safe_load(f)
    logging.config.dictConfig(d)

以上只是该配置的部分YAML片段;有关更多信息,您可以参考链接文档.当然,您也可以将JSON或Python代码用于配置字典.

Python相关问答推荐

为什么Pydantic在我申报邮箱时说邮箱丢失

socket.gaierror:[Errno -2]名称或服务未知|Firebase x Raspberry Pi

如何编写一个正规表达式来查找序列中具有2个或更多相同辅音的所有单词

如何终止带有队列的Python进程?+ 队列大小的错误?

在函数内部使用eval(),将函数的输入作为字符串的一部分

如何在msgraph.GraphServiceClient上进行身份验证?

海运图:调整行和列标签

加速Python循环

Python虚拟环境的轻量级使用

如何在solve()之后获得症状上的等式的值

Streamlit应用程序中的Plotly条形图中未正确显示Y轴刻度

有没有一种方法可以从python的pussompy比较结果中提取文本?

使用密钥字典重新配置嵌套字典密钥名

使用Python更新字典中的值

导入...从...混乱

让函数调用方程

合并帧,但不按合并键排序

在matplotlib中删除子图之间的间隙_mosaic

网格基于1.Y轴与2.x轴显示在matplotlib中

Flask Jinja2如果语句总是计算为false&