本机日志取证层:每条结论带行号出处、可重读原文自校验;拿不出因果链就说证据不足。零出网,附 MCP Server / Agent Skill。
概要
拿不出因果链就说证据不足,并精确列出还缺什么才能定论 —— 而且会对这些缺口负责:补上了就把缺口划掉。 大多数日志工具要你**它的结论。这个工具给的是你可以**的东西 —— 每条结论都带原文的**和那段原文的 。 判定只有三档, —— 一份掺了假证据的报告,不该因为大部分 为真就放行。那是取证工具最不能犯的错。 第四行是这份 README 里我最想让你注意的一行:一个** 的项目,它剩下的每个数字才有分量。撤回经过见 docs/BENCHMARK.md 与 docs/FAQ.md Q10。 一个只会报好数字的项目不值得信。下面这些是本文**的地方, 先摆在数字前面,完整版见 §9 它做不到什么。 一个云平台说「我不知道」,在产品上读起来像故障。本工具说「我不知道」, 在方法论上读起来像专业。 绝大多数日志工具(包括带 AI 的)都在优化** —— 尽可能多地给出根因。 但这有个没被解决的问题:,因为值班的人会照着它去查。 按频率排,工具一定会说「根因:连接池耗尽」。 真正的因只出现 10 次,被当成了噪音。
README
log-ai-compressor · 本机日志取证层
我们不把日志交给大模型。我们用确定性算法把日志变成可复核的证据,大模型只读证据。 拿不出因果链就说证据不足,并精确列出还缺什么才能定论 —— 而且会对这些缺口负责:补上了就把缺口划掉。 全部计算在本机完成,日志不出网。
🧾 立场:你不必相信这个工具
大多数日志工具要你相信它的结论。这个工具给的是你可以自己复核的东西 —— 每条结论都带原文的行号区间和那段原文的 sha256。
$ log-ai-compressor run app.log -f json -o report.json
$ log-ai-compressor verify --report report.json
证据:共 8 条引用,匹配 8 条,失配 0 条,源不可读 0 条
事故复盘时,有人把日志里的主机名改了:
$ log-ai-compressor verify --report report.json
证据:共 8 条引用,匹配 7 条,失配 1 条
✗ MISMATCH ca0e981df461 app.log 期望 c33aeb824ce67aaf 实际 4a1689f3780880ae
自校验结论:TAMPERED # 退出码 1
判定只有三档,没有「大部分通过」 —— 一份掺了假证据的报告,不该因为大部分 为真就放行。那是取证工具最不能犯的错。
同一套立场长成了四件具体的事:
| 我们怎么做 | 通常的反面 |
|---|---|
拿不出 Caused by 因果链就只给 LIKELY,并列出还缺什么才能定论,补上了就把那条缺口划掉 |
给一个听起来很像回事的根因 |
| 同一份日志跑两遍,结论指纹逐字节相同(耗时与速率已排除) | 每次结论都不一样,没法归档、没法追责 |
| 证据摘要只认文件原始字节,剥过 ANSI 的文本不算 | 同一行原文,两条出口给两个摘要 |
| 撤回过一个跑不出来的召回率数字(91.4%),并公开查了哪六条路径 | 挂着一个复现不了的漂亮数字 |
第四行是这份 README 里我最想让你注意的一行:一个主动撤回自己招牌数字 的项目,它剩下的每个数字才有分量。撤回经过见
docs/BENCHMARK.md与docs/FAQ.mdQ10。
📌 先读这一节:本文的数字不能证明什么
一个只会报好数字的项目不值得信。下面这些是本文所有实测结论都覆盖不到的地方, 先摆在数字前面,完整版见 §9 它做不到什么。
| 本文不能证明 | 原因 |
|---|---|
| 根因准确率高于云平台 | RCA100 的结论是 62.5% 的根因案例至少需要两种模态、31% 需要三种。本工具只有日志一种,跟它们不是同一场比赛 |
| 在所有日志形态上都优于 Drain3 | 实测覆盖 Loghub 5 个数据集 + Android_v1。fetch_datasets.py 自 v2.8.1 起能下 10 个(新增 Linux / Mac / HPC / OpenSSH / Hadoop),但本次开发环境连不上 Zenodo,新增的 4 个未实测,表里没有它们的数。最差的一个(OpenStack)证据保留率只有 50%,不是全胜 |
| 压缩比能外推到你的日志 | 12289 倍是 OpenStack 全级别摘要口径下的数字。换个数据集、换个 --context,数量级就变 |
| 「召回率 100%」代表真实生产事故 | 只在 1 个含链真实数据集上测过(Android_v1 全量,131 条链 / 8 个根因类)。样本小,结论未必能外推。原先并列的 Hadoop 91.4% 已于 v2.7.0 撤回(数据集来源不可得) |
| 持续监控与告警 | 没有 agent 埋点、没有时序库、没有告警队列 —— 这是有意的取舍,不是没做完 |
一个云平台说「我不知道」,在产品上读起来像故障。本工具说「我不知道」, 在方法论上读起来像专业。但如果你要的是全天候告警,本工具给不了,别选它。
1. 这个工具和别的日志工具有什么不一样
绝大多数日志工具(包括带 AI 的)都在优化命中率 —— 尽可能多地给出根因。 但这有个没被解决的问题:一个自信的错误根因,比没有根因更糟,因为值班的人会照着它去查。
举个实测例子。同一份 20 万行日志里:
| 出现次数 | 真实角色 | |
|---|---|---|
connection pool exhausted |
370 | 症状 |
Connection is not available |
10 | 真正的因 |
按频率排,工具一定会说「根因:连接池耗尽」。这是错的。 真正的因只出现 10 次,被当成了噪音。
本工具的做法:
判定:可能原因 —— 统计推断,非因果证明
不可作为根因输出
最可能的原因:connection pool exhausted —— 但这是统计推断,不是因果证明
补齐下列证据才能定论:
· 缺少确定性因果链 —— 带完整异常堆栈的日志(尤其是 Caused by: 链)
· 存在难以区分的并列候选 —— 能区分二者的额外信号(调用链先后、指标对比)
· 无异常堆栈 —— 未做异常栈裁剪的完整堆栈
这就是本项目与全品类工具的核心差异,完整论证见 docs/POSITIONING.md §3.4。
而这个差异,是可以被第三方复算的 —— 本项目只认领这一个独占叙事
上面讲的是立场。立场不值钱,能被复算的立场才值钱。
这个方向上目前公开的判断是:Resolve.ai 和 Rootly 都发过自有的 LLM 基准文章, 但没有一个带可复现数据集(来源)。
于是本项目做了一件笨事:不宣传自己的压缩比,去打一张公开的榜。
证据保留率(Loghub 2.0 真实数据 + 人工标注,每一行都有 EventId):
| 数据集 | 标注事件 | 本项目(全级别) | Drain3 | LogsLop (AMD) | tail @32k | grep @32k |
|---|---|---|---|---|---|---|
| Apache | 29 | 100.0% | 93.1% | 44.8% | 27.6% | 34.5% |
| HealthApp | 156 | 87.8% | 83.3% | 7.1% | 32.1% | 3.8% |
| OpenStack | 48 | 50.0% | 41.7% | 18.8% | 20.8% | 8.3% |
| Proxifier | 11 | 100.0% | 72.7% | 27.3% | 63.6% | 45.5% |
| Zookeeper | 89 | 92.1% | 76.4% | 23.6% | 79.8% | 9.0% |
对照的三个都是真工具,不是稻草人:
- Drain3 —— 学术标准日志模板抽取(ICWS’17, 800+★),Loghub 官方用来算 PA 的那个
- LogsLop —— AMD 2026-07 的 ROCm 博客开源工具,目前最接近的正面竞品, 同样用 Loghub + Drain3 做对照。它是去重工具,优化的是「别让我看两遍一样的」, 而证据保留要的是「别弄丢根因证据」——两个目标方向相反,所以它把文本相似的 不同事件合并掉了,且几乎不随预算增长(Apache @500tok 37.9% → @32k 仍是 44.8%)
- tail / grep —— 最朴素的两条基线
复现命令、数据来源、口径说明、以及这个数不能证明什么,全在
docs/BENCHMARK.md。
至于本地优先、零出网、MCP Server、Agent Skill —— 这些都是行业里越来越多人在做的事, 我们有,但不是护城河,不当卖点讲。
被质疑时请直接看
docs/FAQ.md—— 那里逐条回答了 「凭什么比 Drain3 强」「自信错误率是不是门槛设高了」「证据引用能不能防结论本身错」 「压缩比是不是挑了口径」「为什么 Drain3 的 PA 99.75% 你不比」等问题, 每一条都附实测依据和「本项目做不到什么」。
每条结论都能被独立复核 —— 这是本项目最硬的一条
上面那三档置信度,如果无法验证,就只是三张标签。所以每条结论都绑定一份 证据引用:文件、行号区间、该段原文的 sha256 摘要。
$ log-ai-compressor run app.log -f json -o report.json
$ log-ai-compressor verify --report report.json
模式:复核已导出报告
证据:共 8 条引用,匹配 8 条,失配 0 条,源不可读 0 条
确定性指纹:37a53c71…139ae06a8a17
摘要不是装饰。它让「结论来自这段原文」从一句断言变成可验证的命题:
# 事故复盘时,有人把日志里的主机名改了
# db-primary:5432 → db-replica:6432
$ log-ai-compressor verify --report report.json
证据:共 8 条引用,匹配 7 条,失配 1 条
✗ MISMATCH ca0e981df461 app.log 期望 c33aeb824ce67aaf 实际 4a1689f3780880ae
自校验结论:TAMPERED # 退出码 1
判定只有三档,没有「大部分通过」 —— 一份掺了假证据的报告不该因为大部分
为真就放行,那是取证工具最不能犯的错。粘贴文本没有可回读的源文件时如实报
NO_SOURCE,不谎称通过。
这个工具不需要你相信它。 你可以自己跑这一步。
确定性:同一份日志跑两遍,结论逐字节相同
报告头部与 API 都带一个 sha256「确定性指纹」(耗时、速率这类每次都不同的 数字已排除)。同一份输入跑两次指纹不一致,就是回归。CI 里跑三次:
$ python scripts/adversarial_eval.py # 见下
$ # CI: 同一份日志连跑三次,指纹必须唯一
这条约束是「结论可写进事后复盘」的前提 —— 不能复现的结论没法归档、没法追责。
对抗性评测:专门设计来误导这个工具的场景
上面所有数字都由本项目自己产出,所以另配了一组专门用来让本工具出错的 场景,按四条硬规则打分。这是本项目唯一能证明自己没在自说自话的方式。
$ python scripts/adversarial_eval.py
● structured_trace_not_causal [4/4] verdict=LIKELY 簇=3 CONFIRMED=0
✓ abstain_correctly verdict=LIKELY, can_conclude=False, CONFIRMED 簇 0 个
✓ causal_language_ok 非 CONFIRMED 簇未使用因果措辞
✓ trace_chain_found 最长链路覆盖 3 个服务(要求 ≥3)
…
────────────────────────────────────────────────────────────
场景数 : 10
评分项 / 通过 : 35/35 (100.0%)
正确弃权率 : 100.0% (5 个应弃权场景)
自信错误率 : 0.0% ← 最该压到 0 的那个数
总判定 : PASS
10 个场景包括:红鲱鱼部署、关键词堆砌的良性日志、共现无因果、单模块无栈、 无时间戳、反向场景(证据其实够了,不该虚报缺口)、结构化日志调用链、 有完整调用链但无 Caused-by、以及普通文本被误吞成 logfmt。
两条口径写死在脚本里,评审前先看这两条:
- 弃权算通过,不算失败。 在确实无法定论的事件上正确弃权是这个工具想要 的行为。只算命中率的评测会偏好猜得最自信的系统 —— 那正是要淘汰的。
- 自信错误率权重最高。 值班的人会照着一个自信的错误根因去排查。
这套评测已经抓出过真 bug:原实现把「时间上紧邻在前的另一个错误簇」当成
因果因,标成 CONFIRMED,一条 INFO request started 因此被判成确定性根因。
已接入 CI(.github/workflows/ci.yml):评分卡不过,CI 变红。
一条命令验证本文所有数字
上面每个数字都可以自己复现,不需要相信作者:
$ python scripts/prove.py
==========================================================================
自证:sample_system.log —— 不必相信作者,自己跑
==========================================================================
PASS 确定性:同输入同结论
3 次运行产生 1 个指纹 (一致)
PASS 证据可复核:每条结论带行号出处且核对通过
8/8 个簇带出处;自校验 VERIFIED,匹配 8/8
PASS 置信档位:无因果链时零确定性断言
日志含 Caused-by:True;判 CONFIRMED 0 个;verdict=LIKELY
PASS 压缩:投喂口径远小于原文,且完整报告体积如实报出
原始 ≈934 tok → summary ≈453 tok (2.1x)→ md ≈9,204 tok
PASS 对抗性评测:该弃权时确实弃权
10 场景 35/35 通过;正确弃权率 100.0%;自信错误率 0.0%
PASS 结构化日志:JSON 认领 / 普通文本不误判
PASS 轻量安装:硬依赖不含 Web/MCP/AI
硬依赖 ['PyYAML>=6.0']
尚无数据的主张(刻意列出,不藏)
? 根因判定的真实数据集覆盖度
? 与云平台根因准确率的对比
注意压缩那一行:在这个 52 行的小日志上,完整 md 报告比原文大 9.9 倍。
脚本不回避这一点 —— 完整报告带样例与上下文,小文件上必然比原文长,这是事实。
压缩比 15x–388x 那组数字来自 Loghub 真实数据集,口径见 §6.1 与
docs/BENCHMARK.md,不要拿本节的小文件数字去宣称压缩比。
prove.py 也是 CI 门禁之一:README 与产品不允许漂移。
实测:5 个真实故障日志上的「压缩比 vs 证据保留率」
在 Loghub-2.0(ISSTA’24 配套数据集, 事件模板为人工标注,不是任何工具的输出)上实测 5 个真实系统日志, 与 Drain3(ICWS’17 论文,821★)同场对比:
| 数据集 | 原始 | 本项目输出 | Drain3 输出 | 本项目保留率 | Drain3 保留率 |
|---|---|---|---|---|---|
| Proxifier | 624K tok | 743 | 317 | 100% | 72.7% |
| Apache | 1.2M tok | 548 | 431 | 100% | 93.1% |
| Zookeeper | 2.6M tok | 470 | 980 | 92.1% | 76.4% |
| HealthApp | 5.1M tok | 499 | 566,802 | 87.8% | 83.3% |
| OpenStack | 15.3M tok | 746 | 73,569 | 50.0% | 41.7% |
证据保留率 5 个数据集全部领先(保留率 = 输出中仍可识别的标注事件类型占比)。
表中「本项目输出」是首轮跑分(旧版代码与旧估算器口径)。输出规模的 当前复测值与统一口径见
docs/BENCHMARK.md「结果二」 (Zookeeper 517 / Apache 564 / Hadoop 708 tokens,结论形状不变)。
两个差异,以及各自的口径:
- 输出规模有上界(口径:
summary,投喂 LLM 用)。与日志行数、事件类型数 无关 —— 当前代码复测:日志从 12 万行涨到 18 万行(原始 tokens 6.4 倍), summary 仍在数百 token(313–788);Drain3 从 317 涨到 566,802(跨度 1789 倍)。 HealthApp 上它压缩比只有 9x、耗时 578 秒 —— 一个 56 万 token 的"压缩结果"等于没压缩。 - 但人读的完整报告(md,CLI 默认格式)不是恒定的:复测 4.8 万–9.7 万 tokens,
压缩 28x–85x,取决于簇数与实例展开。两种口径不能混用 —— 拿 md 去宣称
「几百 token」是夸大。详见
docs/BENCHMARK.md。
这个领先不是算法更强,是补了两个真实日志格式的解析洞。 首轮实测只有
3 胜 2 负;逐条追查后补上 ZooKeeper 的 - LEVEL [模块] - 与
HealthApp 的 YYYYMMDD-HH:MM:SS:mmm|模块|ID|内容 两种格式。在解析正常的日志上
领先,靠的是每簇保留一行原始样例作为可引用证据,不是分得更准。
置信档位实测:零因果链时零确定性断言
「敢不敢说我不知道」这句话需要数据支撑。评测方式:完全独立于本项目,
直接扫原始日志的 Caused by: 链构造地面真相,再与工具输出对账。
| 数据集 | 行数 | 真实因果链 | 工具判 CONFIRMED | 自信错误率 |
|---|---|---|---|---|
| Zookeeper | 74,273 | 0 | 0 | 0% |
| 其余 4 个 | 455,324 | 0 | 0 | 0% |
这个评测第一跑就抓到一个真 bug:原实现把「时间上紧邻在前的另一个错误
簇」当成因果因,然后标成 CONFIRMED —— 一条 INFO request started 因此
被判成确定性根因,正是这个功能声称要消灭的「自信的错误答案」。已修复为
只认条目内 Caused by: 链,并把根因指向链上最内层的异常。
召回率(真出现因果链时能否找到):复现语料(自建故障场景 + 真实 Java 异常/栈帧/日志格式,非生产日志)上已可复跑 —— 5 条因果链,精确率 100%、 召回率 100%、自信错误率 0%,无链对照组 0 CONFIRMED:
$ python scripts/eval_rootcause.py --repro
合计:真实因果链 5,CONFIRMED 5
精确率 100.0% 自信错误率 0.0% 召回率 100.0%
真实数据集:一个,全量可复现
| 数据集 | 含链文件 | 真实链 | CONFIRMED | 精确率 | 自信错误率 | 召回率·报告口径 |
|---|---|---|---|---|---|---|
| Loghub Android_v1(全量 1,555,005 行) | 1 | 131 | 10 | 100.0% | 0.0% | 100.0% |
$ python scripts/eval_rootcause.py
合计:真实因果链 131,CONFIRMED 10
精确率 100.0% 自信错误率 0.0%
召回率·报告口径 100.0% (131/131)
召回率·簇文本 100.0% (131/131)
召回率·宽松 100.0% (131/131)
v2.7.0 撤回了一组数字:Loghub Hadoop 的 91.4%。 那份数据的来源已确认 不可得 —— 两个 Zenodo 记录、
logpai/loghub仓库、本项目data/下全部真实 日志都查过,均无 YARN /application_*/container_*.log,且本地每个 Loghub 日志逐文件实测Caused by出现次数为 0(只有 Android_v1 有链)。一个跑不 出来的数字留着只会在被追问时塌台。撤回经过见docs/BENCHMARK.md与FAQ.mdQ10。
三个召回口径必须说清差别:报告口径(对外只认这个)要求 CONFIRMED 簇
对外报告的根因文本(root_cause_reason + 全部内层因变体)点名该链的根因
类名 —— 答的是「用户照着报告能不能查到这一条」;簇文本只查簇的样例原文
里有没有出现过这个类名(文本里有过 ≠ 工具把它说了出来);宽松只要求行区间
盖住,只证明位置对得上。
v2.7.0 把对外口径换成「报告口径」的理由:旧口径查的是样例原文,而一个簇的样例
恰好是 SocketException 时,后面 29 次同类的链全被算作"被点名",可报告里根因
那一行写的是另一个类 —— 用户照着报告查,报告里没有。更要紧的是,旧口径
检测不出 v2.6.0 那个「一簇只报一因」缺陷(变体不存在,簇文本照样满分)。
指标看不见自己该管的缺陷,比指标偏低更危险。
Android_v1 那一行是被真实 bug 逼出来的:最初实测召回率是 0%(131 条真实
链、CONFIRMED 零个)。根因是 Android logcat 把整个异常压在一行里
(E Tag: com.x.PushException: boom Caused by: java.net.SocketException: abort),
而本工具既没有 logcat 解析模式(无年份 / 单字母级别 / PID+TID),Caused by 的
两条正则也都锚在行首 —— 链整条看不见。现在两种形态都认,
见 docs/BENCHMARK.md 与 CHANGELOG 2.3.0。
样本限制照实说:
- Android_v1 在 v2.4.0 已补跑全量 —— 1,555,005 行 / 131 条链,链密度与原文件 一致(1 / 11,870 行),报告口径召回 100%。原先切片时那条「密度高 6.8 倍、 方向偏保守」的免责声明已删除,因为结论没有随密度回落而翻转。
- Hadoop 那组数字已在 v2.7.0 撤回 —— 数据集来源不可得(两个 Zenodo 记录、
logpai/loghub仓库、本地全部数据都查过),且本地每个 Loghub 日志逐文件实测Caused by出现次数为 0。撤回经过见docs/BENCHMARK.md。 - 只有一个含链的真实数据集 —— 这是本项目最实在的一条短板,且代码解决不了: 131 条链、8 个根因类,样本量不大,「召回 100%」不能外推到别的日志形态。
复现语料与真实数据分开列,不混。
复现:python scripts/benchmark_loghub.py ·
python scripts/eval_rootcause.py ·
python scripts/eval_rootcause.py --repro ·
完整方法学、对照组公平性说明与「本文不能证明什么」见 docs/BENCHMARK.md
2. 它到底做什么
一句话:把一个日志文件,变成一份带行号引用、压缩到几百 token 的证据包。
| 场景 | 痛点 | 解法 |
|---|---|---|
| 日志压缩投喂大模型 | 几十 MB 的日志远超 LLM 上下文窗口,直接粘贴要么截断要么爆 token | 聚类去重 + Top N + 典型样例。实测 10 万行 / 7MB → 150 tokens |
| 快速故障排查 | 上百万行人工翻找,同类错误刷屏干扰判断 | 根因排序 + 异常检测 + 堆栈降噪,直接指出「先查哪里」 |
| 给 AI Agent 当后端 | Agent 查日志只能 grep + 硬塞上下文 |
内置 MCP Server,Claude Code / Codex / mavis 直接调用 |
| 判定「这个问题能不能定论」 | 所有工具都硬给答案 | 证据充分性评估:敢说我不知道,并说清缺什么 |
为什么是「本地」
主流可观测平台(阿里云 SLS、Datadog、Dynatrace…)必须把日志上传到云上, 按 GB 或按主机计费,还要求先装 Agent 埋点。
这不是懒于做云版本,而是有具体理由:2026 年 7 月 Hugging Face 遭攻击事件中, 他们的取证分析一开始尝试调用商业 LLM API,被安全策略拦截了 —— 护栏无法判断提交者是攻击者还是应急响应人员,最终只能自托管模型完成分析, 并因此保住了「凭据从未离开环境」。
涉密/内网日志根本不能上云,这是结构性的需求,不会被技术进步消除。
代价是它不做「持续监控」:它是取证工具,不是 APM 平台。这是有意的取舍。
3. 快速开始
安装
# 本地 Web 界面(推荐:自动开浏览器,端口 8765 起,被占用自动顺延)
pip install "log-ai-compressor[web]"
log-ai-compressor web
只在命令行里压缩日志、不需要界面:
pip install log-ai-compressor(硬依赖只有 PyYAML)
Windows:双击运行
从源码运行时,项目根目录的 start.bat 会自动定位 Python、首次运行自动装依赖、
启动本地服务并打开浏览器。
命令行
log-ai-compressor web # 本地 Web 界面
log-ai-compressor web --port 9000 # 指定端口
log-ai-compressor web --no-browser # 不自动开浏览器
log-ai-compressor run app.log --top 20 -o report.md # 分析并导出 Markdown
# 复核一份报告的结论出处(推荐:报告发出去后日志可能已被改动或轮转清理)
log-ai-compressor verify --report report.json
log-ai-compressor verify --report report.json --json # 机器可读
log-ai-compressor verify app.log # 当场自检
从源码运行(开发者)
git clone https://github.com/hu-chenyu/log-ai-compressor.git
cd log-ai-compressor
pip install -r requirements-dev.txt
python -m pytest # 1,043 个测试
python scripts/adversarial_eval.py # 对抗性评测评分卡(CI 门禁之一)
python scripts/benchmark_loghub.py # 复现上面的实测表(需先下载数据集)
让 AI Agent 直接调用本机日志(MCP / Agent Skills)
pip install "log-ai-compressor[mcp]"
log-ai-compressor mcp # 打印现成的客户端配置
已收录于官方 MCP Registry(registry.modelcontextprotocol.io),MCP 客户端可直接发现并安装:
mcp-name: io.github.hu-chenyu/log-ai-compressor
提供 8 个只读工具:analyze_log_file、analyze_log_text、compare_log_files、
export_report、get_cluster_detail、verify_evidence、list_rules、check_environment。
全部在本机执行,日志不出网。
verify_evidence 是取证层的关键工具:它重读原始日志逐条核对结论出处,
返回 VERIFIED / TAMPERED。Agent 不需要相信这个工具,可以自己复核。
同时提供 SKILL.md(Agent Skills 开放标准),任意支持该标准的
agent 可一条命令安装:
npx skills add /log-forensics
4. 核心特性
分析引擎(全部本地算法,零出网)
- 双输入模式:文件导入(超大文件、编码自动适配 UTF-8/GBK/GB2312/UTF-16/UTF-32,
.gz/.zip透明解压)+ 文本粘贴 - 结构化日志原生解析:JSON Lines 与 logfmt 开箱即用,零配置零新依赖。
2026 年主流框架的默认输出已经是 JSON(Spring Boot 4.x 原生支持 ECS / Logstash /
GELF,内置 OpenTelemetry starter),拿正则去刮纯文本的工具在真实生产日志面前是残废的。
级别、时间、服务、
trace_id/request_id全部按字段认领, 兼容 OTellog.level点号命名空间、ECSseverity_text、真嵌套{"service":{"name":…}} - 调用链重建:结构化日志里存在关联键时,按
trace_id/request_id还原 跨服务链路与首个失败点 —— 不需要装 agent、不需要接拓扑、不需要第二模态。 这让工具能把自己列出的证据缺口真的补上(见下) - 通用文本日志解析:时间戳 / 级别 / 模块 / 内容 / 堆栈(Java、Python、C/C++、gdb 帧全兼容)
- 模糊指纹聚类去重:行号、参数、十六进制 ID、路径差异全部抹平,同类错误只留一份典型样例 + 前后上下文
- 三档相似度:严格 ≥0.95(簇更准)/ 标准 ≥0.85(默认)/ 宽松 ≥0.70(簇更少更狠)
- 证据引用:每条结论绑定
evidence_id+ 文件 + 行号区间 + 原文 sha256 摘要, 可用verify --report重读原文逐条核对;日志被修改或轮转清理会报TAMPERED - 确定性指纹:同一份日志两次分析,结论部分逐字节相同
- 智能辅助分析:
- 证据充分性评估(v2 核心):根因置信三档
CONFIRMED/LIKELY/INSUFFICIENT。只有 Caused-by 因果链直连才算 CONFIRMED;关键词投票、 时间连锁这类统计线索只到 LIKELY。证据不足时不输出「根因」措辞, 改为列出「还缺什么才能定论」—— 见第 1 节 - 缺口自闭环:缺口清单由日志里实际有什么驱动。日志带
trace_id→ 调用链重建成功 → 「缺少调用链关联」这条缺口自动关闭;一条都没有 → 如实申报并说清补什么格式就能补上。只加不减的缺口清单同样是不可信的 - 错误因果关联(Caused-by 链 / 时间连锁 / 根因关键词)自动区分根因与连锁衍生
- 统计异常检测(中位数 + MAD 稳健基线):集中爆发 / 周期发作 / 新型错误 / 罕见异常
- 优先级综合评分(级别 35% + 频次 25% + 根因 20% + 异常 10% + 持续 5% + 新生 5%),按级别分档钳制
- 堆栈降噪:折叠
java.base/site-packages/node_modules等系统库与第三方帧,高亮业务栈帧
- 证据充分性评估(v2 核心):根因置信三档
- 多文件对比:2~3 个文件的新增 / 消失 / 共同错误与数量变化率,适配版本对比与修复验证
- 可插拔解析规则引擎:YAML 声明规则,改配置不改代码即可接入新格式;内置 generic / embedded / jenkins 三套模板
- 脱敏:内置规则(邮箱/手机号/身份证/密钥)+ 自定义正则,导出与复制时自动生效
- 纯流式逐行处理:内存占用只与错误种类数相关,与日志总行数无关
Web 界面(v2)
- 零构建、零 CDN:纯 HTML/CSS/JS,直接改完刷新就生效,完全离线可用
- 三 Tab:文件导入 / 文本粘贴 / 多文件对比
- 内置文件浏览器:服务与日志同机,直接挑本机文件,无需上传(7MB 日志也不走网络)
- 实时 SSE 进度 + 可中途取消
- 错误簇列表(级别/次数/优先级/根因/异常标记)+ 详情面板(典型样例 / 前后上下文 / 降噪堆栈 / 变量分布 / 全部实例)
- 三张图表:错误时间分布(爆发段标红)/ 级别构成 / 模块分布 Top 10
- 实时过滤:支持
and/or/not布尔表达式(例:redis and not debug) - 一键导出:Markdown(投喂大模型)/ JSON / JSON 全文 / 纯文本 / HTML / 精简摘要
- 亮色 / 暗色双主题
AI 解读(可选,不配置也完全可用)
在压缩结果之上再生成一段人话解读:「一句话结论 / 根因链 / 先查哪里 / 证据不足的部分」。
- 三家通吃的 provider 接入:DeepSeek / 阿里百炼 Qwen / 智谱 GLM / Kimi / OpenAI / 本地 Ollama / 任意 OpenAI 兼容端点
- 不配 API Key 也能用:聚类、根因判定、异常检测、导出全是本地算法,一分钱不花。AI 只是额外加一层
- 只上传压缩后的证据摘要,不上传原始日志全文
- 提示词显式约束「只依据给定证据、不得编造」,避免模型编造不存在的根因
log-ai-compressor ai status # 看当前配置
log-ai-compressor ai config --provider deepseek # 选服务商
log-ai-compressor ai config --provider deepseek --key sk-xxx
log-ai-compressor ai test # 测连通性
log-ai-compressor ai explain app.log # 生成解读
log-ai-compressor ai explain app.log --cluster 3 # 只解读某个错误簇
也可以在 Web 界面右上角「⚙ AI 设置」里点选配置。
MCP 接入(给 AI Agent 用)
2026 年可观测平台几乎都出了 MCP Server(阿里云 SLS、Datadog、Grafana…),MCP 把平台从「人去看的目的地」变成「Agent 可调用的数据源」。但那些平台的数据都在别人的机房里;本工具的数据就在你本机。
8 个只读工具(7 个分析 + 1 个取证):analyze_log_file / analyze_log_text /
compare_log_files / export_report / get_cluster_detail / verify_evidence /
list_rules / check_environment
log-ai-compressor mcp --install claude-code # 打印配置片段
log-ai-compressor mcp --install codex
log-ai-compressor mcp --install mavis # JSON 配置
log-ai-compressor mcp # 直接以 stdio 启动
接入后可以直接对 Agent 说:
分析一下
C:\logs\app.log,哪些错误是这次故障的根因?
Agent 会调用本工具做聚类、根因排序,并直接引用压缩后的证据摘要 —— 不需要把几十万行日志塞进上下文。
全部工具只读:没有删除、修改、上传、联网的接口。
5. CLI 使用
# 分析日志并导出 Markdown 报告(默认级别 ERROR,FAIL)
log-ai-compressor run examples/sample_system.log --top 20 -o report.md
# 指定级别、关键字、规则模板
log-ai-compressor run test.log --level ERROR,FAIL,WARN \
--include "timeout,refused" --rule embedded --top 30 -o report.md
# JSON 格式
log-ai-compressor run test.log --format json -o report.json
# 多文件对比(第一个为基准)
log-ai-compressor compare examples/app_v1.log examples/app_v2.log -o diff.md
# 查看内置解析规则
log-ai-compressor rules list
| 子命令 | 用途 |
|---|---|
web |
启动本地 Web 界面(主入口) |
mcp |
启动 MCP Server / 打印客户端配置 |
ai |
AI 解读的 status / config / test / explain |
run |
分析单个日志文件 |
compare |
多文件对比 |
verify |
复核结论出处:核对报告里的每条结论是否仍与原始日志一致 |
rules |
查看解析规则模板 |
6. 实测数据
6.1 真实日志上的压缩与证据保留(Loghub 2.0)
数据来自 Loghub-2.0(ISSTA’24 配套数据集),
其 event template 为人工标注。对照组为 Drain3(ICWS’17 论文,821★)、
tail -N、grep。完整方法学、公平性说明与本文不能证明什么,
见 docs/BENCHMARK.md。
| 数据集 | 原始 | 本项目输出 | Drain3 输出 | 本项目保留率 | Drain3 保留率 |
|---|---|---|---|---|---|
| Proxifier | 624K tok | 743 | 317 | 100% | 72.7% |
| Apache | 1.2M tok | 548 | 431 | 100% | 93.1% |
| Zookeeper | 2.6M tok | 470 | 980 | 92.1% | 76.4% |
| HealthApp | 5.1M tok | 499 | 566,802 | 87.8% | 83.3% |
| OpenStack | 15.3M tok | 746 | 73,569 | 50.0% | 41.7% |
证据保留率 5 个数据集全部领先。 但这个领先是补出来的,不是算法更强 ——
首轮实测是 3 胜 2 负,逐条追查后补了两个解析格式的洞(ZooKeeper 的
- LEVEL [模块] -、HealthApp 的 YYYYMMDD-HH:MM:SS:mmm|模块|ID|内容)。
在解析正常的日志上领先,是因为每簇保留了原始样例行作为可引用证据。详见
docs/BENCHMARK.md。
另一个差异在输出规模(口径:summary):输出有上界、与日志规模无关
—— 当前代码复测 313–788 tokens(上表为首轮旧口径跑分,绝对值已随版本
漂移,形状结论不变);Drain3 从 317 涨到 566,802(跨度 1789 倍)。
HealthApp 上 Drain3 压缩比只有 9x、耗时 578 秒,等于没压缩。
本节没有验证根因判定准确率 —— Loghub 标注的是日志模板,不是故障根因。
6.2 工程指标
| 指标 | 实测值 |
|---|---|
| 生产代码 | 7,575 行(32 个模块) |
| 测试 | 1,043 用例,覆盖率 96%(漏行 156 / 3,883 语句),ruff 全绿 |
| CI | Ubuntu 3.11 / Ubuntu 3.12 / Windows 3.12 三矩阵全绿,六道门禁:ruff / 单测+覆盖率 / 对抗性评分卡 / 确定性指纹 / 自证脚本 / 构建可复现性。其中自证脚本现已断言 9 条主张,含「README 工程指标与架构树必须与仓库一致」 |
| 内存 | 与日志总行数无关,只与错误种类数相关 |
| 硬依赖 | 仅 PyYAML(web / mcp / ai 全部为可选 extra) |
覆盖率不是目标,只是底线(CI 卡 90%)。真正卡回归的是那套对抗性评分卡 —— 覆盖率衡量「代码被执行过」,它衡量「该出错的时候会不会出错」。
6.3 速度
合成日志,仅供吞吐参考(不代表压缩效果,真实效果见 6.1):
~25 万行/秒,10 万行 / 7.03MB 用时 0.40 秒。复现:python scripts/benchmark.py
7. 技术架构
log_ai_compressor/
├── constants.py # 全局常量(时间上限 / 内存有界参数 / 展示上限)
├── service.py # 共享服务层:参数校验 + JSON 序列化 + 导出门面
├── __main__.py # `python -m log_ai_compressor` 入口(退出码即契约)
├── rules/ # 可插拔解析规则引擎(YAML 驱动)
│ ├── engine.py # 规则加载/编译/占位符展开
│ └── presets/ # generic / embedded / jenkins 三套模板
├── core/ # 核心处理层(零 UI / 零 Web 依赖)
│ ├── models.py # 数据模型 + 自适应时间直方图
│ ├── encoding.py # 编码探测(BOM/严格解码验证/截断容忍)
│ ├── structured.py # 结构化日志原生解析(JSON Lines / logfmt)
│ ├── parser.py # 增量解析器(多行聚合:折行/堆栈/Caused-by)
│ ├── causal.py # Caused-by 因果链识别原语(摄入层与分析层共用)
│ ├── filters.py # 级别 + 关键词准入过滤
│ ├── clustering.py # 模糊指纹聚类(三级匹配)
│ ├── analysis.py # 根因判定/异常检测/优先级/堆栈降噪/证据评估
│ ├── traces.py # 调用链重建(trace_id / request_id 跨服务关联)
│ ├── evidence.py # 证据引用 + 自校验 + 确定性指纹(取证层)
│ ├── pipeline.py # 流式管线(进度/取消/上下文捕获)
│ ├── comparator.py # 多文件对比
│ └── redact.py # 脱敏
├── export/reporters.py # 导出层(Markdown/JSON/文本/HTML/摘要)
├── web/ # v2 Web 接入层
│ ├── server.py # FastAPI:REST + SSE + 文件浏览
│ ├── jobs.py # 后台任务 + 进度队列 + SSE 帧
│ └── static/ # 零构建前端(index.html / app.js / style.css)
├── mcp/server.py # MCP 接入层(8 个只读工具)
├── ai/ # 可选 AI 解读层
│ ├── config.py # 服务商配置(三层优先级 + Key 不回显)
│ ├── client.py # OpenAI 兼容 / Ollama 原生协议
│ └── prompts.py # 提示词(显式约束防幻觉)
└── cli.py # 命令行入口
分层解耦:rules → core → export → service → web / mcp / cli 单向依赖。
core零 UI 依赖,可独立测试、被脚本直接复用:from log_ai_compressor.core.pipeline import analyze_filecore/evidence.py不 import 任何上层模块 —— 证据是比模型更底层的概念, 模型层反过来引用它。这让取证层可以被单独审计。service是 core 与接入层之间唯一的转换点,Web 和 MCP 共用同一份序列化逻辑,不会各写一份、各写错一份- 前端零构建:不引入 node/webpack,改完刷新即生效,也不需要 npm
核心算法
-
模糊指纹聚类(两级性能保护)
- 指纹 = 级别 + 掩码消息(数字→N、十六进制→H、UUID→U、路径→P、引号串→S)+ 堆栈前 3 行特征
- 匹配路径:完整指纹精确命中(O(1))→ (级别, 消息模板) 精确命中 → 同级别桶内编辑距离相似度(上限 256 次比较)
- 变体命中后回写精确表,后续重复变体继续 O(1)
-
内存控制
- 逐行流式读取,簇内只存「模板 + 计数 + 一份样例 + 有界直方图」
- 时间直方图桶数上限固定(簇 96 / 全局 512),超限自动 8 倍扩宽桶宽合并旧桶
-
根因判定(三路证据融合):Caused-by 链回溯 + 60 秒窗口内首发且含根因关键词 + 强关键词命中;含 retry/after/downstream 等被动词的簇标记为连锁衍生
8. 开发与测试
pip install -r requirements-dev.txt
ruff check log_ai_compressor tests scripts # 代码规范
python -m pytest # 全量测试
python -m pytest --cov=log_ai_compressor --cov-report=term-missing
测试分层:
| 文件 | 覆盖 | 速度 |
|---|---|---|
test_service.py |
参数归一化、序列化、导出门面 | < 1s |
test_web.py |
REST 契约、SSE 帧格式、参数拦截、文件浏览边界 | < 2s |
test_mcp.py |
工具注册、只读标注、各工具行为与错误路径 | < 1s |
test_ai.py |
配置优先级、提示词、客户端(mock 网络)、可选性 | < 1s |
test_forensics.py |
证据引用确定性、篡改/删除检测、指纹稳定性、CLI/MCP 入口 | < 1s |
test_structured_logs.py |
JSON/logfmt 字段别名、命名空间、误判防护、调用链与越界防线 | < 1s |
test_correctness_fixes.py |
18 个已复现缺陷的回归测试(每条断言写成"修好后必须成立") | < 1s |
test_sdist_contents.py |
交付物完整性:README 引用的每个文件都得在 sdist 里 | < 1s |
test_packaging.py |
可选依赖契约、轻装可跑、降级不炸 | ~2s |
test_*.py(core) |
解析 / 聚类 / 分析 / 导出 / 编码 / 对比 | ~2s |
另有一个不在 pytest 里的门禁:scripts/adversarial_eval.py。它测的不是
“函数返回什么”,而是"这个工具在该闭嘴的时候会不会闭嘴" —— 这类问题写不成
单元测试,只能用场景 + 评分表来表达。
CI(GitHub Actions)三矩阵:ubuntu-3.11(requires-python 下限)、
ubuntu-3.12(最常用版本)、windows-3.12(行尾 / shell / 路径处理与
unix 不同,且 start.bat 是 Windows 一等入口)。六道门禁:ruff →
pytest + 覆盖率 ≥90% → 对抗性评分卡 → 确定性指纹 → 自证脚本 → 构建可复现性。
自证脚本内部已扩到 9 条主张(v2.8.0 起新增「README 工程指标与仓库一致」,
v2.8.1 再加「README 架构树必须列全包内模块」)。
启动脚本的硬约束
start.bat 必须是纯 ASCII + CRLF 行尾,测试会强制校验。原因见 tests/test_launcher.py 顶部注释:cmd.exe 逐字节按控制台代码页解析批处理文件,用裸 LF 或含非 ASCII 字节都会导致解析错位、每行开头被吞,程序永远起不来。所有中文提示都放在 Web 界面里,不放 bat。
9. 它做不到什么
这一节比上面所有功能列表加起来都重要。看不下去可以不看了,但你会高估它。
| 它做不到 | 为什么 | 谁行 |
|---|---|---|
| 比云平台更高的根因准确率 | 多模态根因需要指标 + 链路 + 拓扑。RCA100 数据集的结论是 62.5% 的案例至少需要两种模态,31% 需要三种。本工具只有日志一种 | Datadog / SLS / Dynatrace |
| 持续监控与告警 | 没有 agent 埋点、没有时序库、没有告警队列。这是有意的取舍 | 全部 APM 平台 |
| 调用链追踪 | traces 是从日志里的 trace_id 重建出来的,不是采集的。没有采样就没有精确耗时、没有 span 树 |
Jaeger / Tempo |
| 「召回率」实测 | 只有 1 个含链真实数据集:Android_v1 全量(1,555,005 行 / 131 链 / 8 个根因类,报告口径召回 100%,精确率 100%、自信错误率 0%,可从公开来源完整复现)。原先并列的 Hadoop 91.4% / 5,921 链已于 v2.7.0 撤回 —— 该数据集来源不可得(见 BENCHMARK 撤回经过)。一个真实数据集撑不起「召回率」这个说法,这是本项目最实在的短板 | — |
| 隐私合规认证 | 它不处理合规,只保证「数据不出本机」 | — |
还有一条是方法论上的硬约束,写在代码里而不只是文档里:
调用链只证明顺序,不证明因果。 有完整 trace 但没有
Caused by:时, 工具仍然只给LIKELY、can_conclude=false。CONFIRMED的唯一来源始终是条目内 Caused-by 链。这条线一松, 「拿不出因果链就说不知道」的立场就作废了。 对抗评测里有一个场景专门盯它(structured_trace_not_causal)。
10. 自定义解析规则
新建 my_format.yaml:
name: my_format
description: 自研日志格式
patterns:
- name: main
# {LEVEL} 为引擎占位符,自动展开为标准级别令牌
regex: '^\d+)>\s*\[(?P\w+)\]\s*(?P{LEVEL})\s*(?P.*)$'
stack_indicators:
- '^\s*at\s+[\w$.]+\('
level_hints: # 无级别字段的行按关键词推断(可选)
ERROR: ['\bERROR\b', '\berror\b']
使用:log-ai-compressor run app.log --rule my_format.yaml
11. License
MIT
推奨ツール
別のキーワードを試すか、フィルタを外してください。
インストール
npx skillfish add hu-chenyu/log-ai-compressor