MoviePilot/app/log.py
2024-02-22 17:59:44 +08:00

148 lines
4.6 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 inspect
import logging
from logging.handlers import RotatingFileHandler
from pathlib import Path
from typing import Dict, Any
import click
from app.core.config import settings
# 日志级别颜色
level_name_colors = {
logging.DEBUG: lambda level_name: click.style(str(level_name), fg="cyan"),
logging.INFO: lambda level_name: click.style(str(level_name), fg="green"),
logging.WARNING: lambda level_name: click.style(str(level_name), fg="yellow"),
logging.ERROR: lambda level_name: click.style(str(level_name), fg="red"),
logging.CRITICAL: lambda level_name: click.style(
str(level_name), fg="bright_red"
),
}
class CustomFormatter(logging.Formatter):
"""
定义日志输出格式
"""
def format(self, record):
seperator = " " * (8 - len(record.levelname))
record.leveltext = level_name_colors[record.levelno](record.levelname + ":") + seperator
return super().format(record)
class LoggerManager:
"""
日志管理
"""
# 管理所有的Logger
_loggers: Dict[str, Any] = {}
# 默认日志文件
_default_log_file = "moviepilot.log"
@staticmethod
def __setup_logger(log_file: str):
"""
设置日志
log_file日志文件相对路径
"""
log_file_path = settings.LOG_PATH / log_file
if not log_file_path.parent.exists():
log_file_path.parent.mkdir(parents=True, exist_ok=True)
# 创建新实例
_logger = logging.getLogger(log_file_path.stem)
# DEBUG
if settings.DEBUG:
_logger.setLevel(logging.DEBUG)
else:
_logger.setLevel(logging.INFO)
# 移除已有的 handler避免重复添加
for handler in _logger.handlers:
_logger.removeHandler(handler)
# 终端日志
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)
console_formatter = CustomFormatter("%(leveltext)s%(name)s - %(message)s")
console_handler.setFormatter(console_formatter)
_logger.addHandler(console_handler)
# 文件日志
file_handler = RotatingFileHandler(filename=log_file_path,
mode='w',
maxBytes=5 * 1024 * 1024,
backupCount=3,
encoding='utf-8')
file_handler.setLevel(logging.INFO)
file_formater = CustomFormatter("%(levelname)s%(asctime)s - %(name)s - %(message)s")
file_handler.setFormatter(file_formater)
_logger.addHandler(file_handler)
return _logger
def logger(self, path: str) -> logging.Logger:
"""
获取模块的logger
:param path: 当前运行程序路径
"""
filepath = Path(path)
# 区分插件日志
if "plugins" in filepath.parts:
# 使用插件日志文件
plugin_name = filepath.parts[filepath.parts.index("plugins") + 1]
logfile = Path("plugins") / f"{plugin_name}.log"
else:
# 使用默认日志文件
logfile = self._default_log_file
# 获取调用者的模块的logger
_logger = self._loggers.get(logfile)
if not _logger:
_logger = self.__setup_logger(logfile)
self._loggers[logfile] = _logger
return _logger
def info(self, msg, *args, **kwargs):
"""
重载info方法按模块区分输出
"""
self.logger(inspect.stack()[1].filename).info(msg, *args, **kwargs)
def debug(self, msg, *args, **kwargs):
"""
重载debug方法按模块区分输出
"""
self.logger(inspect.stack()[1].filename).debug(msg, *args, **kwargs)
def warning(self, msg, *args, **kwargs):
"""
重载warning方法按模块区分输出
"""
self.logger(inspect.stack()[1].filename).warning(msg, *args, **kwargs)
def warn(self, msg, *args, **kwargs):
"""
重载warn方法按模块区分输出
"""
self.warning(msg, *args, **kwargs)
def error(self, msg, *args, **kwargs):
"""
重载error方法按模块区分输出
"""
self.logger(inspect.stack()[1].filename).error(msg, *args, **kwargs)
def critical(self, msg, *args, **kwargs):
"""
重载critical方法按模块区分输出
"""
self.logger(inspect.stack()[1].filename).critical(msg, *args, **kwargs)
# 初始化公共日志
logger = LoggerManager()