开发组日志记录SPEC_v0.1.0

更新记录

时间版本内容修订者备注
2024/08/150.1.0创建henry.xu

开发组日志记录SPEC_v0.1.0

1. 目的

1.1 区分用户日志和开发人员日志

  • 实现效果:
logger = LoggerManager() 

# 为记录器添加文件处理器;不添加则不生成日志文件;
logger.logfile(log_path, encoding='utf-8', mode='w')

# 设置log_level
logger.set_log_level(level=DEBUG)

# 启用 Dev 记录器的控制台处理器;
# 为True的时候,控制台会打印属于 Dev 记录器的日志信息,反之则不打印;
logger.dev_log_enabled = True

# dev参数默认为False;
# True表示该日志属于 Dev 日志记录器,反之表示该日志属于 User 记录器;
# 表示这条消息在logger.dev_log_enabled设置为False的时候,不会打印在系统终端;
logger.info('This is an info message', dev=True)

logger.debug('This is a debug message')
logger.info('This is an info message')
  • 当logger.dev_log_enabled设置为True的时候控制台打印的消息:
[Dev  I 2024-08-16 13:12:49 auto_logger:122] This is an info message
[User D 2024-08-16 13:12:49 auto_logger:124] This is a debug message
[User I 2024-08-16 13:12:49 auto_logger:125] This is an info message
  • 当logger.dev_log_enabled设置为False的时候控制台打印的消息:
[User D 2024-08-16 13:13:35 auto_logger:124] This is a debug message
[User I 2024-08-16 13:13:35 auto_logger:125] This is an info message

1. 2. 帮助开发人员快速定位

  • 合理利用装饰器实现,详情可以参考4.2

2. 设计逻辑

以下是 logging 模块中记录器、格式器、处理器、筛选器作用介绍:

组件主要作用
Logger- 日志记录器提供记录日志的接口,并将日志消息传递给 Handler
Handler-处理器将日志消息传递到指定的目标位置,如文件、控制台、网络等
Formatter-格式器定义日志消息的输出格式,包括时间戳、日志级别、消息内容等
Filter-筛选器控制哪些日志消息应该被记录或忽略,提供细粒度的日志控制
  • 重新封装logging模块,在基本不改变代码的情况下替换掉之前使用的log日志系统;
  • 定义两个日志记录器分别对应User 和 Dev;
  • 提供参数dev区分两个日志记录器;dev=True代表Dev日志记录器;dev=False代表User日志记录器
  • 为了方便开发人员开发调试,提供参数dev_log_enabled,为True的时候,控制台会打印属于 Dev 记录器的日志信息,反之则不打印;
  • 同时为了方便开发人员debug,能够在生产端脚本报错的情况下,在开发端快速定位,引入装饰器快速实现执行每个方法时,方法开始和结束的日志记录;

3. User日志记录器

  • 高于或等于设置的日志事件等级的日志,控制台和log文件都会记录;

3.1 记录器标签内容介绍

  • User 代表给用户看的日志内容;
  • D 代表该日志等级为debug;
  • 2024-08-12 18:57:44 代表打印日志的时间;
  • auto_logger 代表当前模块名称;
  • 121代表代码在当前模块所在行数;
  • This is a debug message 代表用户要看到的信息;
[User D 2024-08-12 18:57:44 auto_logger:121] This is a debug message

3.2 程序打印User日志规则

  • 按照需求分析表步骤编号打印

  • 日志内容格式规则:

    • Step:按照项目需求分析表中的步骤编号填写;
    • 步骤内容:按照项目需求分析表中的需求描述或功能介绍填写;
    • 信息反馈:按照项目需求分析表中的预期效果填写;
    • 测试结果:执行成功为PASS, 反之则为FAIL;
#例子:

#代码
logger.info("""
    Step: 1-1-1
    步骤内容: 设置UAC:搜索UAC->选择Change User Account Control settings打开UAC设置界面->设置UAC为Never notify->点击ok完成
    信息反馈: 成功设置UAC为Never notify
    测试结果: PASS
    """)

# 实际效果:
[User I 2024-08-15 10:54:59 auto_logger:130] 
    Step: 1-1-1
    步骤内容: 设置UAC:搜索UAC->选择Change User Account Control settings打开UAC设置界面->设置UAC为Never notify->点击ok完成
    信息反馈: 成功设置UAC为Never notify
    测试结果: PASS

4. Dev日志记录器

4.1 记录器标签内容介绍

  • Dev代表这是给开发/测试/需求人员的,可以设置是否需要在控制台上打印
  • 其他内容同User日志记录器;
[Dev  I 2024-08-12 19:00:26 auto_logger:122] This is an info message

4.2 程序打印Dev日志规则

  • 要求程序执行每个方法前需要打印"STA: 方法名",执行完方法以后,打印"END:方法名";
# 例子
# 利用装饰器实现

import time


def log_execution(func):
    def wrapper(*args, **kwargs):
        logger.info(f"STA: {func.__qualname__}", dev=True)
        result = func(*args, **kwargs)
        logger.info(f"END: {func.__qualname__}", dev=True)
        return result

    return wrapper


class MyClass:
    @log_execution
    def my_method_1(self):
        time.sleep(1)
        logger.info("正在执行 my_method_1")

    @log_execution
    def my_method_2(self, x):
        time.sleep(2)
        logger.info(f"正在执行 my_method_2,参数: {x}")


# 示例用法
obj = MyClass()
obj.my_method_1()
obj.my_method_2(5)


# log展示:
"""
[Dev  I 2024-08-15 14:07:41 auto_logger:142] STA: MyClass.my_method_1
[User I 2024-08-15 14:07:42 auto_logger:154] 正在执行 my_method_1
[Dev  I 2024-08-15 14:07:42 auto_logger:144] END: MyClass.my_method_1
[Dev  I 2024-08-15 14:07:42 auto_logger:142] STA: MyClass.my_method_2
[User I 2024-08-15 14:07:44 auto_logger:159] 正在执行 my_method_2,参数: 5
[Dev  I 2024-08-15 14:07:44 auto_logger:144] END: MyClass.my_method_2
"""

5.代码说明

5.1 代码详情

import logging
import os

import colorlog

CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0


class LoggerManager:
    def __init__(self, log_file='log.txt'):

        self.file_handler_formatter = '[%(name)s %(levelname)1.1s %(asctime)s %(module)s:%(lineno)d] %(message)s'
        self.console_handler_formatter = '%(log_color)s[%(name)s %(levelname)1.1s %(asctime)s %(module)s:%(lineno)d] %(log_color)s%(message)s'
        self.color_formatter = colorlog.ColoredFormatter(
            self.console_handler_formatter,
            datefmt='%Y-%m-%d %H:%M:%S',
            log_colors={
                'DEBUG': 'cyan',
                'INFO': 'green',
                'WARNING': 'yellow',
                'ERROR': 'red',
                'CRITICAL': 'bold_red'
            }
        )

        # 设置日志文件路径
        self.log_file = os.path.join(os.getcwd(), log_file)

        # 控制台处理器(可选)
        self._dev_log_enabled = False
        self.console_handler = None
        self.user_logger = self._create_user_logger()
        self.dev_logger = self._create_dev_logger()

    def logfile(self, filename, mode='a', encoding=None, delay=False, errors=None):

        # 添加文件处理器
        file_handler = logging.FileHandler(filename, mode=mode, encoding=encoding, delay=delay, errors=errors)
        file_handler.setLevel(logging.DEBUG)
        formatter = logging.Formatter(self.file_handler_formatter, datefmt="%Y-%m-%d %H:%M:%S")
        file_handler.setFormatter(formatter)

        # 添加文件处理器
        self.user_logger.addHandler(file_handler)

        self.dev_logger.addHandler(file_handler)

    def _create_user_logger(self):
        logger_ = logging.getLogger('User')
        logger_.setLevel(logging.DEBUG)

        # 控制台处理器
        console_handler = colorlog.StreamHandler()
        console_handler.setLevel(logging.DEBUG)
        console_handler.setFormatter(self.color_formatter)
        logger_.addHandler(console_handler)

        return logger_

    @staticmethod
    def _create_dev_logger():
        logger_ = logging.getLogger('Dev ')
        logger_.setLevel(logging.DEBUG)

        return logger_

    @property
    def dev_log_enabled(self):
        """控制Dev记录器的控制台处理器的启用和禁用"""
        return self._dev_log_enabled

    @dev_log_enabled.setter
    def dev_log_enabled(self, value):
        """启用或禁用控制台处理器"""
        if value and not self._dev_log_enabled:
            # 如果请求启用并且当前未启用,则添加控制台处理器
            if self.console_handler is None:
                self.console_handler = colorlog.StreamHandler()
                self.console_handler.setLevel(logging.DEBUG)
                self.console_handler.setFormatter(self.color_formatter)
            self.dev_logger.addHandler(self.console_handler)
        elif not value and self._dev_log_enabled:
            # 如果请求禁用并且当前已启用,则移除控制台处理器
            self.dev_logger.removeHandler(self.console_handler)

        self._dev_log_enabled = value

    def set_log_level(self, level):
        """设置 User 和 Dev 记录器的日志级别"""
        self.user_logger.setLevel(level)
        self.dev_logger.setLevel(level)
        for handler in self.user_logger.handlers:
            handler.setLevel(level)
        for handler in self.dev_logger.handlers:
            handler.setLevel(level)

    def debug(self, message, dev=False):
        logger_ = self.dev_logger if dev else self.user_logger
        logger_.debug(message, stacklevel=2)

    def info(self, message, dev=False):
        logger_ = self.dev_logger if dev else self.user_logger
        logger_.info(message, stacklevel=2)

    def warning(self, message, dev=False):
        logger_ = self.dev_logger if dev else self.user_logger
        logger_.warning(message, stacklevel=2)

    def error(self, message, dev=False):
        logger_ = self.dev_logger if dev else self.user_logger
        logger_.error(message, stacklevel=2)

    def critical(self, message, dev=False):
        logger_ = self.dev_logger if dev else self.user_logger
        logger_.critical(message, stacklevel=2)

logger = LoggerManager()

5.2 使用说明

# 日志模块

# 实例化;
logger = LoggerManager() 

# 为记录器添加文件处理器;不添加则不生成日志文件;
logger.logfile(filename="1.txt") 

# 设置log_level
logger.set_log_level(level=INFO)

# 启用 Dev 记录器的控制台处理器;
# 为True的时候,控制台会打印属于 Dev 记录器的日志信息,反之则不打印;
logger.dev_log_enabled = True

# dev参数默认为False;
# True表示该日志属于 Dev 日志记录器,反之表示该日志属于 User 记录器;
# 表示这条消息在logger.dev_log_enabled设置为False的时候,不会打印在系统终端;
logger.info('This is an info message', dev=True)

logger.debug('This is a debug message')
logger.info('This is an info message')
logger.warning('This is a warning message')
logger.error('This is an error message')
logger.critical('This is a critical message')
  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值