更换print到logger
This commit is contained in:
50
core/logger.py
Normal file
50
core/logger.py
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
"""
|
||||||
|
日志模块
|
||||||
|
|
||||||
|
该模块负责初始化和配置 loguru 日志记录器,为整个应用程序提供统一的日志记录接口。
|
||||||
|
"""
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
# 定义日志格式
|
||||||
|
LOG_FORMAT = (
|
||||||
|
"<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | "
|
||||||
|
"<level>{level: <8}</level> | "
|
||||||
|
"<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - "
|
||||||
|
"<level>{message}</level>"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 移除 loguru 默认的处理器
|
||||||
|
logger.remove()
|
||||||
|
|
||||||
|
# 添加控制台输出处理器
|
||||||
|
logger.add(
|
||||||
|
sys.stderr,
|
||||||
|
level="INFO",
|
||||||
|
format=LOG_FORMAT,
|
||||||
|
colorize=True,
|
||||||
|
enqueue=True # 异步写入
|
||||||
|
)
|
||||||
|
|
||||||
|
# 定义日志文件路径
|
||||||
|
log_dir = Path("logs")
|
||||||
|
log_dir.mkdir(exist_ok=True)
|
||||||
|
log_file_path = log_dir / "{time:YYYY-MM-DD}.log"
|
||||||
|
|
||||||
|
# 添加文件输出处理器
|
||||||
|
logger.add(
|
||||||
|
log_file_path,
|
||||||
|
level="DEBUG",
|
||||||
|
format=LOG_FORMAT,
|
||||||
|
colorize=False,
|
||||||
|
rotation="00:00", # 每天午夜创建新文件
|
||||||
|
retention="7 days", # 保留最近 7 天的日志
|
||||||
|
encoding="utf-8",
|
||||||
|
enqueue=True, # 异步写入
|
||||||
|
backtrace=True, # 记录完整的异常堆栈
|
||||||
|
diagnose=True # 添加异常诊断信息
|
||||||
|
)
|
||||||
|
|
||||||
|
# 导出配置好的 logger
|
||||||
|
__all__ = ["logger"]
|
||||||
@@ -9,6 +9,7 @@ import pkgutil
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
from core.command_manager import matcher
|
from core.command_manager import matcher
|
||||||
|
from .logger import logger
|
||||||
|
|
||||||
|
|
||||||
def load_all_plugins():
|
def load_all_plugins():
|
||||||
@@ -24,7 +25,7 @@ def load_all_plugins():
|
|||||||
plugin_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "plugins")
|
plugin_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "plugins")
|
||||||
package_name = "plugins"
|
package_name = "plugins"
|
||||||
|
|
||||||
print(f" 正在从 {package_name} 加载插件...")
|
logger.info(f"正在从 {package_name} 加载插件...")
|
||||||
|
|
||||||
for loader, module_name, is_pkg in pkgutil.iter_modules([plugin_dir]):
|
for loader, module_name, is_pkg in pkgutil.iter_modules([plugin_dir]):
|
||||||
full_module_name = f"{package_name}.{module_name}"
|
full_module_name = f"{package_name}.{module_name}"
|
||||||
@@ -43,6 +44,6 @@ def load_all_plugins():
|
|||||||
matcher.plugins[full_module_name] = meta
|
matcher.plugins[full_module_name] = meta
|
||||||
|
|
||||||
type_str = "包" if is_pkg else "文件"
|
type_str = "包" if is_pkg else "文件"
|
||||||
print(f" [{type_str}] 成功{action}: {module_name}")
|
logger.success(f" [{type_str}] 成功{action}: {module_name}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" {action if 'action' in locals() else '加载'}插件 {module_name} 失败: {e}")
|
logger.error(f" {action if 'action' in locals() else '加载'}插件 {module_name} 失败: {e}")
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import redis
|
import redis
|
||||||
from .config_loader import global_config as config
|
from .config_loader import global_config as config
|
||||||
|
from .logger import logger
|
||||||
|
|
||||||
class RedisManager:
|
class RedisManager:
|
||||||
"""
|
"""
|
||||||
@@ -20,7 +21,7 @@ class RedisManager:
|
|||||||
db = config.redis['db']
|
db = config.redis['db']
|
||||||
password = config.redis.get('password')
|
password = config.redis.get('password')
|
||||||
|
|
||||||
print(f" 正在尝试连接 Redis: {host}:{port}, DB: {db}")
|
logger.info(f"正在尝试连接 Redis: {host}:{port}, DB: {db}")
|
||||||
|
|
||||||
cls._pool = redis.ConnectionPool(
|
cls._pool = redis.ConnectionPool(
|
||||||
host=host,
|
host=host,
|
||||||
@@ -31,15 +32,15 @@ class RedisManager:
|
|||||||
)
|
)
|
||||||
cls._client = redis.Redis(connection_pool=cls._pool)
|
cls._client = redis.Redis(connection_pool=cls._pool)
|
||||||
if cls._client.ping():
|
if cls._client.ping():
|
||||||
print(" Redis 连接成功!")
|
logger.success("Redis 连接成功!")
|
||||||
else:
|
else:
|
||||||
print(" Redis 连接失败: PING 命令无响应")
|
logger.error("Redis 连接失败: PING 命令无响应")
|
||||||
except redis.exceptions.ConnectionError as e:
|
except redis.exceptions.ConnectionError as e:
|
||||||
print(f" Redis 连接失败: {e}")
|
logger.error(f"Redis 连接失败: {e}")
|
||||||
cls._pool = None
|
cls._pool = None
|
||||||
cls._client = None
|
cls._client = None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" Redis 初始化时发生未知错误: {e}")
|
logger.exception(f"Redis 初始化时发生未知错误: {e}")
|
||||||
cls._pool = None
|
cls._pool = None
|
||||||
cls._client = None
|
cls._client = None
|
||||||
|
|
||||||
|
|||||||
31
core/ws.py
31
core/ws.py
@@ -24,6 +24,7 @@ from models import EventFactory
|
|||||||
from .bot import Bot
|
from .bot import Bot
|
||||||
from .command_manager import matcher
|
from .command_manager import matcher
|
||||||
from .config_loader import global_config
|
from .config_loader import global_config
|
||||||
|
from .logger import logger
|
||||||
|
|
||||||
|
|
||||||
class WS:
|
class WS:
|
||||||
@@ -58,24 +59,23 @@ class WS:
|
|||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
print(f" 正在尝试连接至 NapCat: {self.url}")
|
logger.info(f"正在尝试连接至 NapCat: {self.url}")
|
||||||
async with websockets.connect(
|
async with websockets.connect(
|
||||||
self.url, additional_headers=headers
|
self.url, additional_headers=headers
|
||||||
) as websocket:
|
) as websocket:
|
||||||
self.ws = websocket
|
self.ws = websocket
|
||||||
print(" 连接成功!")
|
logger.success("连接成功!")
|
||||||
await self._listen_loop(websocket)
|
await self._listen_loop(websocket)
|
||||||
|
|
||||||
except (
|
except (
|
||||||
websockets.exceptions.ConnectionClosed,
|
websockets.exceptions.ConnectionClosed,
|
||||||
ConnectionRefusedError,
|
ConnectionRefusedError,
|
||||||
) as e:
|
) as e:
|
||||||
print(f" 连接断开或服务器拒绝访问: {e}")
|
logger.warning(f"连接断开或服务器拒绝访问: {e}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" 运行异常: {e}")
|
logger.exception(f"运行异常: {e}")
|
||||||
traceback.print_exc()
|
|
||||||
|
|
||||||
print(f" {self.reconnect_interval}秒后尝试重连...")
|
logger.info(f"{self.reconnect_interval}秒后尝试重连...")
|
||||||
await asyncio.sleep(self.reconnect_interval)
|
await asyncio.sleep(self.reconnect_interval)
|
||||||
|
|
||||||
async def _listen_loop(self, websocket):
|
async def _listen_loop(self, websocket):
|
||||||
@@ -108,8 +108,7 @@ class WS:
|
|||||||
asyncio.create_task(self.on_event(data))
|
asyncio.create_task(self.on_event(data))
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" 解析消息异常: {e}")
|
logger.exception(f"解析消息异常: {e}")
|
||||||
traceback.print_exc()
|
|
||||||
|
|
||||||
async def on_event(self, raw_data: dict):
|
async def on_event(self, raw_data: dict):
|
||||||
"""
|
"""
|
||||||
@@ -130,21 +129,22 @@ class WS:
|
|||||||
event.bot = self.bot # 注入 Bot 实例
|
event.bot = self.bot # 注入 Bot 实例
|
||||||
|
|
||||||
# 打印日志
|
# 打印日志
|
||||||
t = datetime.fromtimestamp(event.time).strftime("%H:%M:%S")
|
|
||||||
if event.post_type == "message":
|
if event.post_type == "message":
|
||||||
sender_name = event.sender.nickname if event.sender else "Unknown"
|
sender_name = event.sender.nickname if event.sender else "Unknown"
|
||||||
print(f" [{t}] [消息] {event.message_type} | {event.user_id}({sender_name}): {event.raw_message}")
|
logger.info(f"[消息] {event.message_type} | {event.user_id}({sender_name}): {event.raw_message}")
|
||||||
elif event.post_type == "notice":
|
elif event.post_type == "notice":
|
||||||
print(f" [{t}] [通知] {event.notice_type}")
|
logger.info(f"[通知] {event.notice_type}")
|
||||||
elif event.post_type == "request":
|
elif event.post_type == "request":
|
||||||
print(f" [{t}] [请求] {event.request_type}")
|
logger.info(f"[请求] {event.request_type}")
|
||||||
|
elif event.post_type == "meta_event":
|
||||||
|
logger.debug(f"[元事件] {event.meta_event_type}")
|
||||||
|
|
||||||
|
|
||||||
# 分发事件
|
# 分发事件
|
||||||
await matcher.handle_event(self.bot, event)
|
await matcher.handle_event(self.bot, event)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" 事件处理异常: {e}")
|
logger.exception(f"事件处理异常: {e}")
|
||||||
traceback.print_exc()
|
|
||||||
|
|
||||||
async def call_api(self, action: str, params: dict = None):
|
async def call_api(self, action: str, params: dict = None):
|
||||||
"""
|
"""
|
||||||
@@ -162,11 +162,13 @@ class WS:
|
|||||||
表示失败的字典。
|
表示失败的字典。
|
||||||
"""
|
"""
|
||||||
if not self.ws:
|
if not self.ws:
|
||||||
|
logger.error("调用 API 失败: WebSocket 未初始化")
|
||||||
return {"status": "failed", "msg": "websocket not initialized"}
|
return {"status": "failed", "msg": "websocket not initialized"}
|
||||||
|
|
||||||
from websockets.protocol import State
|
from websockets.protocol import State
|
||||||
|
|
||||||
if getattr(self.ws, "state", None) is not State.OPEN:
|
if getattr(self.ws, "state", None) is not State.OPEN:
|
||||||
|
logger.error("调用 API 失败: WebSocket 连接未打开")
|
||||||
return {"status": "failed", "msg": "websocket is not open"}
|
return {"status": "failed", "msg": "websocket is not open"}
|
||||||
|
|
||||||
echo_id = str(uuid.uuid4())
|
echo_id = str(uuid.uuid4())
|
||||||
@@ -182,5 +184,6 @@ class WS:
|
|||||||
return await asyncio.wait_for(future, timeout=30.0)
|
return await asyncio.wait_for(future, timeout=30.0)
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
self._pending_requests.pop(echo_id, None)
|
self._pending_requests.pop(echo_id, None)
|
||||||
|
logger.warning(f"API 调用超时: action={action}, params={params}")
|
||||||
return {"status": "failed", "retcode": -1, "msg": "api timeout"}
|
return {"status": "failed", "retcode": -1, "msg": "api timeout"}
|
||||||
|
|
||||||
|
|||||||
17
main.py
17
main.py
@@ -10,9 +10,11 @@ import time
|
|||||||
from watchdog.observers import Observer
|
from watchdog.observers import Observer
|
||||||
from watchdog.events import FileSystemEventHandler
|
from watchdog.events import FileSystemEventHandler
|
||||||
|
|
||||||
|
# 初始化日志系统,必须在其他 core 模块导入之前执行
|
||||||
|
from core.logger import logger
|
||||||
|
|
||||||
from core import WS
|
from core import WS
|
||||||
from core.plugin_manager import load_all_plugins
|
from core.plugin_manager import load_all_plugins
|
||||||
#from core.redis_manager import redis_client
|
|
||||||
|
|
||||||
|
|
||||||
class PluginReloadHandler(FileSystemEventHandler):
|
class PluginReloadHandler(FileSystemEventHandler):
|
||||||
@@ -55,17 +57,18 @@ class PluginReloadHandler(FileSystemEventHandler):
|
|||||||
|
|
||||||
self.last_reload_time = current_time
|
self.last_reload_time = current_time
|
||||||
|
|
||||||
print(f"\n[HotReload] 检测到文件变更: {event.src_path}")
|
logger.info(f"检测到文件变更: {event.src_path}")
|
||||||
print("[HotReload] 正在重载插件...")
|
logger.info("正在重载插件...")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 重新扫描并加载插件
|
# 重新扫描并加载插件
|
||||||
load_all_plugins()
|
load_all_plugins()
|
||||||
print("[HotReload] 插件重载完成")
|
logger.success("插件重载完成")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[HotReload] 重载失败: {e}")
|
logger.exception(f"重载失败: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
@logger.catch
|
||||||
async def main():
|
async def main():
|
||||||
"""
|
"""
|
||||||
主函数
|
主函数
|
||||||
@@ -87,9 +90,9 @@ async def main():
|
|||||||
if os.path.exists(plugin_path):
|
if os.path.exists(plugin_path):
|
||||||
observer.schedule(event_handler, plugin_path, recursive=True)
|
observer.schedule(event_handler, plugin_path, recursive=True)
|
||||||
observer.start()
|
observer.start()
|
||||||
print(f"[HotReload] 已启动插件热重载监控: {plugin_path}")
|
logger.info(f"已启动插件热重载监控: {plugin_path}")
|
||||||
else:
|
else:
|
||||||
print(f"[HotReload] 警告: 插件目录不存在 {plugin_path}")
|
logger.warning(f"插件目录不存在 {plugin_path}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
bot = WS()
|
bot = WS()
|
||||||
|
|||||||
@@ -12,3 +12,4 @@ websockets==15.0.1
|
|||||||
yarg==0.1.10
|
yarg==0.1.10
|
||||||
watchdog==6.0.0
|
watchdog==6.0.0
|
||||||
redis==5.0.7
|
redis==5.0.7
|
||||||
|
loguru
|
||||||
|
|||||||
Reference in New Issue
Block a user