Skip to content

Commit

Permalink
rechore: logging
Browse files Browse the repository at this point in the history
  • Loading branch information
z0z0r4 committed Nov 29, 2024
1 parent 35779e7 commit 1382c6a
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 121 deletions.
5 changes: 0 additions & 5 deletions app/config/mcim.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 0 additions & 2 deletions app/controller/curseforge/v1/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

"""
Expand Down
2 changes: 0 additions & 2 deletions app/controller/modrinth/v2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down
164 changes: 53 additions & 111 deletions app/utils/loger/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
import os
import sys
import logging
from types import FrameType
from typing import cast
from loguru import logger
import time

Expand All @@ -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="<green>{time:YYYYMMDD HH:mm:ss}</green> | " # 颜色>时间
# "{process.name} | " # 进程名
# "{thread.name} | " # 进程名
"<cyan>{module}</cyan>.<cyan>{function}</cyan> | " # 模块名.方法名
# ":<cyan>{line}</cyan> | " # 行号
"<level>{level}</level>: " # 等级
"<level>{message}</level>", # 日志内容
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()
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="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{module}</cyan>.<cyan>{function}</cyan>.<cyan>{line}</cyan> | <cyan>{message}</cyan>",
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
2 changes: 1 addition & 1 deletion start.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

0 comments on commit 1382c6a

Please sign in to comment.