Files
feishu_screen/utils/logger.py

185 lines
4.9 KiB
Python
Raw 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.
"""
日志记录工具
"""
import logging
import sys
from pathlib import Path
from typing import Optional
def setup_logger(
name: str = 'screen2feishu',
log_file: Optional[str] = None,
level: str = 'INFO',
format: str = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
) -> logging.Logger:
"""
设置日志记录器
Args:
name: 日志记录器名称
log_file: 日志文件路径如果为None则只输出到控制台
level: 日志级别 (DEBUG, INFO, WARNING, ERROR, CRITICAL)
format: 日志格式
Returns:
配置好的日志记录器
"""
# 创建日志记录器
logger = logging.getLogger(name)
# 避免重复配置
if logger.handlers:
return logger
# 设置日志级别
level_map = {
'DEBUG': logging.DEBUG,
'INFO': logging.INFO,
'WARNING': logging.WARNING,
'ERROR': logging.ERROR,
'CRITICAL': logging.CRITICAL
}
log_level = level_map.get(level.upper(), logging.INFO)
logger.setLevel(log_level)
# 创建格式化器
formatter = logging.Formatter(format, datefmt='%Y-%m-%d %H:%M:%S')
# 创建控制台处理器
# 在Windows系统上确保使用UTF-8编码输出
if sys.platform == 'win32':
import io
console_handler = logging.StreamHandler(io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8'))
else:
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
# 创建文件处理器(如果指定了日志文件)
if log_file:
log_path = Path(log_file)
# 确保日志目录存在
log_path.parent.mkdir(parents=True, exist_ok=True)
file_handler = logging.FileHandler(log_path, encoding='utf-8')
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
return logger
def get_logger(name: str = 'screen2feishu') -> logging.Logger:
"""
获取已配置的日志记录器
Args:
name: 日志记录器名称
Returns:
日志记录器
"""
return logging.getLogger(name)
def log_function_call(logger: logging.Logger, func_name: str, *args, **kwargs):
"""
记录函数调用日志
Args:
logger: 日志记录器
func_name: 函数名
*args: 位置参数
**kwargs: 关键字参数
"""
args_str = ', '.join(repr(arg) for arg in args)
kwargs_str = ', '.join(f'{k}={repr(v)}' for k, v in kwargs.items())
all_args = ', '.join(filter(None, [args_str, kwargs_str]))
logger.debug(f"调用函数: {func_name}({all_args})")
def log_function_result(logger: logging.Logger, func_name: str, result):
"""
记录函数返回结果日志
Args:
logger: 日志记录器
func_name: 函数名
result: 函数返回结果
"""
logger.debug(f"函数 {func_name} 返回: {repr(result)}")
def log_error_with_context(logger: logging.Logger, error: Exception, context: str = ""):
"""
记录错误日志,包含上下文信息
Args:
logger: 日志记录器
error: 异常对象
context: 错误上下文信息
"""
if context:
logger.error(f"{context}: {str(error)}")
else:
logger.error(f"错误: {str(error)}")
def create_log_rotation_handler(
log_file: str,
max_bytes: int = 10 * 1024 * 1024, # 10MB
backup_count: int = 5
) -> logging.Handler:
"""
创建支持日志轮转的文件处理器
Args:
log_file: 日志文件路径
max_bytes: 单个日志文件最大字节数
backup_count: 备份文件数量
Returns:
文件处理器
"""
from logging.handlers import RotatingFileHandler
log_path = Path(log_file)
log_path.parent.mkdir(parents=True, exist_ok=True)
handler = RotatingFileHandler(
log_file,
maxBytes=max_bytes,
backupCount=backup_count,
encoding='utf-8'
)
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
handler.setFormatter(formatter)
return handler
if __name__ == "__main__":
# 测试日志功能
logger = setup_logger(
name='test_logger',
log_file='test.log',
level='DEBUG'
)
logger.debug("这是一条调试信息")
logger.info("这是一条普通信息")
logger.warning("这是一条警告信息")
logger.error("这是一条错误信息")
# 测试函数调用日志
log_function_call(logger, "test_function", "arg1", "arg2", key="value")
log_function_result(logger, "test_function", {"result": "success"})
log_error_with_context(logger, Exception("测试错误"), "处理数据时")