autool/logging_config.py
2026-06-17 19:44:18 +08:00

230 lines
6.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- encoding=utf8 -*-
"""
统一的日志配置模块
此模块提供了整个项目的日志管理功能,包括:
- 统一的日志格式
- 集中的日志级别控制
- 第三方库日志管理
- 支持文件和控制台输出
"""
import logging
import sys
from pathlib import Path
from typing import Optional, List
# 默认日志格式
DEFAULT_LOG_FORMAT = '%(asctime)s %(name)-20s %(levelname)-8s %(message)s'
DEFAULT_DATE_FORMAT = '%Y-%m-%d %H:%M:%S'
# 需要抑制的第三方库logger
THIRD_PARTY_LOGGERS = [
# Airtest相关
'airtest',
'adb',
'airtest.core.android.adb',
# 网络相关
'urllib3',
'urllib3.connectionpool',
'requests',
# AI/ML相关
'transformers',
'torch',
'tensorflow',
# 图像处理
'PIL',
'PIL.PngImagePlugin',
'PIL.Image',
'matplotlib',
'cv2',
# 其他
'filelock',
'webdriver_manager',
]
def setup_logging(
level: int = logging.INFO,
log_file: Optional[str] = None,
log_format: str = DEFAULT_LOG_FORMAT,
date_format: str = DEFAULT_DATE_FORMAT,
debug_mode: bool = False,
enable_file_handler: bool = True,
enable_console_handler: bool = True,
third_party_level: int = logging.WARNING,
custom_third_party_loggers: Optional[List[str]] = None
) -> logging.Logger:
"""
统一配置项目日志系统
Args:
level: 主日志级别 (默认: logging.INFO)
log_file: 日志文件路径None表示不写入文件
log_format: 日志格式字符串
date_format: 日期格式字符串
debug_mode: 是否启用调试模式会将level设为DEBUG
enable_file_handler: 是否启用文件处理器
enable_console_handler: 是否启用控制台处理器
third_party_level: 第三方库的日志级别
custom_third_party_loggers: 额外需要抑制的第三方logger名称列表
Returns:
配置好的根logger对象
Example:
# 基本使用
setup_logging()
logger = logging.getLogger(__name__)
logger.info("Application started")
# 带文件输出
setup_logging(log_file="app.log", debug_mode=True)
# 仅文件输出,不输出到控制台
setup_logging(log_file="app.log", enable_console_handler=False)
"""
# Debug模式覆盖级别设置
if debug_mode:
level = logging.DEBUG
# 准备handlers
handlers = []
formatter = logging.Formatter(log_format, datefmt=date_format)
# 控制台handler
if enable_console_handler:
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(formatter)
console_handler.setLevel(level)
handlers.append(console_handler)
# 文件handler
if enable_file_handler and log_file:
# 确保日志目录存在
log_path = Path(log_file)
log_path.parent.mkdir(parents=True, exist_ok=True)
file_handler = logging.FileHandler(log_file, encoding='utf-8')
file_handler.setFormatter(formatter)
file_handler.setLevel(level)
handlers.append(file_handler)
# 配置根logger
logging.basicConfig(
level=level,
format=log_format,
datefmt=date_format,
handlers=handlers,
force=True # 强制覆盖已有配置
)
# 配置第三方库日志级别
all_third_party = THIRD_PARTY_LOGGERS.copy()
if custom_third_party_loggers:
all_third_party.extend(custom_third_party_loggers)
for logger_name in all_third_party:
logging.getLogger(logger_name).setLevel(third_party_level)
root_logger = logging.getLogger()
return root_logger
def get_logger(name: str = None) -> logging.Logger:
"""
获取logger实例的便捷函数
Args:
name: logger名称通常传入 __name__。如果为None返回root logger
Returns:
Logger实例
Example:
logger = get_logger(__name__)
logger.info("Message")
"""
return logging.getLogger(name)
def set_module_log_level(module_name: str, level: int):
"""
设置特定模块的日志级别
Args:
module_name: 模块名称
level: 日志级别
Example:
# 只看DroidBot的DEBUG日志
set_module_log_level('DroidBot', logging.DEBUG)
# 完全禁用某个模块的日志
set_module_log_level('noisy_module', logging.CRITICAL)
"""
logging.getLogger(module_name).setLevel(level)
def disable_third_party_logs():
"""
完全禁用所有第三方库的日志输出
Example:
disable_third_party_logs()
"""
for logger_name in THIRD_PARTY_LOGGERS:
logging.getLogger(logger_name).setLevel(logging.CRITICAL + 1)
# 便捷的配置预设
def setup_basic_logging():
"""基础配置INFO级别仅控制台输出"""
return setup_logging(level=logging.INFO, enable_file_handler=False)
def setup_debug_logging(log_file: str = None):
"""调试配置DEBUG级别控制台+文件输出"""
return setup_logging(
level=logging.DEBUG,
log_file=log_file,
debug_mode=True
)
def setup_production_logging(log_file: str):
"""生产配置INFO级别仅文件输出"""
return setup_logging(
level=logging.INFO,
log_file=log_file,
enable_console_handler=False
)
if __name__ == "__main__":
# 测试日志配置
print("=== 测试日志配置 ===\n")
# 测试1: 基础配置
print("1. 基础配置测试")
setup_basic_logging()
logger = get_logger(__name__)
logger.debug("这条DEBUG不会显示")
logger.info("这条INFO会显示")
logger.warning("这条WARNING会显示")
print("\n2. 调试模式测试")
setup_debug_logging()
logger.debug("调试模式下这条DEBUG会显示")
logger.info("这条INFO也会显示")
print("\n3. 第三方库日志抑制测试")
third_party_logger = logging.getLogger('urllib3')
third_party_logger.warning("这条第三方WARNING不会显示被抑制到WARNING级别以上")
print("\n测试完成!")