CLP Log Viewer
在 VSCode 里直接查看与解压 CLP(Compressed Log Processor) 日志的扩展。
支持两种 y-scope CLP 文件形态:
| 格式 |
文件后缀 |
说明 |
| IR 流 |
.clp.zst |
zstd 压缩的 CLP IR(preamble JSON + payload 记录流) |
| 归档 |
.clp |
YCLP 归档(内含 msgpack 索引、SQLite 元数据、logtype/var 字典、zstd 段) |
解压出来的文本是 Android logcat 风格的一行一条日志:
2026-10-30 23:20:52.184 588 588 W linker : Warning: failed to find generated linker configuration from "/linkerconfig/ld.config.txt"
用法
三条命令(命令面板 Ctrl/Cmd+Shift+P,或资源管理器里右键 .clp / .clp.zst):
- CLP: 解压为 .log 并打开(
clp.openAsLog) —— 写出同名 .log 文件并在编辑器打开。
目标文件已存在时会弹窗确认覆盖。
- CLP: 以虚拟视图打开(懒加载)(
clp.openVirtualViewer) —— 不落盘,用自定义只读编辑器
按视口懒加载行,适合几十万行的大文件。每行默认显示行号(宽度随总行数位数自动调整,
横向滚动时吸附在左侧,且不会被选中复制)。
- CLP: 从当前文件解压(
clp.openFromActiveFile) —— 对当前活动编辑器所在的 CLP 文件执行解压。
此外,直接双击 / 右键 Open With… 选择 CLP Log Viewer 也会打开自定义编辑器;
因为注册为 option 优先级,默认仍会用文本编辑器打开 .clp。
虚拟视图里的搜索
虚拟视图只渲染视口内的行,但搜索是全量的:扩展侧会分批扫描整个行索引,边扫边把命中行号
推给 webview,进度实时显示在搜索栏。
| 操作 |
快捷键 |
| 打开搜索栏 |
Ctrl/Cmd+F |
| 下一个 / 上一个匹配 |
Enter / Shift+Enter |
| 关闭搜索栏(并清除高亮) |
Esc |
搜索栏还支持区分大小写(Aa)与正则(.*)两个开关;输入有 250ms 防抖。
结果按行号顺序返回,Enter 会在命中之间循环跳转,命中的行会滚动到视口中央。
搜索由扩展侧的 log.getLines() 驱动(每批 4000 行,批间让出事件循环),
因此输入时面板不会卡死。命中数不设上限 —— 结果面板可以完整列出全部命中行,
它同样按视口懒加载文本,所以几十万条命中也不会一次性物化字符串。
结果面板(上下分屏)
搜索栏里的 ▾ 按钮会把视图切成上下两块:上方仍是完整日志(虚拟滚动),下方只列出命中的日志行。
- 带行号;点击任意一条会把上方视图滚到该行,并把它设为当前匹配(上方同样标记)。
- 结果面板也按需加载:滚动到哪几条命中,才向扩展索取那几行的文本,不会为了显示几百条结果把整个文件读出来。
- 中间的分隔条可上下拖动,调整结果面板的高度。
Enter / Shift+Enter 在上方与下方同步移动当前匹配。
- 编辑搜索字后结果会重建;清空输入时面板提示“先在上方搜索”。
设置
| 设置项 |
默认值 |
说明 |
clp.maxFileSizeMB |
2048 |
解压后超过该大小则拒绝处理;0 表示不限制 |
clp.warnFileSizeMB |
256 |
写出文本超过该大小前先确认 |
clp.virtualViewer.lineHeight |
18 |
虚拟视图行高(px) |
clp.virtualViewer.overscan |
50 |
视口上下额外预渲染的行数 |
clp.openLogWithOptimizations |
true |
以 log 语言打开并关闭折行、缩略图等 |
开发
npm install
npm run typecheck # tsc --noEmit
npm run compile # 打包到 dist/extension.js
npm run watch # 监听模式
在 VSCode 中按 F5 启动扩展开发宿主(Extension Host)即可调试。
架构
src/core/ —— 零原生依赖的解码层,可独立于 VSCode 复用:
zstd.ts 用纯 JS 的 fzstd,失败时回退到容错流式解压(源文件可能被截断);
sqliteReader.ts 是一个只读 SQLite 解析器(支持 WITHOUT ROWID 的索引 B-tree 与溢出页),
用来读 YCLP 归档里的 metadata.db;
ir.ts / yclp.ts 分别实现 IR 流与归档的解码。两者都做 两遍式处理:
第一遍只建立行索引(时间戳、pid/tid、logtype id、变量区间),不物化字符串;
之后 getLines(start, end) 按需渲染任意区间。
index.ts 通过文件头自动分派格式,导出 decodeClp()。
src/vscode/ —— 命令、写盘、自定义只读编辑器(webview)。
media/ —— 虚拟滚动前端:按滚动位置请求行区间,只渲染可见窗口,行缓存设上限;
搜索时对已加载的行就地高亮,并把命中行滚到视口。上下分屏的结果列表与主视图共用同一份行缓存。
src/vscode/clpEditorProvider.ts 里的 runSearch() 负责全量扫描:以递增的 searchToken
取代旧扫描,每批 4000 行、批间 setImmediate 让出事件循环,命中数不设上限;
readSelectedLines() 负责结果面板的离散行号取样(先把行号合并成连续区间再批量渲染)。
校验
.agents/tmp/verify-core.mjs 会把解码结果与同目录 clp_decompress.py 的输出做整文件比对:
npx esbuild src/core/index.ts --bundle --platform=node --format=esm --outfile=.agents/tmp/core.mjs
cd .agents/tmp && node verify-core.mjs
两个样例文件的输出与 Python 参考实现逐字节一致。
已知限制
- 写出超过 48 MB 的
.log 时,VSCode 无法把文件内容同步给扩展主机
(Files above 50MB cannot be synchronized with extensions),
因此这种文件改由核心命令 vscode.open 交给编辑器直接打开 —— 不再强制切换语言,
但仍会命中 .log → log 语言的内置关联与 [log] 优化默认值。
- 虚拟视图中,单条记录内部的换行会折叠为
␊(虚拟列表按固定行高定位);
需要保留原始折行时请用「解压为 .log 并打开」。
- 解码在主线程同步完成,几十万行的文件会有数秒阻塞(伴随进度通知)。
- 极端泛字的搜索(例如单个字母,可能命中几十万行)会让匹配列表占用可观内存;
结果面板按视口懒加载文本,因此不会因命中多而卡死。
- 只读;不修改源
.clp / .clp.zst 文件。