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 () => {