• 『无为则无心』Python日志 — 67、logging日志模块处理流程


    1、概括理解

    了解了四大组件的基本定义之后,我们通过图示的方式来理解下信息的传递过程:

    image

    也就是获取的日志信息,进入到Logger日志器中,传递给处理器确定要输出到哪里,然后进行过滤器筛选,通过后再按照定义的格式进行日志的输出。

    2、详细说明

    image

    描述上面这个图的日志流处理流程:

    • 1)在用户代码中进行日志记录函数调用,如:logger.info(…)logger.debug(…)等;
    • 2)判断要记录的日志级别是否满足日志器设置的级别要求。
      要记录的日志级别要大于或等于日志器设置的级别才算满足要求,如果不满足则该日志记录会被丢弃,并终止后续的操作,如果满足则继续下一步操作;
    • 3)根据日志记录函数调用时传入的参数,创建一个日志记录(LogRecord类)对象;
    • 4)判断日志记录器上设置的过滤器是否拒绝这条日志记录,如果日志记录器上的某个过滤器拒绝,则该日志记录会被丢弃并终止后续的操作。如果日志记录器上设置的过滤器,不拒绝这条日志记录,或者日志记录器上没有设置过滤器,则继续下一步操作,将日志记录分别交给该日志器上添加的各个处理器;
    • 5)判断要记录的日志级别是否满足处理器设置的级别要求。
      要记录的日志级别要大于或等于该处理器设置的日志级别才算满足要求,如果不满足记录将会被该处理器丢弃并终止后续的操作,如果满足则继续下一步操作;
    • 6)判断该处理器上设置的过滤器是否拒绝这条日志记录,如果该处理器上的某个过滤器拒绝,则该日志记录会被当前处理器丢弃并终止后续的操作。如果当前处理器上设置的过滤器不拒绝这条日志记录,或当前处理器上没有设置过滤器测继续下一步操作;
    • 7)如果能到这一步,说明这条日志记录经过了层层关卡允许被输出了,此时当前处理器会根据自身被设置的格式器(如果没有设置则使用默认格式),会将这条日志记录进行格式化,最后将格式化后的结果,输出到指定位置(文件、网络、类文件的Stream等);
    • 8)如果日志器被设置了多个处理器的话,上面的第5-8步会执行多次;
    • 9)这里才是完整流程的最后一步:判断该日志器输出的日志消息是否需要传递给上一级logger
      日志器是有层级关系的,如果propagate属性值为1,则表示日志消息将会被输出到处理器指定的位置,同时还会被传递给parent日志器的handlers进行处理,直到当前日志器的propagate属性为0停止,如果propagate值为0则表示不向parent日志器的handlers传递该消息,到此结束。

    可见,一条日志信息要想被最终输出需要依次经过以下几次过滤:

    • 日志器等级过滤;
    • 日志器的过滤器过滤;
    • 日志器的处理器等级过滤;
    • 日志器的处理器的过滤器过滤;

    3、应用示例

    (1)需求:

    • 1)要求将所有级别的所有日志都写入磁盘文件中
    • 2)all.log文件中记录所有的日志信息,日志格式为:日期和时间 - 日志级别 - 日志信息
    • 3)error.log文件中单独记录error及以上级别的日志信息,日志格式为:日期和时间 - 日志级别 - 文件名[:行号] - 日志信息
    • 4)要求all.log在每天凌晨进行日志切割。

    (2)分析:

    • 1)要记录所有级别的日志,因此日志器的有效level需要设置为最低级别DEBUG;
    • 2)日志需要被发送到两个不同的目的地,因此需要为日志器设置两个handler
      另外,两个目的地都是磁盘文件,因此这两个handler都是与FileHandler相关的;
    • 3)all.log要求按照时间进行日志切割,因此他需要用logging.handlers.TimedRotatingFileHandler类;
      error.log没有要求日志切割,因此可以使用FileHandler类;
    • 4)两个日志文件的格式不同,因此需要对这两个handler分别设置格式器;

    (3)示例

    python
    # 导入logging模块
    import logging
    import logging.handlers
    # 或者 from logging.handlers import TimedRotatingFileHandler
    import datetime
    
    # 创建一个日志器,就是一个logger对象
    logger = logging.getLogger('logger')
    # 设置logger日志级别
    logger.setLevel(logging.DEBUG)
    
    # 定义处理器1
    # 这里进行简化
    # rf_handler = logging.handlers.TimedRotatingFileHandler('all.log', when='midnight', interval=1, backupCount=7,
    #                                                        atTime=datetime.time(0, 0, 0, 0))
    """
    `TimedRotatingFileHandler`位于`logging.handlers`模块中, 
    支持按一定时间间隔更换磁盘日志文件。这样就可以保证日志单个文件不会太大。
    可以根据官方文档自己学习:
    https://docs.python.org/zh-cn/3/library/logging.handlers.html
    """
    
    
    all_handler = logging.FileHandler('../log/all.log', encoding="utf-8")
    
    # 给处理器传入格式器
    all_handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
    
    # 定义处理器2
    error_handler = logging.FileHandler('../log/error.log', encoding="utf-8")
    # 设置处理器日志级别
    error_handler.setLevel(logging.ERROR)
    # 给处理器传入格式器
    error_handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(filename)s[:%(lineno)d] - %(message)s"))
    
    # 把两个处理器添加到日志器中
    logger.addHandler(all_handler)
    logger.addHandler(error_handler)
    
    logger.debug('debug message')
    logger.info('info message')
    logger.warning('warning message')
    logger.error('error message')
    logger.critical('critical message')

    执行结果:

    all.log文件输出。

    py
    2021-01-15 23:12:27,197 - DEBUG - debug message
    2021-01-15 23:12:27,198 - INFO - info message
    2021-01-15 23:12:27,198 - WARNING - warning message
    2021-01-15 23:12:27,198 - ERROR - error message
    2021-01-15 23:12:27,198 - CRITICAL - critical message

    error.log文件输出。

    py
    2021-01-15 23:12:27,198 - ERROR - demo_log3.py[:35] - error message
    2021-01-15 23:12:27,198 - CRITICAL - demo_log3.py[:36] - critical message

    参考:https://blog.csdn.net/mk1843109092/article/details/97104041


    __EOF__

  • 本文作者: 繁华似锦的博客
  • 本文链接: https://www.cnblogs.com/liuyuelinfighting/p/15967157.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    【LeetCode】——链式二叉树经典OJ题详解
    分布式电源接入对配电网影响分析(Matlab代码实现)
    【LeetCode】3. 无重复字符的最长子串
    Arm32进行远程调试
    深入解析Spring Cloud:构建分布式微服务架构的最佳实践
    初识OpenGL (-)VAO&VBO
    Redis之缓存
    双网关多发选收配置实验案例(5G CPE场景)
    Redisson—分布式集合详述
    机器学习平台架构系列-2-之江天枢
  • 原文地址:https://www.cnblogs.com/liuyuelinfighting/p/15967157.html