Skip to content

Commit 9be2ce7

Browse files
committed
update:日志添加版本显示
1 parent 4f8b302 commit 9be2ce7

File tree

4 files changed

+99
-32
lines changed

4 files changed

+99
-32
lines changed

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ pydantic==2.5.0
66
python-dotenv==1.0.0
77
configparser==6.0.0
88
asyncio-mqtt==0.16.1
9-
pycryptodome==3.23.0
9+
pycryptodome==3.23.0
10+
loguru==0.7.2

src/server.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
JSONRPCProtocol,
1616
)
1717
from src.utils.util import get_local_ip
18+
from .utils import __version__
1819
from contextlib import asynccontextmanager
1920
from fastapi.responses import RedirectResponse
2021
from fastapi.middleware.cors import CORSMiddleware
@@ -90,7 +91,7 @@ async def lifespan(app: FastAPI):
9091
app = FastAPI(
9192
title="MCP Endpoint Server",
9293
description="高效的WebSocket中转服务器",
93-
version="1.0.0",
94+
version=__version__,
9495
lifespan=lifespan,
9596
)
9697

@@ -117,7 +118,7 @@ async def root():
117118
response = JSONRPCProtocol.create_success_response(
118119
result={
119120
"message": "MCP Endpoint Server",
120-
"version": "1.0.0",
121+
"version": __version__,
121122
"status": "running",
122123
}
123124
)
@@ -222,6 +223,11 @@ def signal_handler(signum, frame):
222223

223224
def main():
224225
"""主函数"""
226+
# 设置uvicorn日志拦截
227+
from .utils.logger import logger_manager
228+
229+
logger_manager.setup_uvicorn_logging()
230+
225231
# 注册信号处理器
226232
signal.signal(signal.SIGINT, signal_handler)
227233
signal.signal(signal.SIGTERM, signal_handler)
@@ -241,6 +247,8 @@ def main():
241247
reload=debug,
242248
log_level=config.get("server", "log_level", "INFO").lower(),
243249
access_log=False,
250+
log_config=None, # 禁用uvicorn默认日志配置
251+
use_colors=True, # 启用颜色支持
244252
)
245253

246254

src/utils/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"""
2+
工具模块
3+
"""
4+
5+
__version__ = "0.0.6"

src/utils/logger.py

Lines changed: 82 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,61 +2,97 @@
22
日志管理工具
33
"""
44

5-
import logging
6-
import logging.handlers
75
import os
6+
import sys
7+
import logging
88
from typing import Optional
9+
from loguru import logger
910
from .config import config
1011

12+
# 版本号
13+
from . import __version__ as VERSION
14+
15+
16+
class InterceptHandler(logging.Handler):
17+
"""拦截标准库日志并转发到loguru"""
18+
19+
def emit(self, record):
20+
# 获取对应的loguru级别
21+
try:
22+
level = logger.level(record.levelname).name
23+
except ValueError:
24+
level = record.levelno
25+
26+
# 查找调用者
27+
frame, depth = sys._getframe(6), 6
28+
while frame and frame.f_code.co_filename == __file__:
29+
frame = frame.f_back
30+
depth += 1
31+
32+
logger.opt(depth=depth, exception=record.exc_info).log(
33+
level, record.getMessage()
34+
)
35+
1136

1237
class LoggerManager:
1338
"""日志管理器"""
1439

1540
def __init__(self):
16-
self.logger = None
1741
self._setup_logger()
1842

1943
def _setup_logger(self):
2044
"""设置日志器"""
21-
self.logger = logging.getLogger("mcp_server")
22-
23-
# 设置日志级别
24-
log_level = config.get("server", "log_level", "INFO")
25-
self.logger.setLevel(getattr(logging, log_level.upper(), logging.INFO))
26-
27-
# 清除现有的处理器
28-
self.logger.handlers.clear()
29-
30-
# 创建格式化器
31-
formatter = logging.Formatter(
32-
"%(asctime)s - %(name)s - %(levelname)s - %(message)s",
33-
datefmt="%Y-%m-%d %H:%M:%S",
45+
# 移除默认的处理器
46+
logger.remove()
47+
48+
# 自定义格式:时间[版本号][模块路径]-级别-消息
49+
# 不同部分使用不同颜色
50+
custom_format = (
51+
f"<green>{{time:YYMMDD HH:mm:ss}}</green>"
52+
f"<blue>[{VERSION}][{{name}}]</blue>"
53+
"<level>-{level}-</level>"
54+
"<green>{message}</green>"
3455
)
3556

3657
# 控制台处理器
37-
console_handler = logging.StreamHandler()
38-
console_handler.setFormatter(formatter)
39-
self.logger.addHandler(console_handler)
58+
logger.add(
59+
sys.stdout,
60+
format=custom_format,
61+
level=config.get("server", "log_level", "INFO"),
62+
colorize=True,
63+
backtrace=True,
64+
diagnose=True,
65+
enqueue=True,
66+
catch=True,
67+
)
4068

41-
# 文件处理器
69+
# 文件处理器(不带颜色)
4270
log_file = config.get("logging", "log_file", "logs/mcp_server.log")
4371
if log_file:
4472
# 确保日志目录存在
4573
os.makedirs(os.path.dirname(log_file), exist_ok=True)
4674

75+
# 文件格式(不带颜色)
76+
file_format = f"{{time:YYYY-MM-DD HH:mm:ss}} [{VERSION}][{{name}}] {{level}} - {{message}}"
77+
4778
# 获取文件大小限制
4879
max_file_size = config.get("logging", "max_file_size", "10MB")
4980
max_bytes = self._parse_size(max_file_size)
5081

5182
# 获取备份数量
5283
backup_count = config.getint("logging", "backup_count", 5)
5384

54-
# 创建轮转文件处理器
55-
file_handler = logging.handlers.RotatingFileHandler(
56-
log_file, maxBytes=max_bytes, backupCount=backup_count, encoding="utf-8"
85+
logger.add(
86+
log_file,
87+
format=file_format,
88+
level=config.get("server", "log_level", "INFO"),
89+
rotation=max_bytes,
90+
retention=backup_count,
91+
compression="zip",
92+
encoding="utf-8",
93+
enqueue=True,
94+
catch=True,
5795
)
58-
file_handler.setFormatter(formatter)
59-
self.logger.addHandler(file_handler)
6096

6197
def _parse_size(self, size_str: str) -> int:
6298
"""解析文件大小字符串"""
@@ -70,19 +106,36 @@ def _parse_size(self, size_str: str) -> int:
70106
else:
71107
return int(size_str)
72108

73-
def get_logger(self) -> logging.Logger:
109+
def get_logger(self):
74110
"""获取日志器"""
75-
return self.logger
111+
return logger
76112

77113
def reload(self):
78114
"""重新加载日志配置"""
79115
self._setup_logger()
80116

117+
def setup_uvicorn_logging(self):
118+
"""设置uvicorn日志拦截"""
119+
import logging
120+
121+
# 拦截标准库日志
122+
logging.basicConfig(handlers=[InterceptHandler()], level=0, force=True)
123+
124+
# 直接禁用uvicorn.access日志
125+
logging.getLogger("uvicorn.access").disabled = True
126+
logging.getLogger("uvicorn.access").propagate = False
127+
128+
# 拦截其他uvicorn日志
129+
for name in logging.root.manager.loggerDict.keys():
130+
if not name.startswith("uvicorn.access"):
131+
logging.getLogger(name).handlers = []
132+
logging.getLogger(name).propagate = True
133+
81134

82135
# 全局日志管理器实例
83136
logger_manager = LoggerManager()
84137

85138

86-
def get_logger() -> logging.Logger:
139+
def get_logger(name: str = "mcp_server"):
87140
"""获取日志器"""
88-
return logger_manager.get_logger()
141+
return logger.bind(name=name)

0 commit comments

Comments
 (0)