Skip to content

feat(sdk): 三种 SDK 接入 litheLogging 1 结构化诊断 - #17

Merged
xiaoyumuxi merged 4 commits into
mainfrom
codex/plugin-logging-v2
Nov 4, 2026
Merged

xiaoyumuxi merged 4 commits into
mainfrom
codex/plugin-logging-v2

Conversation

@xiaoyumuxi

@xiaoyumuxi xiaoyumuxi commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

概要

三种官方插件后端 SDK(Node、Java、Rust)接入结构化日志 v2:SDK 在 initialize 中协商 litheLogging 1,删除自由文本日志 API,改为通过 lithe/log 通知上报四种受控诊断事实,由 Core 统一校验、脱敏并写入 plugins/<id>/host。

依赖宿主 PR https://github.com/1lck/Lithe-IDEA/pull/1699(Core 侧协议、目录事件和共享契约)。本 PR 不直接修改 contract/v1:按仓库规则,宿主 PR 合并后再运行 node scripts/contract.mjs sync --revision <合并后的 preview commit> 同步契约副本和 contract.lock.json。

协议与公共 API(三种 SDK 一致)

  • initialize 时检查 Core 提供的 experimental.litheLogging.versions 是否包含 1,包含则回答 litheLogging: {"version": 1};不包含时 initialize 返回错误 “The backend requires litheLogging version 1.”,不再退回旧的 stderr 文本日志。litheLogging 由 SDK 协商,插件自己在 capabilities 里声明会被拒绝(和 litheBuild 等一致)。
  • 删除自由文本日志 API:Node context.log / backend.log、Java CallContext.log / Backend.log(含带 Throwable 的重载)、Rust Context::log / Backend::log(原来都是写 stderr)。
  • 新增公共 API:diagnostics()(Node 为 diagnostics 属性)提供 degraded(operation, code, count?) 和 recovered(operation, code, count?),用于插件自己报告降级和恢复;suppressSuccessDiagnostics()(当前调用)和 backend.suppressSuccessDiagnostics(operation)(按注册)用于静默高频成功。终态 operationFinished / operationFailed 只由 SDK 自动产生,插件不能手写。
  • 线上只有四种事实:operationFinished(INFO)、operationFailed(ERROR)、degraded(WARN)、recovered(WARN),字段只有 operation、durationMs、code、count、operationId,不能带消息正文、路径、SQL 或其他用户数据。
  • 新增 Diagnostics 模块(Node src/diagnostics.mjs、Java Diagnostics.java、Rust src/diagnostics.rs):在本地先校验 token 字符集和长度、已知 operation 白名单以及字段组合;不合法的事实在 SDK 内拒收(sdk.logging.invalidOperation 等),不会发给 Core。
  • operation 白名单包括插件注册的函数、SDK 自有阶段(initialize、shutdown、notification、function-call、result-encoding)、lithe/build/*、lithe/vcs/* 和 lithe/keymap/import,与 Core 的 known_operation 一一对应。

自动上报行为

  • 函数调用、构建、VCS 请求的终态由 SDK 自动上报:成功为 operationFinished 带耗时,失败为 operationFailed 带稳定错误码;事实带 wire 请求号作为 operationId,Core 据此关联回宿主 op。
  • 成功事实可以按注册(高频调用整体静默)或按当前调用抑制,失败事实始终保留。
  • 正常终态先于 RPC 响应发出,保证日志顺序与调用顺序一致。
  • initialize 完成前产生的事实最多缓存八条,在 initialize 响应之后发送,超出部分丢弃。
  • 快捷键导入:rebase 到 Support shortcut import providers in plugin SDKs #15/Sync keymap import plugin contract #16(typed shortcut import provider)后,lithe/keymap/import 请求也自动上报终态。事实中的 operation 使用 Core 注册的线协议方法名 lithe/keymap/import,而不是按 provider 区分的调用 id(keymap:<provider>);公开的 context.function_id() 仍返回 keymap:<provider>,与上游行为一致。

各语言实现细节

  • Node:backend.mjs 的 #run 增加诊断 operation 参数,#invokeKeymap 传入 lithe/keymap/import;errors.mjs、host.mjs 配合调整;index.d.ts 删除 log,新增 Diagnostics 接口、diagnostics 与 suppressSuccessDiagnostics。
  • Java:Backend.run 增加诊断 operation 参数,invokeKeymap 传入 lithe/keymap/import;CallContext、Cancellation、HostChannel、PluginError、Processes 配合删除自由文本日志、改用事实上报。
  • Rust:backend.rs 新增常量 KEYMAP_IMPORT_METHOD,function_answer 改为显式接收诊断 operation(普通调用传 function_id,快捷键导入传线协议方法名);worker 启动失败按同一 operation 上报 worker_start_failed;新增 panic_boundary.rs,在 SDK 捕获范围内屏蔽 panic payload(不把 panic 文本当作日志外泄),范围外保留原 panic hook;修复 clippy nonminimal_bool(改用 is_none_or)。

文档、示例与端到端

  • 新增 guides/plugin-logging.md:说明协商、四种事实与级别映射、自动上报规则、抑制规则、白名单,以及插件不应该自己写日志文件。
  • 根 README.md 和三种 SDK 的 README 删除旧 log 用法,改为诊断事实示例;Node/Java/Rust 示例后端同步更新。
  • scripts/sdk-e2e.mjs 与 sdk/e2e/plugin_sdk/{mod,backend,vcs}.rs:端到端场景校验 Core 写入的通道、级别、op 关联、耗时和隐私(不出现正文)。

测试

  • Node:diagnostics.test.mjs(新增)以及 backend/build/vcs/keymap 测试;keymap.test.mjs 断言快捷键导入上报恰好一条 operationFinished / lithe/keymap/import。
  • Java:BackendTest 补诊断场景,KeymapTest 断言同上,TestHost 支持读取 lithe/log 消息。
  • Rust:tests/session.rs 补协商、缓存、顺序、抑制、panic 屏蔽等场景;tests/keymap.rs 的 initialize 提供 litheLogging,断言快捷键导入在响应前恰好一条事实。

验证

本地在 rebase 到最新 main(f968e3f)之后完成:

  • Node:node --test sdk/node/test/*.test.mjs 77/77;npm run test:types 通过。
  • Java:mvn verify 64 项通过(BUILD SUCCESS)。
  • Rust:cargo fmt --check、cargo clippy -- -D warnings、全部单元、集成、文档测试通过。
  • 脚本:node --test scripts/*.test.mjs 16/16。
  • 端到端:node scripts/sdk-e2e.mjs --source <宿主工作树> --ref codex/owned-plugin-logging(宿主 286c0090d)9/9 通过,含三种 SDK 的快捷键导入场景。

本轮更新(宿主 #1699 合并后)

  • 契约同步已通过 Sync plugin logging contract #18 合入 main,contract.lock.json 固定到宿主合并提交 7a24126eca3a26775daeb84db38ae04bec938d1a(含 litheLogging 1);本分支已合入该 main。之前固定在旧宿主上的端到端失败,是因为新 SDK 按设计拒绝不支持 litheLogging 1 的宿主,现在不会再出现。
  • sdk/rust/plugin-sdk/src/diagnostics.rs:请求号回退改用 ?,修复 CI 中 stable clippy 1.99 报的 clippy::question_mark,行为不变。
  • sdk/e2e/plugin_sdk/mod.rs:修复端到端 CI 偶发失败。同一个测试二进制里的测试并行运行,共用 Core 进程级的诊断事实队列(diagnostics.drainCoreEvents),一个测试排空时会把另一个测试插件的事实取走,导致对方断言找不到事实。现在所有排空都在一把锁下进行,排出的事实先放进共享暂存区,每个测试只取走自己插件通道(plugins/<id>/host)的事实,其余留给其他测试。断言内容不变。
  • 复验:
    • node scripts/sdk-e2e.mjs --source <Lithe 仓库> --build-workflows(宿主 7a24126ec)9/9 通过,包括 Node/Java 原生 build/test/run 流程、三种 SDK 的示例后端与快捷键导入;
    • Rust:cargo fmt --check、cargo clippy --all-targets -- -D warnings(本机 1.96),以及 cargo +1.87 test 全部通过;
    • 脚本 16/16;contract.mjs verify --upstream(79 个文件)通过。
    • 修复端到端竞争后,sdk-e2e.mjs --build-workflows 本地连续 3 次 9/9 通过;CI 五项检查(契约镜像、Java、Node、Rust、端到端)全部通过。

合并顺序

  1. 宿主 PR feat(logging): 插件与调试适配器接入结构化日志 v2 1lck/Lithe-IDEA#1699 合入 preview(已合入)。
  2. 契约同步(Sync plugin logging contract #18 已合入)。
  3. 合入本 PR。
  4. 各插件 PR 把 vendored SDK 固定到本 PR 合并后的 commit,再合入。新 SDK 只能在支持 litheLogging 1 的 Lithe(包含 #1699)上启动,稳定版带上 #1699 之前,插件只能以预发布形式发布。

限制

  • 未在 Windows 主机上运行 SDK(Windows 宿主仍是 v1 writer)。
  • 真实插件(JDT、LLDB、Docker daemon)通过新 SDK 的整机日志窗口展示没有做端到端验收。

配套 PR:

- Node、Java、Rust SDK 在 initialize 中强制协商 litheLogging 1,删除自由文本
  log API,改为通过 lithe/log 上报受控事实(finished/failed/degraded/recovered)
- 操作终态自动上报并保留真实 op;成功可按注册或当前调用抑制,失败始终保留;
  初始化完成前最多缓存八条,响应后发送;正常终态先于 RPC 响应
- 快捷键导入请求 lithe/keymap/import 也自动上报终态,事实中的 operation 用
  Core 注册的线协议方法名,而不是按 provider 区分的调用 id;三种 SDK 的
  operation 白名单同步加入该方法
- Rust SDK 在捕获范围内屏蔽 panic payload,范围外保留原 panic hook
- 新增 guides/plugin-logging.md,更新三种 SDK README、示例与端到端场景
Core's catalog queue is process-global and the tests of one binary run in
parallel, so one test's drain could take another plugin's terminal facts
(CI saw the Node build scenario consume the VCS checkin fact). Every drain
now happens under one lock into a shared buffer, and each test takes only
the facts on its own plugin's channel.
@xiaoyumuxi
xiaoyumuxi merged commit 67ee82c into main Nov 4, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant