mirror of
https://github.com/snailyp/gemini-balance.git
synced 2026-06-01 05:39:47 +08:00
新增自定义日志模块,替换全局logging实现;优化日志输出格式与颜色支持
This commit is contained in:
3
.vscode/launch.json
vendored
3
.vscode/launch.json
vendored
@@ -15,7 +15,8 @@
|
||||
"--host",
|
||||
"127.0.0.1",
|
||||
"--port",
|
||||
"8000"
|
||||
"8000",
|
||||
"--no-access-log"
|
||||
],
|
||||
"jinja": true
|
||||
}
|
||||
|
||||
@@ -17,4 +17,4 @@ ENV MODEL_SEARCH='["gemini-2.0-flash-exp"]'
|
||||
EXPOSE 8000
|
||||
|
||||
# Run the application
|
||||
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--no-access-log"]
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from http.client import HTTPException
|
||||
from fastapi import APIRouter, Depends, Header
|
||||
import logging
|
||||
from fastapi.responses import StreamingResponse
|
||||
|
||||
from app.core.security import SecurityService
|
||||
@@ -10,9 +9,10 @@ from app.services.chat_service import ChatService
|
||||
from app.services.embedding_service import EmbeddingService
|
||||
from app.schemas.request_model import ChatRequest, EmbeddingRequest
|
||||
from app.core.config import settings
|
||||
from app.core.logger import get_api_logger
|
||||
|
||||
router = APIRouter()
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = get_api_logger()
|
||||
|
||||
# 初始化服务
|
||||
security_service = SecurityService(settings.ALLOWED_TOKENS)
|
||||
@@ -59,7 +59,6 @@ async def chat_completion(
|
||||
tools=request.tools,
|
||||
tool_choice=request.tool_choice,
|
||||
)
|
||||
|
||||
|
||||
# 处理流式响应
|
||||
if request.stream:
|
||||
|
||||
105
app/core/logger.py
Normal file
105
app/core/logger.py
Normal file
@@ -0,0 +1,105 @@
|
||||
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:
|
||||
_loggers: Dict[str, logging.Logger] = {}
|
||||
|
||||
@staticmethod
|
||||
def setup_logger(
|
||||
name: str,
|
||||
level: str = "info",
|
||||
) -> 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_api_logger():
|
||||
return Logger.setup_logger("api")
|
||||
|
||||
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")
|
||||
@@ -1,8 +1,8 @@
|
||||
from fastapi import HTTPException, Header
|
||||
import logging
|
||||
from typing import Optional
|
||||
from app.core.logger import get_security_logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = get_security_logger()
|
||||
|
||||
|
||||
class SecurityService:
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
import logging
|
||||
from app.core.logger import get_main_logger
|
||||
|
||||
from app.api.routes import router
|
||||
import uvicorn
|
||||
|
||||
# 配置日志
|
||||
logging.basicConfig(
|
||||
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = get_main_logger()
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -2,12 +2,12 @@ import httpx
|
||||
import json
|
||||
import time
|
||||
import uuid
|
||||
import logging
|
||||
from typing import Dict, Any, Optional, AsyncGenerator, Union
|
||||
import openai
|
||||
from app.core.config import settings
|
||||
from app.core.logger import get_chat_logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = get_chat_logger()
|
||||
|
||||
|
||||
class ChatService:
|
||||
@@ -170,6 +170,9 @@ class ChatService:
|
||||
gemini_model = model
|
||||
gemini_messages = self.convert_messages_to_gemini_format(messages)
|
||||
|
||||
if not stream:
|
||||
# 非流式模式下,移除代码执行工具
|
||||
tools.remove({"code_execution": {}})
|
||||
payload = {
|
||||
"contents": gemini_messages,
|
||||
"generationConfig": {"temperature": temperature},
|
||||
@@ -241,7 +244,9 @@ class ChatService:
|
||||
url = f"https://generativelanguage.googleapis.com/v1beta/models/{gemini_model}:generateContent?key={api_key}"
|
||||
response = await client.post(url, json=payload)
|
||||
if response.status_code != 200:
|
||||
raise Exception(f"API error: {response.status_code}")
|
||||
error_text = response.text
|
||||
error_code = response.status_code
|
||||
raise Exception(f"API调用错误 - 状态码: {error_code}, 响应内容: {error_text}")
|
||||
gemini_response = response.json()
|
||||
return self.convert_gemini_response_to_openai(gemini_response, model, finish_reason="stop")
|
||||
except Exception as e:
|
||||
@@ -287,10 +292,10 @@ class ChatService:
|
||||
language = code_data.get("language", "").lower()
|
||||
code = code_data.get("code", "").strip()
|
||||
|
||||
return f"""\n```{language}\n{code}\n```\n"""
|
||||
return f"""\n【代码执行】\n```{language}\n{code}\n```\n"""
|
||||
|
||||
def format_execution_result(self, result_data: dict) -> str:
|
||||
"""格式化执行结果输出"""
|
||||
outcome = result_data.get("outcome", "")
|
||||
output = result_data.get("output", "").strip()
|
||||
return f"""\n【执行结果】\noutcome: {outcome}\noutput: {output}\n"""
|
||||
return f"""\n【执行结果】\noutcome: {outcome}\noutput:\n```{output}```\n"""
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import logging
|
||||
import openai
|
||||
from typing import Union, List, Dict, Any
|
||||
from app.core.logger import get_embeddings_logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = get_embeddings_logger()
|
||||
|
||||
|
||||
class EmbeddingService:
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import asyncio
|
||||
from itertools import cycle
|
||||
import logging
|
||||
from typing import Dict
|
||||
from app.core.logger import get_key_manager_logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = get_key_manager_logger()
|
||||
|
||||
|
||||
class KeyManager:
|
||||
@@ -42,7 +42,7 @@ class KeyManager:
|
||||
|
||||
current_key = await self.get_next_key()
|
||||
if current_key == initial_key:
|
||||
await self.reset_failure_counts()
|
||||
# await self.reset_failure_counts() 取消重置
|
||||
return current_key
|
||||
|
||||
async def handle_api_failure(self, api_key: str) -> str:
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import requests
|
||||
from datetime import datetime, timezone
|
||||
from typing import Optional, Dict, Any
|
||||
import logging
|
||||
from app.core.logger import get_model_logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = get_model_logger()
|
||||
|
||||
|
||||
class ModelService:
|
||||
|
||||
Reference in New Issue
Block a user