Files
gemini-balance/app/log/logger.py
snaily 169488851f feat: 集成数据库配置管理并添加错误日志查看器
主要变更:

1.  **数据库集成**:
    *   引入 MySQL 数据库支持,使用 SQLAlchemy 和 `databases` 库持久化存储应用程序设置。
    *   添加了 `app/database` 目录,包含数据库连接、模型和初始化逻辑。
    *   更新 `requirements.txt` 添加数据库相关依赖 (`pymysql`, `sqlalchemy`, `aiomysql`, `databases`, `python-dotenv`)。

2.  **配置管理重构**:
    *   重构 `ConfigService` (`app/service/config/config_service.py`),使其从数据库加载和保存设置,并支持从 `.env` 文件同步初始配置到数据库。
    *   修改 `Settings` 模型 (`app/config/config.py`) 以包含数据库连接信息,并添加了从数据库加载/同步配置的逻辑。
    *   配置相关的路由 (`app/router/config_routes.py`) 更新为异步,并调用新的 `ConfigService` 方法。
    *   `KeyManager` (`app/service/key/key_manager.py`) 现在可以在配置更新后重置和重新初始化。

3.  **错误日志查看器**:
    *   新增 `/logs` 页面 (`app/templates/error_logs.html`) 用于展示应用程序错误日志。
    *   添加了相应的路由 (`app/router/log_routes.py`)、静态资源 (`app/static/css/error_logs.css`, `app/static/js/error_logs.js`) 和日志记录器 (`app/log/logger.py`)。
    *   在配置页面和密钥管理页面的导航栏中添加了指向日志页面的链接。

4.  **异步操作**:
    *   将配置服务和相关路由转换为异步 (`async def`) 以支持异步数据库操作。

5.  **其他**:
    *   更新了应用程序初始化逻辑 (`app/core/application.py`, `app/core/initialization.py`) 以包含数据库连接的建立和关闭。
2025-04-09 15:04:29 +08:00

172 lines
3.7 KiB
Python

import logging
import sys
from typing import Dict, Optional
import platform
# ANSI转义序列颜色代码
COLORS = {
'DEBUG': '\033[34m', # 蓝色
'INFO': '\033[32m', # 绿色
'WARNING': '\033[33m', # 黄色
'ERROR': '\033[31m', # 红色
'CRITICAL': '\033[1;31m' # 红色加粗
}
# Windows系统启用ANSI支持
if platform.system() == 'Windows':
import ctypes
kernel32 = ctypes.windll.kernel32
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
class ColoredFormatter(logging.Formatter):
"""
自定义的日志格式化器,添加颜色支持
"""
def format(self, record):
# 获取对应级别的颜色代码
color = COLORS.get(record.levelname, '')
# 添加颜色代码和重置代码
record.levelname = f"{color}{record.levelname}\033[0m"
return super().format(record)
# 日志格式
FORMATTER = ColoredFormatter(
"%(asctime)s - %(name)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s"
)
# 日志级别映射
LOG_LEVELS = {
"debug": logging.DEBUG,
"info": logging.INFO,
"warning": logging.WARNING,
"error": logging.ERROR,
"critical": logging.CRITICAL,
}
class Logger:
def __init__(self):
pass
_loggers: Dict[str, logging.Logger] = {}
@staticmethod
def setup_logger(
name: str,
level: str = "debug",
) -> logging.Logger:
"""
设置并获取logger
:param name: logger名称
:param level: 日志级别
:return: logger实例
"""
if name in Logger._loggers:
return Logger._loggers[name]
logger = logging.getLogger(name)
logger.setLevel(LOG_LEVELS.get(level.lower(), logging.INFO))
logger.propagate = False
# 添加控制台输出
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(FORMATTER)
logger.addHandler(console_handler)
Logger._loggers[name] = logger
return logger
@staticmethod
def get_logger(name: str) -> Optional[logging.Logger]:
"""
获取已存在的logger
:param name: logger名称
:return: logger实例或None
"""
return Logger._loggers.get(name)
# 预定义的loggers
def get_openai_logger():
return Logger.setup_logger("openai")
def get_gemini_logger():
return Logger.setup_logger("gemini")
def get_chat_logger():
return Logger.setup_logger("chat")
def get_model_logger():
return Logger.setup_logger("model")
def get_security_logger():
return Logger.setup_logger("security")
def get_key_manager_logger():
return Logger.setup_logger("key_manager")
def get_main_logger():
return Logger.setup_logger("main")
def get_embeddings_logger():
return Logger.setup_logger("embeddings")
def get_request_logger():
return Logger.setup_logger("request")
def get_retry_logger():
return Logger.setup_logger("retry")
def get_image_create_logger():
return Logger.setup_logger("image_create")
def get_exceptions_logger():
return Logger.setup_logger("exceptions")
def get_application_logger():
return Logger.setup_logger("application")
def get_initialization_logger():
return Logger.setup_logger("initialization")
def get_middleware_logger():
return Logger.setup_logger("middleware")
def get_routes_logger():
return Logger.setup_logger("routes")
def get_config_routes_logger():
return Logger.setup_logger("config_routes")
def get_config_logger():
return Logger.setup_logger("config")
def get_database_logger():
return Logger.setup_logger("database")
def get_log_routes_logger():
return Logger.setup_logger("log_routes")