From 1382c6a106f181d10d71c0efdf074b0699147985 Mon Sep 17 00:00:00 2001 From: z0z0r4 Date: Fri, 29 Nov 2024 13:58:40 +0800 Subject: [PATCH] rechore: logging --- app/config/mcim.py | 5 - app/controller/curseforge/v1/__init__.py | 2 - app/controller/modrinth/v2/__init__.py | 2 - app/utils/loger/__init__.py | 164 ++++++++--------------- start.py | 2 +- 5 files changed, 54 insertions(+), 121 deletions(-) diff --git a/app/config/mcim.py b/app/config/mcim.py index e5f029b..509431f 100644 --- a/app/config/mcim.py +++ b/app/config/mcim.py @@ -58,11 +58,6 @@ class MCIMConfigModel(BaseModel): open93home_endpoint: str = "http://open93home" expire_second: ExpireSecond = ExpireSecond() - expire_status_code: int = 404 - uncache_status_code: int = 404 - - log_to_file: bool = False - log_path: str = "./logs" favicon_url: str = ( "https://thirdqq.qlogo.cn/g?b=sdk&k=ABmaVOlfKKPceB5qfiajxqg&s=640" diff --git a/app/controller/curseforge/v1/__init__.py b/app/controller/curseforge/v1/__init__.py index c300a46..8f72a7b 100644 --- a/app/controller/curseforge/v1/__init__.py +++ b/app/controller/curseforge/v1/__init__.py @@ -40,8 +40,6 @@ v1_router = APIRouter(prefix="/v1", tags=["curseforge"]) -EXPIRE_STATUS_CODE = mcim_config.expire_status_code -UNCACHE_STATUS_CODE = mcim_config.uncache_status_code SEARCH_TIMEOUT = 3 """ diff --git a/app/controller/modrinth/v2/__init__.py b/app/controller/modrinth/v2/__init__.py index ffd4803..246f7b0 100644 --- a/app/controller/modrinth/v2/__init__.py +++ b/app/controller/modrinth/v2/__init__.py @@ -40,8 +40,6 @@ API = mcim_config.modrinth_api v2_router = APIRouter(prefix="/v2", tags=["modrinth"]) -EXPIRE_STATUS_CODE = mcim_config.expire_status_code -UNCACHE_STATUS_CODE = mcim_config.uncache_status_code SEARCH_TIMEOUT = 3 diff --git a/app/utils/loger/__init__.py b/app/utils/loger/__init__.py index b5df190..75447db 100644 --- a/app/utils/loger/__init__.py +++ b/app/utils/loger/__init__.py @@ -2,8 +2,6 @@ import os import sys import logging -from types import FrameType -from typing import cast from loguru import logger import time @@ -14,119 +12,63 @@ mcim_config = MCIMConfig.load() -LOG_PATH = mcim_config.log_path -if mcim_config.log_to_file: - os.makedirs(LOG_PATH, exist_ok=True) - -ENABLED: bool = False - -EXCLUDED_KEYWORDS = ["metrics", "httpx"] -EXCULDED_ENDPOINTS = ["/metrics"] - -def filter(record) -> bool: - """ - Filter out log entries for excluded endpoints. - - Args: - record: The log record to be filtered. - - Returns: - bool: True if the log entry should be included, False otherwise. - """ - if isinstance(record, logging.LogRecord): - return record.args and len(record.args) >= 3 and record.args[2] not in EXCULDED_ENDPOINTS - return not any(keyword in record["message"] for keyword in EXCLUDED_KEYWORDS) - - -class Logger: - """输出日志到文件和控制台""" - - def __init__(self): - # 文件的命名 - log_path = os.path.join(LOG_PATH, "fastapi", "{time:YYYY-MM-DD}.log") - self.logger = logger - # 清空所有设置 - self.logger.remove() - # 判断日志文件夹是否存在,不存则创建 - if not os.path.exists(LOG_PATH): - os.makedirs(LOG_PATH) - # 添加控制台输出的格式,sys.stdout为输出到屏幕;关于这些配置还需要自定义请移步官网查看相关参数说明 - self.logger.add( - sys.stdout, - format="{time:YYYYMMDD HH:mm:ss} | " # 颜色>时间 - # "{process.name} | " # 进程名 - # "{thread.name} | " # 进程名 - "{module}.{function} | " # 模块名.方法名 - # ":{line} | " # 行号 - "{level}: " # 等级 - "{message}", # 日志内容 - level="INFO" if not mcim_config.debug else "DEBUG", - backtrace=False, - diagnose=False, - filter=filter, - ) - if mcim_config.log_to_file: - # 日志写入文件 - self.logger.add( - log_path, # 写入目录指定文件 - format="{time:YYYYMMDD HH:mm:ss} - " # 时间 - # "{process.name} | " # 进程名 - # "{thread.name} | " # 进程名 - "{module}.{function}:{line} - {level} -{message}", # 模块名.方法名:行号 - encoding="utf-8", - retention="7 days", # 设置历史保留时长 - backtrace=True, # 回溯 - diagnose=True, # 诊断 - enqueue=True, # 异步写入 - rotation="00:00", # 每日更新时间 - # rotation="5kb", # 切割,设置文件大小,rotation="12:00",rotation="1 week" - # filter="my_module" # 过滤模块 - # compression="zip" # 文件压缩 - level="INFO" if not mcim_config.debug else "DEBUG", - filter=filter, - ) - - def get_logger(self): - return self.logger - - def init_config(self): - global ENABLED - if not ENABLED: - LOGGER_NAMES = ("uvicorn.asgi", "uvicorn.access", "uvicorn") - - # change handler for default uvicorn logger - logging.getLogger().handlers = [InterceptHandler()] - for logger_name in LOGGER_NAMES: - logging_logger = logging.getLogger(logger_name) - # log level - if not mcim_config.debug: - logging_logger.setLevel(logging.INFO) - else: - logging_logger.setLevel(logging.DEBUG) - logging_logger.handlers = [InterceptHandler()] - logging_logger.addFilter(filter) - ENABLED = True - +# 清空 root 日志器的 handlers +logging.root.handlers = [] +# 定义一个拦截标准日志的处理器 class InterceptHandler(logging.Handler): - def emit(self, record: logging.LogRecord) -> None: # pragma: no cover - # Get corresponding Loguru level if it exists + def emit(self, record): + # 获取对应的 Loguru 日志等级 try: level = logger.level(record.levelname).name except ValueError: - level = str(record.levelno) - - # Find caller from where originated the logged message + level = record.levelno + # 重建 LogRecord,以确保格式正确 frame, depth = logging.currentframe(), 2 - while frame.f_code.co_filename == logging.__file__: # noqa: WPS609 - frame = cast(FrameType, frame.f_back) + while frame.f_code.co_filename == logging.__file__: + frame = frame.f_back depth += 1 - - logger.opt(depth=depth, exception=record.exc_info).log( - level, - record.getMessage(), - ) - -Loggers = Logger() -Loggers.init_config() -log = Loggers.get_logger() \ No newline at end of file + logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage()) + +# 配置 Loguru 日志器 +logger.remove() +logger.add( + sys.stdout, + level="DEBUG" if mcim_config.debug else "INFO", + format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {module}.{function}.{line} | {message}", + colorize=True, + backtrace=True, + diagnose=True, +) + +# 拦截标准日志并重定向到 Loguru +logging.basicConfig(handlers=[InterceptHandler()], level=0) + +# 要忽略的路由列表 +routes_to_ignore = ["/ignore_this_route", "/and_this_route"] + +# 定义过滤器 +def filter_uvicorn_access(record: logging.LogRecord) -> bool: + message = record.getMessage() + for route in routes_to_ignore: + if route in message: + return False # 过滤该日志 + return True # 保留该日志 + +# 为 uvicorn.access 日志器添加过滤器 +access_logger = logging.getLogger("uvicorn.access") +access_logger.addFilter(filter_uvicorn_access) + +# 处理 uvicorn 日志器 +for uvicorn_logger in ("uvicorn", "uvicorn.error", "uvicorn.access", "uvicorn.asgi"): + uv_logger = logging.getLogger(uvicorn_logger) + uv_logger.handlers = [InterceptHandler()] + uv_logger.propagate = False + +# 禁用日志器 +logging.getLogger("httpx").propagate = False +logging.getLogger("httpcore").propagate = False +logging.getLogger("pymongo").propagate = False + +# 导出 logger +log = logger \ No newline at end of file diff --git a/start.py b/start.py index ffbc23b..5f3fa16 100644 --- a/start.py +++ b/start.py @@ -6,6 +6,6 @@ mcim_config = MCIMConfig.load() if __name__ == "__main__": - config = uvicorn.Config(APP, host=mcim_config.host, port=mcim_config.port) + config = uvicorn.Config(APP, host=mcim_config.host, port=mcim_config.port, log_config=None) server = uvicorn.Server(config) server.run()