#!/usr/bin/env python # -*- coding: utf-8 -*- """ 简单日志汇总脚本 遍历 logs/ 目录下最近的若干个 dashboard.log 文件,统计 ERROR / WARNING / CRITICAL, 并输出简要汇总信息,供 log-summary Skill 调用。 """ import os import re from pathlib import Path from typing import List, Tuple LOG_ROOT = Path("logs") LOG_FILENAME = "dashboard.log" MAX_FILES = 5 # 最多分析最近 N 个日志文件 LEVEL_PATTERNS = { "ERROR": re.compile(r"\bERROR\b"), "WARNING": re.compile(r"\bWARNING\b"), "CRITICAL": re.compile(r"\bCRITICAL\b"), } def find_log_files() -> List[Path]: if not LOG_ROOT.exists(): return [] candidates: List[Tuple[float, Path]] = [] for root, dirs, files in os.walk(LOG_ROOT): if LOG_FILENAME in files: p = Path(root) / LOG_FILENAME try: mtime = p.stat().st_mtime except OSError: continue candidates.append((mtime, p)) # 按修改时间从新到旧排序 candidates.sort(key=lambda x: x[0], reverse=True) return [p for _, p in candidates[:MAX_FILES]] def summarize_file(path: Path): counts = {level: 0 for level in LEVEL_PATTERNS.keys()} top_messages = {} try: with path.open("r", encoding="utf-8", errors="ignore") as f: for line in f: for level, pattern in LEVEL_PATTERNS.items(): if pattern.search(line): counts[level] += 1 # 取日志消息部分做前缀(粗略) msg = line.strip() # 截断以防过长 msg = msg[:200] top_messages[msg] = top_messages.get(msg, 0) + 1 break except OSError as e: print(f"[!] 读取日志失败 {path}: {e}") return None # 取 Top 5 top_list = sorted(top_messages.items(), key=lambda x: x[1], reverse=True)[:5] return counts, top_list def main(): log_files = find_log_files() if not log_files: print("未找到任何日志文件(logs/*/dashboard.log)。") return print(f"共找到 {len(log_files)} 个最近的日志文件(最多 {MAX_FILES} 个):\n") overall = {level: 0 for level in LEVEL_PATTERNS.keys()} for idx, path in enumerate(log_files, start=1): print(f"[{idx}] 日志文件: {path}") result = summarize_file(path) if result is None: print(" 无法读取该日志文件。\n") continue counts, top_list = result for level, c in counts.items(): overall[level] += c print( " 级别统计: " + ", ".join(f"{lvl}={counts[lvl]}" for lvl in LEVEL_PATTERNS.keys()) ) if top_list: print(" Top 错误/警告消息:") for msg, n in top_list: print(f" [{n}次] {msg}") else: print(" 未发现 ERROR/WARNING/CRITICAL 级别日志。") print() print("总体统计:") print( " " + ", ".join(f"{lvl}={overall[lvl]}" for lvl in LEVEL_PATTERNS.keys()) ) if __name__ == "__main__": main()