From 696cd976189958f8380e51010cd5411730699acf Mon Sep 17 00:00:00 2001 From: Wenjie Zhang Date: Tue, 23 Dec 2025 11:21:34 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=97=A5=E5=BF=97):=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=90=8E=E7=AB=AF=E6=97=A5=E5=BF=97=E7=BA=A7=E5=88=AB=E8=BF=87?= =?UTF-8?q?=E6=BB=A4=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98=E5=8C=96=E5=89=8D?= =?UTF-8?q?=E7=AB=AF=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 在后端添加日志级别过滤参数,支持按级别筛选日志 2. 前端移除本地级别过滤,改为向后端传递过滤参数 3. 优化日志显示样式和自动刷新逻辑 --- server/routers/system_router.py | 34 +++++++++++++++++++++++---- web/src/apis/system_api.js | 6 ++++- web/src/components/DebugComponent.vue | 21 ++++++++++------- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/server/routers/system_router.py b/server/routers/system_router.py index f9aba820..deb6984e 100644 --- a/server/routers/system_router.py +++ b/server/routers/system_router.py @@ -52,18 +52,42 @@ async def update_config_batch(items: dict = Body(...), current_user: User = Depe @system.get("/logs") -async def get_system_logs(current_user: User = Depends(get_admin_user)): - """获取系统日志""" +async def get_system_logs( + levels: str | None = None, + current_user: User = Depends(get_admin_user) +): + """获取系统日志 + + Args: + levels: 可选的日志级别过滤,多个级别用逗号分隔,如 "INFO,ERROR,DEBUG,WARNING" + """ try: from src.utils.logging_config import LOG_FILE + # 解析日志级别过滤条件 + level_filter = None + if levels: + level_filter = set(level.strip().upper() for level in levels.split(',') if level.strip()) + async with aiofiles.open(LOG_FILE) as f: # 读取最后1000行 lines = [] async for line in f: - lines.append(line) - if len(lines) > 1000: - lines.pop(0) + filtered_line = line.rstrip('\n\r') + # 如果指定了日志级别过滤,则按级别过滤 + if level_filter: + # 日志格式: 2025-03-10 08:26:37,269 - INFO - module - message + # 提取日志级别 + parts = filtered_line.split(' - ') + if len(parts) >= 2 and parts[1].strip() in level_filter: + lines.append(filtered_line + '\n') + # 继续读取以保持行数统计准确 + if len(lines) > 1000: + lines.pop(0) + else: + lines.append(filtered_line + '\n') + if len(lines) > 1000: + lines.pop(0) log = "".join(lines) return {"log": log, "message": "success", "log_file": LOG_FILE} diff --git a/web/src/apis/system_api.js b/web/src/apis/system_api.js index 1b4b0001..3a9a8f28 100644 --- a/web/src/apis/system_api.js +++ b/web/src/apis/system_api.js @@ -54,9 +54,13 @@ export const configApi = { /** * 获取系统日志 + * @param {string} levels - 可选的日志级别过滤,多个级别用逗号分隔 * @returns {Promise} - 系统日志 */ - getLogs: async () => apiAdminGet('/api/system/logs') + getLogs: async (levels) => { + const url = levels ? `/api/system/logs?levels=${encodeURIComponent(levels)}` : '/api/system/logs'; + return apiAdminGet(url); + } } // ============================================================================= diff --git a/web/src/components/DebugComponent.vue b/web/src/components/DebugComponent.vue index aa120ab5..8ebed3c5 100644 --- a/web/src/components/DebugComponent.vue +++ b/web/src/components/DebugComponent.vue @@ -196,7 +196,6 @@ const processedLogs = computed(() => { return state.rawLogs .map(parseLogLine) .filter(log => log !== null) - .filter(log => state.selectedLevels.includes(log.level)) .filter(log => { if (!state.searchText) return true; return log.raw.toLowerCase().includes(state.searchText.toLowerCase()); @@ -210,7 +209,9 @@ const fetchLogs = async () => { state.fetching = true; try { error.value = ''; - const logData = await configApi.getLogs(); + // 将选中的日志级别转换为逗号分隔的字符串传递给后端 + const levelsParam = state.selectedLevels.join(','); + const logData = await configApi.getLogs(levelsParam); state.rawLogs = logData.log.split('\n').filter(line => line.trim()); await nextTick(); @@ -248,12 +249,18 @@ const toggleLogLevel = (level) => { const index = currentLevels.indexOf(level); if (index > -1) { + // 如果取消选中后没有选中的级别,默认全选 + if (currentLevels.length === 1) { + return; + } currentLevels.splice(index, 1); } else { currentLevels.push(level); } state.selectedLevels = currentLevels; + // 切换日志级别后重新获取数据 + fetchLogs(); }; // 自动刷新 @@ -470,10 +477,6 @@ const printAgentConfig = async () => {