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