编程 Rust 日志压缩器:从 10 万行日志里找出真正相关的 200 行

2026-09-08 06:11:12

Rust 日志压缩器:从 10 万行日志里找出真正相关的 200 行

值班时支付失败,拉日志:kubectl logs deployment/payment-svc --since=1h | wc -l 输出 100,000。grep "timeout" 给你 47 条脱离上下文的精确匹配;塞给 LLM 会爆上下文窗口。你需要的是讲清故事的 200 行

logcompress 解决的就是这个:给自然语言查询和日志文件,返回打分、排序、附带 trace 上下文的关联行:

logcompress search -q "why did payment 42 timeout" -f app.log --stats

架构五步(原文主线)

Step 1:Tokenize(快)。 每行用 FNV-1a 哈希成 token,直接操作 u64 哈希、零 String 分配(大写自动折叠小写)。

Step 2:TF-IDF 打分。 候选行与查询做 TF-IDF 余弦相似度。结构化日志有个坑:每行都含 "service":"payment" 时,"payment" 出现在每个文档里、区分度为零。解法是 score gap filter:丢掉得分低于最高分 25% 的行,干净分离信号与噪声。

Step 3:JSON 字段加权。 查询提到 trace-abc123、日志行 "trace_id":"trace-abc123",比同一字符串出现在 message 里信号更强。给结构化字段可配置倍数:error_id 3.0x、trace_id 3.0x、span_id 2.5x、order_id 2.0x。

Step 4:Trace 扩展(核心特性)。 超时事故中只有第 4 行匹配"timeout",前 3 行词汇不同但共享同一 trace_id。打分后从高分命中提取 trace ID,拉出所有共享该 ID 的行——基准里 recall 从 ~70% 提到 100%

Step 5:上下文窗口。 在每个命中周围扩展 ±N 行并合并重叠区间,补上不共享 trace ID 的触发请求与恢复动作。

基准

10 万行合成数据集、50 个隐藏事故(timeout/OOM/deadlock/auth failure/rate limit):Recall 100%(55/55 查询)、10 万行延迟 <250ms、压缩 100k → 100-200 行

实践建议

  • 日志检索别用纯 grep:TF-IDF + 结构字段加权比关键词匹配召回高得多;
  • 按 trace_id 扩展是召回率的关键——跨行词汇不重叠但共享 trace 的行才是事故全貌;
  • score gap filter 解决高频 token 零区分度,别把"每行都出现"的词当信号。

来源:Building a Query-Aware Log Compressor in Rust: From 100k Lines to 200 - DEV Community

复制全文 生成海报 Rust 日志 SRE 开源

推荐文章

程序员茄子在线接单