Merge branch 'dev' of https://github.com/MaiM-with-u/MaiBot into dev
This commit is contained in:
2
bot.py
2
bot.py
@@ -10,6 +10,7 @@ from dotenv import load_dotenv
|
||||
|
||||
# 最早期初始化日志系统,确保所有后续模块都使用正确的日志格式
|
||||
from src.common.logger import initialize_logging
|
||||
|
||||
initialize_logging()
|
||||
|
||||
from src.common.logger import get_logger
|
||||
@@ -46,7 +47,6 @@ app = None
|
||||
loop = None
|
||||
|
||||
|
||||
|
||||
async def request_shutdown() -> bool:
|
||||
"""请求关闭程序"""
|
||||
try:
|
||||
|
||||
@@ -8,6 +8,7 @@ import time
|
||||
import toml
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class LogFormatter:
|
||||
"""日志格式化器,同步logger.py的格式"""
|
||||
|
||||
@@ -16,32 +17,32 @@ class LogFormatter:
|
||||
|
||||
# 日志级别颜色
|
||||
self.level_colors = {
|
||||
"debug": "#FFA500", # 橙色
|
||||
"info": "#0000FF", # 蓝色
|
||||
"debug": "#FFA500", # 橙色
|
||||
"info": "#0000FF", # 蓝色
|
||||
"success": "#008000", # 绿色
|
||||
"warning": "#FFFF00", # 黄色
|
||||
"error": "#FF0000", # 红色
|
||||
"critical": "#800080", # 紫色
|
||||
"error": "#FF0000", # 红色
|
||||
"critical": "#800080", # 紫色
|
||||
}
|
||||
|
||||
# 模块颜色映射 - 同步logger.py中的MODULE_COLORS
|
||||
self.module_colors = {
|
||||
"api": "#00FF00", # 亮绿色
|
||||
"emoji": "#00FF00", # 亮绿色
|
||||
"chat": "#0080FF", # 亮蓝色
|
||||
"config": "#FFFF00", # 亮黄色
|
||||
"common": "#FF00FF", # 亮紫色
|
||||
"tools": "#00FFFF", # 亮青色
|
||||
"lpmm": "#00FFFF", # 亮青色
|
||||
"plugin_system": "#FF0080", # 亮红色
|
||||
"experimental": "#FFFFFF", # 亮白色
|
||||
"api": "#00FF00", # 亮绿色
|
||||
"emoji": "#00FF00", # 亮绿色
|
||||
"chat": "#0080FF", # 亮蓝色
|
||||
"config": "#FFFF00", # 亮黄色
|
||||
"common": "#FF00FF", # 亮紫色
|
||||
"tools": "#00FFFF", # 亮青色
|
||||
"lpmm": "#00FFFF", # 亮青色
|
||||
"plugin_system": "#FF0080", # 亮红色
|
||||
"experimental": "#FFFFFF", # 亮白色
|
||||
"person_info": "#008000", # 绿色
|
||||
"individuality": "#000080", # 蓝色
|
||||
"manager": "#800080", # 紫色
|
||||
"llm_models": "#008080", # 青色
|
||||
"plugins": "#800000", # 红色
|
||||
"plugin_api": "#808000", # 黄色
|
||||
"remote": "#8000FF", # 紫蓝色
|
||||
"individuality": "#000080", # 蓝色
|
||||
"manager": "#800080", # 紫色
|
||||
"llm_models": "#008080", # 青色
|
||||
"plugins": "#800000", # 红色
|
||||
"plugin_api": "#808000", # 黄色
|
||||
"remote": "#8000FF", # 紫蓝色
|
||||
}
|
||||
|
||||
# 应用自定义颜色
|
||||
@@ -163,8 +164,8 @@ class LogFormatter:
|
||||
|
||||
try:
|
||||
# 尝试解析ISO格式时间戳
|
||||
if 'T' in timestamp:
|
||||
dt = datetime.fromisoformat(timestamp.replace('Z', '+00:00'))
|
||||
if "T" in timestamp:
|
||||
dt = datetime.fromisoformat(timestamp.replace("Z", "+00:00"))
|
||||
else:
|
||||
# 假设已经是格式化的字符串
|
||||
return timestamp
|
||||
@@ -172,12 +173,12 @@ class LogFormatter:
|
||||
# 根据配置格式化
|
||||
date_style = self.config.get("date_style", "m-d H:i:s")
|
||||
format_map = {
|
||||
'Y': '%Y', # 4位年份
|
||||
'm': '%m', # 月份(01-12)
|
||||
'd': '%d', # 日期(01-31)
|
||||
'H': '%H', # 小时(00-23)
|
||||
'i': '%M', # 分钟(00-59)
|
||||
's': '%S', # 秒数(00-59)
|
||||
"Y": "%Y", # 4位年份
|
||||
"m": "%m", # 月份(01-12)
|
||||
"d": "%d", # 日期(01-31)
|
||||
"H": "%H", # 小时(00-23)
|
||||
"i": "%M", # 分钟(00-59)
|
||||
"s": "%S", # 秒数(00-59)
|
||||
}
|
||||
|
||||
python_format = date_style
|
||||
@@ -188,6 +189,7 @@ class LogFormatter:
|
||||
except Exception:
|
||||
return timestamp
|
||||
|
||||
|
||||
class LogViewer:
|
||||
def __init__(self, root):
|
||||
self.root = root
|
||||
@@ -221,7 +223,7 @@ class LogViewer:
|
||||
|
||||
# 创建模块选择内部框架
|
||||
self.module_inner_frame = ttk.Frame(self.module_canvas)
|
||||
self.module_canvas.create_window((0, 0), window=self.module_inner_frame, anchor='nw')
|
||||
self.module_canvas.create_window((0, 0), window=self.module_inner_frame, anchor="nw")
|
||||
|
||||
# 创建右侧控制区域(级别和搜索)
|
||||
self.right_control_frame = ttk.Frame(self.control_frame)
|
||||
@@ -237,7 +239,7 @@ class LogViewer:
|
||||
ttk.Label(level_frame, text="级别:").pack(side=tk.LEFT, padx=2)
|
||||
self.level_var = tk.StringVar(value="全部")
|
||||
self.level_combo = ttk.Combobox(level_frame, textvariable=self.level_var, width=8)
|
||||
self.level_combo['values'] = ['全部', 'debug', 'info', 'warning', 'error', 'critical']
|
||||
self.level_combo["values"] = ["全部", "debug", "info", "warning", "error", "critical"]
|
||||
self.level_combo.pack(side=tk.LEFT, padx=2)
|
||||
|
||||
# 搜索框
|
||||
@@ -256,9 +258,15 @@ class LogViewer:
|
||||
self.scrollbar = ttk.Scrollbar(self.log_frame)
|
||||
self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
|
||||
|
||||
self.log_text = tk.Text(self.log_frame, wrap=tk.WORD, yscrollcommand=self.scrollbar.set,
|
||||
background='#1e1e1e', foreground='#ffffff',
|
||||
insertbackground='#ffffff', selectbackground='#404040')
|
||||
self.log_text = tk.Text(
|
||||
self.log_frame,
|
||||
wrap=tk.WORD,
|
||||
yscrollcommand=self.scrollbar.set,
|
||||
background="#1e1e1e",
|
||||
foreground="#ffffff",
|
||||
insertbackground="#ffffff",
|
||||
selectbackground="#404040",
|
||||
)
|
||||
self.log_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
|
||||
self.scrollbar.config(command=self.log_text.yview)
|
||||
|
||||
@@ -267,26 +275,26 @@ class LogViewer:
|
||||
|
||||
# 模块名映射
|
||||
self.module_name_mapping = {
|
||||
'api': 'API接口',
|
||||
'async_task_manager': '异步任务管理器',
|
||||
'background_tasks': '后台任务',
|
||||
'base_tool': '基础工具',
|
||||
'chat_stream': '聊天流',
|
||||
'component_registry': '组件注册器',
|
||||
'config': '配置',
|
||||
'database_model': '数据库模型',
|
||||
'emoji': '表情',
|
||||
'heartflow': '心流',
|
||||
'local_storage': '本地存储',
|
||||
'lpmm': 'LPMM',
|
||||
'maibot_statistic': 'MaiBot统计',
|
||||
'main_message': '主消息',
|
||||
'main': '主程序',
|
||||
'memory': '内存',
|
||||
'mood': '情绪',
|
||||
'plugin_manager': '插件管理器',
|
||||
'remote': '远程',
|
||||
'willing': '意愿',
|
||||
"api": "API接口",
|
||||
"async_task_manager": "异步任务管理器",
|
||||
"background_tasks": "后台任务",
|
||||
"base_tool": "基础工具",
|
||||
"chat_stream": "聊天流",
|
||||
"component_registry": "组件注册器",
|
||||
"config": "配置",
|
||||
"database_model": "数据库模型",
|
||||
"emoji": "表情",
|
||||
"heartflow": "心流",
|
||||
"local_storage": "本地存储",
|
||||
"lpmm": "LPMM",
|
||||
"maibot_statistic": "MaiBot统计",
|
||||
"main_message": "主消息",
|
||||
"main": "主程序",
|
||||
"memory": "内存",
|
||||
"mood": "情绪",
|
||||
"plugin_manager": "插件管理器",
|
||||
"remote": "远程",
|
||||
"willing": "意愿",
|
||||
}
|
||||
|
||||
# 加载自定义映射
|
||||
@@ -304,8 +312,8 @@ class LogViewer:
|
||||
self.update_module_list()
|
||||
|
||||
# 绑定事件
|
||||
self.level_combo.bind('<<ComboboxSelected>>', self.filter_logs)
|
||||
self.search_var.trace('w', self.filter_logs)
|
||||
self.level_combo.bind("<<ComboboxSelected>>", self.filter_logs)
|
||||
self.search_var.trace("w", self.filter_logs)
|
||||
|
||||
# 启动日志监控线程
|
||||
self.running = True
|
||||
@@ -322,24 +330,15 @@ class LogViewer:
|
||||
"""加载配置文件"""
|
||||
# 默认配置
|
||||
self.default_config = {
|
||||
"log": {
|
||||
"date_style": "m-d H:i:s",
|
||||
"log_level_style": "lite",
|
||||
"color_text": "full",
|
||||
"log_level": "INFO"
|
||||
},
|
||||
"log": {"date_style": "m-d H:i:s", "log_level_style": "lite", "color_text": "full", "log_level": "INFO"},
|
||||
"viewer": {
|
||||
"theme": "dark",
|
||||
"font_size": 10,
|
||||
"max_lines": 1000,
|
||||
"auto_scroll": True,
|
||||
"show_milliseconds": False,
|
||||
"window": {
|
||||
"width": 1200,
|
||||
"height": 800,
|
||||
"remember_position": True
|
||||
}
|
||||
}
|
||||
"window": {"width": 1200, "height": 800, "remember_position": True},
|
||||
},
|
||||
}
|
||||
|
||||
# 从bot_config.toml加载日志配置
|
||||
@@ -349,10 +348,10 @@ class LogViewer:
|
||||
|
||||
try:
|
||||
if config_path.exists():
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
with open(config_path, "r", encoding="utf-8") as f:
|
||||
bot_config = toml.load(f)
|
||||
if 'log' in bot_config:
|
||||
self.log_config.update(bot_config['log'])
|
||||
if "log" in bot_config:
|
||||
self.log_config.update(bot_config["log"])
|
||||
except Exception as e:
|
||||
print(f"加载bot配置失败: {e}")
|
||||
|
||||
@@ -363,28 +362,28 @@ class LogViewer:
|
||||
|
||||
try:
|
||||
if viewer_config_path.exists():
|
||||
with open(viewer_config_path, 'r', encoding='utf-8') as f:
|
||||
with open(viewer_config_path, "r", encoding="utf-8") as f:
|
||||
viewer_config = toml.load(f)
|
||||
if 'viewer' in viewer_config:
|
||||
self.viewer_config.update(viewer_config['viewer'])
|
||||
if "viewer" in viewer_config:
|
||||
self.viewer_config.update(viewer_config["viewer"])
|
||||
|
||||
# 加载自定义模块颜色
|
||||
if 'module_colors' in viewer_config['viewer']:
|
||||
self.custom_module_colors = viewer_config['viewer']['module_colors']
|
||||
if "module_colors" in viewer_config["viewer"]:
|
||||
self.custom_module_colors = viewer_config["viewer"]["module_colors"]
|
||||
|
||||
# 加载自定义级别颜色
|
||||
if 'level_colors' in viewer_config['viewer']:
|
||||
self.custom_level_colors = viewer_config['viewer']['level_colors']
|
||||
if "level_colors" in viewer_config["viewer"]:
|
||||
self.custom_level_colors = viewer_config["viewer"]["level_colors"]
|
||||
|
||||
if 'log' in viewer_config:
|
||||
self.log_config.update(viewer_config['log'])
|
||||
if "log" in viewer_config:
|
||||
self.log_config.update(viewer_config["log"])
|
||||
except Exception as e:
|
||||
print(f"加载查看器配置失败: {e}")
|
||||
|
||||
# 应用窗口配置
|
||||
window_config = self.viewer_config.get('window', {})
|
||||
window_width = window_config.get('width', 1200)
|
||||
window_height = window_config.get('height', 800)
|
||||
window_config = self.viewer_config.get("window", {})
|
||||
window_width = window_config.get("width", 1200)
|
||||
window_height = window_config.get("height", 800)
|
||||
self.root.geometry(f"{window_width}x{window_height}")
|
||||
|
||||
def save_viewer_config(self):
|
||||
@@ -398,16 +397,13 @@ class LogViewer:
|
||||
if self.custom_level_colors:
|
||||
viewer_config_copy["level_colors"] = self.custom_level_colors
|
||||
|
||||
config_data = {
|
||||
"log": self.log_config,
|
||||
"viewer": viewer_config_copy
|
||||
}
|
||||
config_data = {"log": self.log_config, "viewer": viewer_config_copy}
|
||||
|
||||
config_path = Path("config/log_viewer_config.toml")
|
||||
config_path.parent.mkdir(exist_ok=True)
|
||||
|
||||
try:
|
||||
with open(config_path, 'w', encoding='utf-8') as f:
|
||||
with open(config_path, "w", encoding="utf-8") as f:
|
||||
toml.dump(config_data, f)
|
||||
except Exception as e:
|
||||
print(f"保存查看器配置失败: {e}")
|
||||
@@ -442,42 +438,49 @@ class LogViewer:
|
||||
frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
|
||||
|
||||
# 日期格式
|
||||
ttk.Label(frame, text="日期格式:").pack(anchor='w', pady=2)
|
||||
ttk.Label(frame, text="日期格式:").pack(anchor="w", pady=2)
|
||||
date_style_var = tk.StringVar(value=self.log_config.get("date_style", "m-d H:i:s"))
|
||||
date_entry = ttk.Entry(frame, textvariable=date_style_var, width=30)
|
||||
date_entry.pack(anchor='w', pady=2)
|
||||
ttk.Label(frame, text="格式说明: Y=年份, m=月份, d=日期, H=小时, i=分钟, s=秒",
|
||||
font=('', 8)).pack(anchor='w', pady=2)
|
||||
date_entry.pack(anchor="w", pady=2)
|
||||
ttk.Label(frame, text="格式说明: Y=年份, m=月份, d=日期, H=小时, i=分钟, s=秒", font=("", 8)).pack(
|
||||
anchor="w", pady=2
|
||||
)
|
||||
|
||||
# 日志级别样式
|
||||
ttk.Label(frame, text="日志级别样式:").pack(anchor='w', pady=(10,2))
|
||||
ttk.Label(frame, text="日志级别样式:").pack(anchor="w", pady=(10, 2))
|
||||
level_style_var = tk.StringVar(value=self.log_config.get("log_level_style", "lite"))
|
||||
level_frame = ttk.Frame(frame)
|
||||
level_frame.pack(anchor='w', pady=2)
|
||||
level_frame.pack(anchor="w", pady=2)
|
||||
|
||||
ttk.Radiobutton(level_frame, text="简洁(lite)", variable=level_style_var,
|
||||
value="lite").pack(side='left', padx=(0,10))
|
||||
ttk.Radiobutton(level_frame, text="紧凑(compact)", variable=level_style_var,
|
||||
value="compact").pack(side='left', padx=(0,10))
|
||||
ttk.Radiobutton(level_frame, text="完整(full)", variable=level_style_var,
|
||||
value="full").pack(side='left', padx=(0,10))
|
||||
ttk.Radiobutton(level_frame, text="简洁(lite)", variable=level_style_var, value="lite").pack(
|
||||
side="left", padx=(0, 10)
|
||||
)
|
||||
ttk.Radiobutton(level_frame, text="紧凑(compact)", variable=level_style_var, value="compact").pack(
|
||||
side="left", padx=(0, 10)
|
||||
)
|
||||
ttk.Radiobutton(level_frame, text="完整(full)", variable=level_style_var, value="full").pack(
|
||||
side="left", padx=(0, 10)
|
||||
)
|
||||
|
||||
# 颜色文本设置
|
||||
ttk.Label(frame, text="文本颜色设置:").pack(anchor='w', pady=(10,2))
|
||||
ttk.Label(frame, text="文本颜色设置:").pack(anchor="w", pady=(10, 2))
|
||||
color_text_var = tk.StringVar(value=self.log_config.get("color_text", "full"))
|
||||
color_frame = ttk.Frame(frame)
|
||||
color_frame.pack(anchor='w', pady=2)
|
||||
color_frame.pack(anchor="w", pady=2)
|
||||
|
||||
ttk.Radiobutton(color_frame, text="无颜色(none)", variable=color_text_var,
|
||||
value="none").pack(side='left', padx=(0,10))
|
||||
ttk.Radiobutton(color_frame, text="仅标题(title)", variable=color_text_var,
|
||||
value="title").pack(side='left', padx=(0,10))
|
||||
ttk.Radiobutton(color_frame, text="全部(full)", variable=color_text_var,
|
||||
value="full").pack(side='left', padx=(0,10))
|
||||
ttk.Radiobutton(color_frame, text="无颜色(none)", variable=color_text_var, value="none").pack(
|
||||
side="left", padx=(0, 10)
|
||||
)
|
||||
ttk.Radiobutton(color_frame, text="仅标题(title)", variable=color_text_var, value="title").pack(
|
||||
side="left", padx=(0, 10)
|
||||
)
|
||||
ttk.Radiobutton(color_frame, text="全部(full)", variable=color_text_var, value="full").pack(
|
||||
side="left", padx=(0, 10)
|
||||
)
|
||||
|
||||
# 按钮
|
||||
button_frame = ttk.Frame(frame)
|
||||
button_frame.pack(fill='x', pady=(20,0))
|
||||
button_frame.pack(fill="x", pady=(20, 0))
|
||||
|
||||
def apply_format():
|
||||
self.log_config["date_style"] = date_style_var.get()
|
||||
@@ -496,8 +499,8 @@ class LogViewer:
|
||||
|
||||
format_window.destroy()
|
||||
|
||||
ttk.Button(button_frame, text="应用", command=apply_format).pack(side='right', padx=(5,0))
|
||||
ttk.Button(button_frame, text="取消", command=format_window.destroy).pack(side='right')
|
||||
ttk.Button(button_frame, text="应用", command=apply_format).pack(side="right", padx=(5, 0))
|
||||
ttk.Button(button_frame, text="取消", command=format_window.destroy).pack(side="right")
|
||||
|
||||
def show_viewer_settings(self):
|
||||
"""显示查看器设置窗口"""
|
||||
@@ -509,33 +512,32 @@ class LogViewer:
|
||||
frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
|
||||
|
||||
# 主题设置
|
||||
ttk.Label(frame, text="主题:").pack(anchor='w', pady=2)
|
||||
ttk.Label(frame, text="主题:").pack(anchor="w", pady=2)
|
||||
theme_var = tk.StringVar(value=self.viewer_config.get("theme", "dark"))
|
||||
theme_frame = ttk.Frame(frame)
|
||||
theme_frame.pack(anchor='w', pady=2)
|
||||
ttk.Radiobutton(theme_frame, text="深色", variable=theme_var, value="dark").pack(side='left', padx=(0,10))
|
||||
ttk.Radiobutton(theme_frame, text="浅色", variable=theme_var, value="light").pack(side='left')
|
||||
theme_frame.pack(anchor="w", pady=2)
|
||||
ttk.Radiobutton(theme_frame, text="深色", variable=theme_var, value="dark").pack(side="left", padx=(0, 10))
|
||||
ttk.Radiobutton(theme_frame, text="浅色", variable=theme_var, value="light").pack(side="left")
|
||||
|
||||
# 字体大小
|
||||
ttk.Label(frame, text="字体大小:").pack(anchor='w', pady=(10,2))
|
||||
ttk.Label(frame, text="字体大小:").pack(anchor="w", pady=(10, 2))
|
||||
font_size_var = tk.IntVar(value=self.viewer_config.get("font_size", 10))
|
||||
font_size_spin = ttk.Spinbox(frame, from_=8, to=20, textvariable=font_size_var, width=10)
|
||||
font_size_spin.pack(anchor='w', pady=2)
|
||||
font_size_spin.pack(anchor="w", pady=2)
|
||||
|
||||
# 最大行数
|
||||
ttk.Label(frame, text="最大显示行数:").pack(anchor='w', pady=(10,2))
|
||||
ttk.Label(frame, text="最大显示行数:").pack(anchor="w", pady=(10, 2))
|
||||
max_lines_var = tk.IntVar(value=self.viewer_config.get("max_lines", 1000))
|
||||
max_lines_spin = ttk.Spinbox(frame, from_=100, to=10000, increment=100,
|
||||
textvariable=max_lines_var, width=10)
|
||||
max_lines_spin.pack(anchor='w', pady=2)
|
||||
max_lines_spin = ttk.Spinbox(frame, from_=100, to=10000, increment=100, textvariable=max_lines_var, width=10)
|
||||
max_lines_spin.pack(anchor="w", pady=2)
|
||||
|
||||
# 自动滚动
|
||||
auto_scroll_var = tk.BooleanVar(value=self.viewer_config.get("auto_scroll", True))
|
||||
ttk.Checkbutton(frame, text="自动滚动到底部", variable=auto_scroll_var).pack(anchor='w', pady=(10,2))
|
||||
ttk.Checkbutton(frame, text="自动滚动到底部", variable=auto_scroll_var).pack(anchor="w", pady=(10, 2))
|
||||
|
||||
# 按钮
|
||||
button_frame = ttk.Frame(frame)
|
||||
button_frame.pack(fill='x', pady=(20,0))
|
||||
button_frame.pack(fill="x", pady=(20, 0))
|
||||
|
||||
def apply_viewer_settings():
|
||||
self.viewer_config["theme"] = theme_var.get()
|
||||
@@ -551,8 +553,8 @@ class LogViewer:
|
||||
|
||||
viewer_window.destroy()
|
||||
|
||||
ttk.Button(button_frame, text="应用", command=apply_viewer_settings).pack(side='right', padx=(5,0))
|
||||
ttk.Button(button_frame, text="取消", command=viewer_window.destroy).pack(side='right')
|
||||
ttk.Button(button_frame, text="应用", command=apply_viewer_settings).pack(side="right", padx=(5, 0))
|
||||
ttk.Button(button_frame, text="取消", command=viewer_window.destroy).pack(side="right")
|
||||
|
||||
def apply_theme(self):
|
||||
"""应用主题设置"""
|
||||
@@ -560,19 +562,16 @@ class LogViewer:
|
||||
font_size = self.viewer_config.get("font_size", 10)
|
||||
|
||||
if theme == "dark":
|
||||
bg_color = '#1e1e1e'
|
||||
fg_color = '#ffffff'
|
||||
select_bg = '#404040'
|
||||
bg_color = "#1e1e1e"
|
||||
fg_color = "#ffffff"
|
||||
select_bg = "#404040"
|
||||
else:
|
||||
bg_color = '#ffffff'
|
||||
fg_color = '#000000'
|
||||
select_bg = '#c0c0c0'
|
||||
bg_color = "#ffffff"
|
||||
fg_color = "#000000"
|
||||
select_bg = "#c0c0c0"
|
||||
|
||||
self.log_text.config(
|
||||
background=bg_color,
|
||||
foreground=fg_color,
|
||||
selectbackground=select_bg,
|
||||
font=('Consolas', font_size)
|
||||
background=bg_color, foreground=fg_color, selectbackground=select_bg, font=("Consolas", font_size)
|
||||
)
|
||||
|
||||
# 重新配置标签样式
|
||||
@@ -582,7 +581,7 @@ class LogViewer:
|
||||
"""配置文本标签样式"""
|
||||
# 清除现有标签
|
||||
for tag in self.log_text.tag_names():
|
||||
if tag != 'sel':
|
||||
if tag != "sel":
|
||||
self.log_text.tag_delete(tag)
|
||||
|
||||
# 基础标签
|
||||
@@ -615,12 +614,11 @@ class LogViewer:
|
||||
def export_logs(self):
|
||||
"""导出当前显示的日志"""
|
||||
filename = filedialog.asksaveasfilename(
|
||||
defaultextension=".txt",
|
||||
filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")]
|
||||
defaultextension=".txt", filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")]
|
||||
)
|
||||
if filename:
|
||||
try:
|
||||
with open(filename, 'w', encoding='utf-8') as f:
|
||||
with open(filename, "w", encoding="utf-8") as f:
|
||||
f.write(self.log_text.get(1.0, tk.END))
|
||||
messagebox.showinfo("导出成功", f"日志已导出到: {filename}")
|
||||
except Exception as e:
|
||||
@@ -631,7 +629,7 @@ class LogViewer:
|
||||
mapping_file = Path("config/module_mapping.json")
|
||||
if mapping_file.exists():
|
||||
try:
|
||||
with open(mapping_file, 'r', encoding='utf-8') as f:
|
||||
with open(mapping_file, "r", encoding="utf-8") as f:
|
||||
custom_mapping = json.load(f)
|
||||
self.module_name_mapping.update(custom_mapping)
|
||||
except Exception as e:
|
||||
@@ -642,7 +640,7 @@ class LogViewer:
|
||||
mapping_file = Path("config/module_mapping.json")
|
||||
mapping_file.parent.mkdir(exist_ok=True)
|
||||
try:
|
||||
with open(mapping_file, 'w', encoding='utf-8') as f:
|
||||
with open(mapping_file, "w", encoding="utf-8") as f:
|
||||
json.dump(self.module_name_mapping, f, ensure_ascii=False, indent=2)
|
||||
except Exception as e:
|
||||
print(f"保存模块映射失败: {e}")
|
||||
@@ -668,32 +666,30 @@ class LogViewer:
|
||||
|
||||
# 创建内部框架
|
||||
inner_frame = ttk.Frame(canvas)
|
||||
canvas.create_window((0, 0), window=inner_frame, anchor='nw')
|
||||
canvas.create_window((0, 0), window=inner_frame, anchor="nw")
|
||||
|
||||
# 添加日志级别颜色设置
|
||||
ttk.Label(inner_frame, text="日志级别颜色", font=('', 10, 'bold')).pack(anchor='w', padx=5, pady=5)
|
||||
for level in ['info', 'warning', 'error']:
|
||||
ttk.Label(inner_frame, text="日志级别颜色", font=("", 10, "bold")).pack(anchor="w", padx=5, pady=5)
|
||||
for level in ["info", "warning", "error"]:
|
||||
frame = ttk.Frame(inner_frame)
|
||||
frame.pack(fill=tk.X, padx=5, pady=2)
|
||||
ttk.Label(frame, text=level).pack(side=tk.LEFT)
|
||||
color_btn = ttk.Button(frame, text="选择颜色",
|
||||
command=lambda l=level: self.choose_color(l))
|
||||
color_btn = ttk.Button(frame, text="选择颜色", command=lambda l=level: self.choose_color(l))
|
||||
color_btn.pack(side=tk.RIGHT)
|
||||
# 显示当前颜色
|
||||
color_label = ttk.Label(frame, text="■", foreground=self.formatter.level_colors[level])
|
||||
color_label.pack(side=tk.RIGHT, padx=5)
|
||||
|
||||
# 添加模块颜色设置
|
||||
ttk.Label(inner_frame, text="\n模块颜色", font=('', 10, 'bold')).pack(anchor='w', padx=5, pady=5)
|
||||
ttk.Label(inner_frame, text="\n模块颜色", font=("", 10, "bold")).pack(anchor="w", padx=5, pady=5)
|
||||
for module in sorted(self.modules):
|
||||
frame = ttk.Frame(inner_frame)
|
||||
frame.pack(fill=tk.X, padx=5, pady=2)
|
||||
ttk.Label(frame, text=module).pack(side=tk.LEFT)
|
||||
color_btn = ttk.Button(frame, text="选择颜色",
|
||||
command=lambda m=module: self.choose_module_color(m))
|
||||
color_btn = ttk.Button(frame, text="选择颜色", command=lambda m=module: self.choose_module_color(m))
|
||||
color_btn.pack(side=tk.RIGHT)
|
||||
# 显示当前颜色
|
||||
color = self.formatter.module_colors.get(module, 'black')
|
||||
color = self.formatter.module_colors.get(module, "black")
|
||||
color_label = ttk.Label(frame, text="■", foreground=color)
|
||||
color_label.pack(side=tk.RIGHT, padx=5)
|
||||
|
||||
@@ -716,7 +712,7 @@ class LogViewer:
|
||||
|
||||
def choose_module_color(self, module):
|
||||
"""选择模块颜色"""
|
||||
color = colorchooser.askcolor(color=self.formatter.module_colors.get(module, 'black'))[1]
|
||||
color = colorchooser.askcolor(color=self.formatter.module_colors.get(module, "black"))[1]
|
||||
if color:
|
||||
self.formatter.module_colors[module] = color
|
||||
self.custom_module_colors[module] = color # 保存到自定义颜色
|
||||
@@ -728,12 +724,12 @@ class LogViewer:
|
||||
"""更新模块列表"""
|
||||
log_file = Path("logs/app.log.jsonl")
|
||||
if log_file.exists():
|
||||
with open(log_file, 'r', encoding='utf-8') as f:
|
||||
with open(log_file, "r", encoding="utf-8") as f:
|
||||
for line in f:
|
||||
try:
|
||||
log_entry = json.loads(line)
|
||||
if 'logger_name' in log_entry:
|
||||
self.modules.add(log_entry['logger_name'])
|
||||
if "logger_name" in log_entry:
|
||||
self.modules.add(log_entry["logger_name"])
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
|
||||
@@ -755,18 +751,19 @@ class LogViewer:
|
||||
|
||||
# 添加"全部"选项
|
||||
all_frame = ttk.Frame(self.module_inner_frame)
|
||||
all_frame.grid(row=current_row, column=current_col, padx=3, pady=2, sticky='ew')
|
||||
all_frame.grid(row=current_row, column=current_col, padx=3, pady=2, sticky="ew")
|
||||
|
||||
all_var = tk.BooleanVar(value='全部' in self.selected_modules)
|
||||
all_check = ttk.Checkbutton(all_frame, text="全部", variable=all_var,
|
||||
command=lambda: self.toggle_module('全部', all_var))
|
||||
all_var = tk.BooleanVar(value="全部" in self.selected_modules)
|
||||
all_check = ttk.Checkbutton(
|
||||
all_frame, text="全部", variable=all_var, command=lambda: self.toggle_module("全部", all_var)
|
||||
)
|
||||
all_check.pack(side=tk.LEFT)
|
||||
|
||||
# 使用颜色标签替代按钮
|
||||
all_color = self.formatter.module_colors.get('全部', 'black')
|
||||
all_color = self.formatter.module_colors.get("全部", "black")
|
||||
all_color_label = ttk.Label(all_frame, text="■", foreground=all_color, width=2, cursor="hand2")
|
||||
all_color_label.pack(side=tk.LEFT, padx=2)
|
||||
all_color_label.bind('<Button-1>', lambda e: self.choose_module_color('全部'))
|
||||
all_color_label.bind("<Button-1>", lambda e: self.choose_module_color("全部"))
|
||||
|
||||
current_col += 1
|
||||
|
||||
@@ -777,7 +774,7 @@ class LogViewer:
|
||||
current_col = 0
|
||||
|
||||
frame = ttk.Frame(self.module_inner_frame)
|
||||
frame.grid(row=current_row, column=current_col, padx=3, pady=2, sticky='ew')
|
||||
frame.grid(row=current_row, column=current_col, padx=3, pady=2, sticky="ew")
|
||||
|
||||
var = tk.BooleanVar(value=module in self.selected_modules)
|
||||
|
||||
@@ -786,8 +783,9 @@ class LogViewer:
|
||||
if len(display_name) > 12:
|
||||
display_name = display_name[:10] + "..."
|
||||
|
||||
check = ttk.Checkbutton(frame, text=display_name, variable=var,
|
||||
command=lambda m=module, v=var: self.toggle_module(m, v))
|
||||
check = ttk.Checkbutton(
|
||||
frame, text=display_name, variable=var, command=lambda m=module, v=var: self.toggle_module(m, v)
|
||||
)
|
||||
check.pack(side=tk.LEFT)
|
||||
|
||||
# 添加工具提示显示完整名称和英文名
|
||||
@@ -797,10 +795,10 @@ class LogViewer:
|
||||
self.create_tooltip(check, full_tooltip)
|
||||
|
||||
# 使用颜色标签替代按钮
|
||||
color = self.formatter.module_colors.get(module, 'black')
|
||||
color = self.formatter.module_colors.get(module, "black")
|
||||
color_label = ttk.Label(frame, text="■", foreground=color, width=2, cursor="hand2")
|
||||
color_label.pack(side=tk.LEFT, padx=2)
|
||||
color_label.bind('<Button-1>', lambda e, m=module: self.choose_module_color(m))
|
||||
color_label.bind("<Button-1>", lambda e, m=module: self.choose_module_color(m))
|
||||
|
||||
current_col += 1
|
||||
|
||||
@@ -809,42 +807,44 @@ class LogViewer:
|
||||
self.module_canvas.config(scrollregion=self.module_canvas.bbox("all"))
|
||||
|
||||
# 添加垂直滚动条
|
||||
if not hasattr(self, 'module_scrollbar'):
|
||||
self.module_scrollbar = ttk.Scrollbar(self.module_frame, orient=tk.VERTICAL,
|
||||
command=self.module_canvas.yview)
|
||||
if not hasattr(self, "module_scrollbar"):
|
||||
self.module_scrollbar = ttk.Scrollbar(
|
||||
self.module_frame, orient=tk.VERTICAL, command=self.module_canvas.yview
|
||||
)
|
||||
self.module_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
|
||||
self.module_canvas.config(yscrollcommand=self.module_scrollbar.set)
|
||||
|
||||
def create_tooltip(self, widget, text):
|
||||
"""为控件创建工具提示"""
|
||||
|
||||
def on_enter(event):
|
||||
tooltip = tk.Toplevel()
|
||||
tooltip.wm_overrideredirect(True)
|
||||
tooltip.wm_geometry(f"+{event.x_root+10}+{event.y_root+10}")
|
||||
tooltip.wm_geometry(f"+{event.x_root + 10}+{event.y_root + 10}")
|
||||
label = ttk.Label(tooltip, text=text, background="lightyellow", relief="solid", borderwidth=1)
|
||||
label.pack()
|
||||
widget.tooltip = tooltip
|
||||
|
||||
def on_leave(event):
|
||||
if hasattr(widget, 'tooltip'):
|
||||
if hasattr(widget, "tooltip"):
|
||||
widget.tooltip.destroy()
|
||||
del widget.tooltip
|
||||
|
||||
widget.bind('<Enter>', on_enter)
|
||||
widget.bind('<Leave>', on_leave)
|
||||
widget.bind("<Enter>", on_enter)
|
||||
widget.bind("<Leave>", on_leave)
|
||||
|
||||
def toggle_module(self, module, var):
|
||||
"""切换模块选择状态"""
|
||||
if module == '全部':
|
||||
if module == "全部":
|
||||
if var.get():
|
||||
self.selected_modules = {'全部'}
|
||||
self.selected_modules = {"全部"}
|
||||
else:
|
||||
self.selected_modules.clear()
|
||||
else:
|
||||
if var.get():
|
||||
self.selected_modules.add(module)
|
||||
if '全部' in self.selected_modules:
|
||||
self.selected_modules.remove('全部')
|
||||
if "全部" in self.selected_modules:
|
||||
self.selected_modules.remove("全部")
|
||||
else:
|
||||
self.selected_modules.discard(module)
|
||||
|
||||
@@ -858,7 +858,7 @@ class LogViewer:
|
||||
while self.running:
|
||||
if log_file.exists():
|
||||
try:
|
||||
with open(log_file, 'r', encoding='utf-8') as f:
|
||||
with open(log_file, "r", encoding="utf-8") as f:
|
||||
f.seek(last_position)
|
||||
new_lines = f.readlines()
|
||||
last_position = f.tell()
|
||||
@@ -870,8 +870,8 @@ class LogViewer:
|
||||
self.log_cache.append(log_entry)
|
||||
|
||||
# 检查是否有新模块
|
||||
if 'logger_name' in log_entry:
|
||||
logger_name = log_entry['logger_name']
|
||||
if "logger_name" in log_entry:
|
||||
logger_name = log_entry["logger_name"]
|
||||
if logger_name not in self.modules:
|
||||
self.modules.add(logger_name)
|
||||
# 在主线程中更新模块列表UI
|
||||
@@ -909,7 +909,7 @@ class LogViewer:
|
||||
"""添加格式化的日志行到文本框"""
|
||||
# 控制最大行数
|
||||
max_lines = self.viewer_config.get("max_lines", 1000)
|
||||
current_lines = int(self.log_text.index('end-1c').split('.')[0])
|
||||
current_lines = int(self.log_text.index("end-1c").split(".")[0])
|
||||
|
||||
if current_lines > max_lines:
|
||||
# 删除前面的行
|
||||
@@ -951,20 +951,20 @@ class LogViewer:
|
||||
"""检查日志是否应该显示"""
|
||||
# 检查模块过滤
|
||||
if self.selected_modules:
|
||||
if '全部' not in self.selected_modules:
|
||||
if log_entry.get('logger_name') not in self.selected_modules:
|
||||
if "全部" not in self.selected_modules:
|
||||
if log_entry.get("logger_name") not in self.selected_modules:
|
||||
return False
|
||||
|
||||
# 检查级别过滤
|
||||
if self.level_var.get() != '全部':
|
||||
if log_entry.get('level') != self.level_var.get():
|
||||
if self.level_var.get() != "全部":
|
||||
if log_entry.get("level") != self.level_var.get():
|
||||
return False
|
||||
|
||||
# 检查搜索过滤
|
||||
search_text = self.search_var.get().lower()
|
||||
if search_text:
|
||||
event = str(log_entry.get('event', '')).lower()
|
||||
logger_name = str(log_entry.get('logger_name', '')).lower()
|
||||
event = str(log_entry.get("event", "")).lower()
|
||||
logger_name = str(log_entry.get("logger_name", "")).lower()
|
||||
if search_text not in event and search_text not in logger_name:
|
||||
return False
|
||||
|
||||
@@ -1013,11 +1013,11 @@ class LogViewer:
|
||||
|
||||
# 创建内部框架
|
||||
inner_frame = ttk.Frame(canvas)
|
||||
canvas.create_window((0, 0), window=inner_frame, anchor='nw')
|
||||
canvas.create_window((0, 0), window=inner_frame, anchor="nw")
|
||||
|
||||
# 添加标题
|
||||
ttk.Label(inner_frame, text="模块映射编辑", font=('', 12, 'bold')).pack(anchor='w', padx=5, pady=5)
|
||||
ttk.Label(inner_frame, text="英文名 -> 中文名", font=('', 10)).pack(anchor='w', padx=5, pady=2)
|
||||
ttk.Label(inner_frame, text="模块映射编辑", font=("", 12, "bold")).pack(anchor="w", padx=5, pady=5)
|
||||
ttk.Label(inner_frame, text="英文名 -> 中文名", font=("", 10)).pack(anchor="w", padx=5, pady=2)
|
||||
|
||||
# 映射编辑字典
|
||||
mapping_vars = {}
|
||||
@@ -1061,10 +1061,12 @@ class LogViewer:
|
||||
ttk.Button(button_frame, text="保存", command=save_mappings).pack(side=tk.RIGHT, padx=5)
|
||||
ttk.Button(button_frame, text="取消", command=mapping_window.destroy).pack(side=tk.RIGHT, padx=5)
|
||||
|
||||
|
||||
def main():
|
||||
root = tk.Tk()
|
||||
app = LogViewer(root)
|
||||
LogViewer(root)
|
||||
root.mainloop()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -494,7 +494,6 @@ class HeartFChatting:
|
||||
"observed_messages": plan_result.get("observed_messages", ""),
|
||||
}
|
||||
|
||||
|
||||
with Timer("执行动作", cycle_timers):
|
||||
action_type, action_data, reasoning = (
|
||||
plan_result.get("action_result", {}).get("action_type", "error"),
|
||||
@@ -502,7 +501,6 @@ class HeartFChatting:
|
||||
plan_result.get("action_result", {}).get("reasoning", "未提供理由"),
|
||||
)
|
||||
|
||||
|
||||
if action_type == "reply":
|
||||
action_str = "回复"
|
||||
elif action_type == "no_reply":
|
||||
|
||||
@@ -5,13 +5,13 @@ from typing import Callable, Optional
|
||||
import json
|
||||
|
||||
import structlog
|
||||
from structlog.dev import ConsoleRenderer
|
||||
import toml
|
||||
|
||||
# 创建logs目录
|
||||
LOG_DIR = Path("logs")
|
||||
LOG_DIR.mkdir(exist_ok=True)
|
||||
|
||||
|
||||
# 读取日志配置
|
||||
def load_log_config():
|
||||
"""从配置文件加载日志设置"""
|
||||
@@ -22,32 +22,34 @@ def load_log_config():
|
||||
"color_text": "title",
|
||||
"log_level": "INFO",
|
||||
"suppress_libraries": [],
|
||||
"library_log_levels": {}
|
||||
"library_log_levels": {},
|
||||
}
|
||||
|
||||
try:
|
||||
if config_path.exists():
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
with open(config_path, "r", encoding="utf-8") as f:
|
||||
config = toml.load(f)
|
||||
return config.get('log', default_config)
|
||||
return config.get("log", default_config)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
LOG_CONFIG = load_log_config()
|
||||
|
||||
|
||||
def get_timestamp_format():
|
||||
"""将配置中的日期格式转换为Python格式"""
|
||||
date_style = LOG_CONFIG.get("date_style", "Y-m-d H:i:s")
|
||||
# 转换PHP风格的日期格式到Python格式
|
||||
format_map = {
|
||||
'Y': '%Y', # 4位年份
|
||||
'm': '%m', # 月份(01-12)
|
||||
'd': '%d', # 日期(01-31)
|
||||
'H': '%H', # 小时(00-23)
|
||||
'i': '%M', # 分钟(00-59)
|
||||
's': '%S', # 秒数(00-59)
|
||||
"Y": "%Y", # 4位年份
|
||||
"m": "%m", # 月份(01-12)
|
||||
"d": "%d", # 日期(01-31)
|
||||
"H": "%H", # 小时(00-23)
|
||||
"i": "%M", # 分钟(00-59)
|
||||
"s": "%S", # 秒数(00-59)
|
||||
}
|
||||
|
||||
python_format = date_style
|
||||
@@ -56,6 +58,7 @@ def get_timestamp_format():
|
||||
|
||||
return python_format
|
||||
|
||||
|
||||
def configure_third_party_loggers():
|
||||
"""配置第三方库的日志级别"""
|
||||
# 设置全局日志级别
|
||||
@@ -128,24 +131,25 @@ def reconfigure_existing_loggers():
|
||||
handler.setFormatter(console_formatter)
|
||||
logger_obj.addHandler(handler)
|
||||
|
||||
|
||||
# 定义模块颜色映射
|
||||
MODULE_COLORS = {
|
||||
"api": "\033[92m", # 亮绿色
|
||||
"emoji": "\033[92m", # 亮绿色
|
||||
"chat": "\033[94m", # 亮蓝色
|
||||
"config": "\033[93m", # 亮黄色
|
||||
"common": "\033[95m", # 亮紫色
|
||||
"tools": "\033[96m", # 亮青色
|
||||
"api": "\033[92m", # 亮绿色
|
||||
"emoji": "\033[92m", # 亮绿色
|
||||
"chat": "\033[94m", # 亮蓝色
|
||||
"config": "\033[93m", # 亮黄色
|
||||
"common": "\033[95m", # 亮紫色
|
||||
"tools": "\033[96m", # 亮青色
|
||||
"lpmm": "\033[96m",
|
||||
"plugin_system": "\033[91m", # 亮红色
|
||||
"experimental": "\033[97m", # 亮白色
|
||||
"person_info": "\033[32m", # 绿色
|
||||
"individuality": "\033[34m", # 蓝色
|
||||
"manager": "\033[35m", # 紫色
|
||||
"plugin_system": "\033[91m", # 亮红色
|
||||
"experimental": "\033[97m", # 亮白色
|
||||
"person_info": "\033[32m", # 绿色
|
||||
"individuality": "\033[34m", # 蓝色
|
||||
"manager": "\033[35m", # 紫色
|
||||
"llm_models": "\033[36m", # 青色
|
||||
"plugins": "\033[31m", # 红色
|
||||
"plugins": "\033[31m", # 红色
|
||||
"plugin_api": "\033[33m", # 黄色
|
||||
"remote": "\033[38;5;93m", # 紫蓝色
|
||||
"remote": "\033[38;5;93m", # 紫蓝色
|
||||
}
|
||||
|
||||
RESET_COLOR = "\033[0m"
|
||||
@@ -160,12 +164,12 @@ class ModuleColoredConsoleRenderer:
|
||||
|
||||
# 日志级别颜色
|
||||
self._level_colors = {
|
||||
"debug": "\033[38;5;208m", # 橙色
|
||||
"info": "\033[34m", # 蓝色
|
||||
"success": "\033[32m", # 绿色
|
||||
"warning": "\033[33m", # 黄色
|
||||
"error": "\033[31m", # 红色
|
||||
"critical": "\033[35m", # 紫色
|
||||
"debug": "\033[38;5;208m", # 橙色
|
||||
"info": "\033[34m", # 蓝色
|
||||
"success": "\033[32m", # 绿色
|
||||
"warning": "\033[33m", # 黄色
|
||||
"error": "\033[31m", # 红色
|
||||
"critical": "\033[35m", # 紫色
|
||||
}
|
||||
|
||||
# 根据配置决定是否启用颜色
|
||||
@@ -288,6 +292,7 @@ logging.basicConfig(
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def configure_structlog():
|
||||
"""配置structlog"""
|
||||
structlog.configure(
|
||||
@@ -306,6 +311,7 @@ def configure_structlog():
|
||||
cache_logger_on_first_use=True,
|
||||
)
|
||||
|
||||
|
||||
# 配置structlog
|
||||
configure_structlog()
|
||||
|
||||
@@ -343,6 +349,7 @@ for handler in root_logger.handlers:
|
||||
else:
|
||||
handler.setFormatter(console_formatter)
|
||||
|
||||
|
||||
# 立即配置日志系统,确保最早期的日志也使用正确格式
|
||||
def _immediate_setup():
|
||||
"""立即设置日志系统,在模块导入时就生效"""
|
||||
@@ -355,12 +362,14 @@ def _immediate_setup():
|
||||
root_logger.removeHandler(handler)
|
||||
|
||||
# 重新添加配置好的handler
|
||||
root_logger.addHandler(logging.handlers.RotatingFileHandler(
|
||||
LOG_DIR / "app.log.jsonl",
|
||||
maxBytes=10 * 1024 * 1024,
|
||||
backupCount=5,
|
||||
encoding="utf-8",
|
||||
))
|
||||
root_logger.addHandler(
|
||||
logging.handlers.RotatingFileHandler(
|
||||
LOG_DIR / "app.log.jsonl",
|
||||
maxBytes=10 * 1024 * 1024,
|
||||
backupCount=5,
|
||||
encoding="utf-8",
|
||||
)
|
||||
)
|
||||
root_logger.addHandler(logging.StreamHandler())
|
||||
|
||||
# 设置格式化器
|
||||
@@ -376,6 +385,7 @@ def _immediate_setup():
|
||||
# 重新配置所有已存在的logger
|
||||
reconfigure_existing_loggers()
|
||||
|
||||
|
||||
# 立即执行配置
|
||||
_immediate_setup()
|
||||
|
||||
@@ -441,17 +451,19 @@ def reload_log_config():
|
||||
for handler in root_logger.handlers:
|
||||
if isinstance(handler, logging.StreamHandler) and not isinstance(handler, logging.handlers.RotatingFileHandler):
|
||||
# 这是控制台处理器,更新其格式化器
|
||||
handler.setFormatter(structlog.stdlib.ProcessorFormatter(
|
||||
processor=ModuleColoredConsoleRenderer(colors=True),
|
||||
foreign_pre_chain=[
|
||||
structlog.stdlib.add_logger_name,
|
||||
structlog.stdlib.add_log_level,
|
||||
structlog.stdlib.PositionalArgumentsFormatter(),
|
||||
structlog.processors.TimeStamper(fmt=get_timestamp_format(), utc=False),
|
||||
structlog.processors.StackInfoRenderer(),
|
||||
structlog.processors.format_exc_info,
|
||||
],
|
||||
))
|
||||
handler.setFormatter(
|
||||
structlog.stdlib.ProcessorFormatter(
|
||||
processor=ModuleColoredConsoleRenderer(colors=True),
|
||||
foreign_pre_chain=[
|
||||
structlog.stdlib.add_logger_name,
|
||||
structlog.stdlib.add_log_level,
|
||||
structlog.stdlib.PositionalArgumentsFormatter(),
|
||||
structlog.processors.TimeStamper(fmt=get_timestamp_format(), utc=False),
|
||||
structlog.processors.StackInfoRenderer(),
|
||||
structlog.processors.format_exc_info,
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
# 重新配置第三方库日志
|
||||
configure_third_party_loggers()
|
||||
@@ -475,12 +487,14 @@ def force_reset_all_loggers():
|
||||
root_logger.handlers.clear()
|
||||
|
||||
# 重新添加我们的handler
|
||||
root_logger.addHandler(logging.handlers.RotatingFileHandler(
|
||||
LOG_DIR / "app.log.jsonl",
|
||||
maxBytes=10 * 1024 * 1024,
|
||||
backupCount=5,
|
||||
encoding="utf-8",
|
||||
))
|
||||
root_logger.addHandler(
|
||||
logging.handlers.RotatingFileHandler(
|
||||
LOG_DIR / "app.log.jsonl",
|
||||
maxBytes=10 * 1024 * 1024,
|
||||
backupCount=5,
|
||||
encoding="utf-8",
|
||||
)
|
||||
)
|
||||
root_logger.addHandler(logging.StreamHandler())
|
||||
|
||||
# 设置格式化器
|
||||
@@ -533,10 +547,10 @@ def force_initialize_logging():
|
||||
|
||||
def show_module_colors():
|
||||
"""显示所有模块的颜色效果"""
|
||||
logger = get_logger("demo")
|
||||
get_logger("demo")
|
||||
print("\n=== 模块颜色展示 ===")
|
||||
|
||||
for module_name, color_code in MODULE_COLORS.items():
|
||||
for module_name, _color_code in MODULE_COLORS.items():
|
||||
# 临时创建一个该模块的logger来展示颜色
|
||||
demo_logger = structlog.get_logger(module_name).bind(logger_name=module_name)
|
||||
demo_logger.info(f"这是 {module_name} 模块的颜色效果")
|
||||
|
||||
Reference in New Issue
Block a user