资讯动态

Qwen Code VS Code 输出通道日志方案解析:统一 Extension Host 与 Webview 的运行诊断日志

发布时间:2026/9/13 17:40:23 来源:尧图企业网站定制
Qwen Code VS Code 输出通道日志方案解析统一 Extension Host 与 Webview 的运行诊断日志【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code本篇文章围绕 qwen-code 仓库中的设计文档 VS Code Output Channel Logging 展开系统讲解 Qwen Code Companion 扩展如何把 Extension Host 与 Webview 两侧的运行诊断日志统一写入 VS Code 的Qwen Code Companion输出通道Output Channel。读完本文你将掌握共享日志器的格式化与脱敏机制、Webview 日志经消息桥回传的完整调用链以及如何在开发与生产模式下收集一份完整、安全、可读的运行日志。背景为什么运行诊断日志难以收集在引入输出通道日志之前Qwen Code Companion 扩展的运行时诊断主要依赖console.*方法这会带来两个割裂的收集入口Extension Host 侧日志需要在 VS Code 中打开「开发者工具」Help → Toggle Developer Tools查看 Console 面板Webview 侧日志需要单独打开 Webview 的开发者工具Webview Developer Tools与 Extension Host 的日志完全隔离。用户遇到问题时往往无法一次性拿到一份覆盖两端的完整日志报告排查链路被拆成两段。设计文档在 Problem 小节 中明确指出了这一痛点并给出了解决方案复用扩展激活时创建的同名OutputChannel把日志统一收拢到一个用户可以直接在「输出」面板中选择查看的地方。总体设计思路整体设计围绕三点展开复用现有输出通道扩展激活activate时创建名为Qwen Code Companion的OutputChannel并让共享 logger 在开发与生产两种模式下都向它写入Extension Host 侧改造运行时代码统一改用共享 logger 替代console.*logger 保留日志级别、格式化对象与 Error、脱敏敏感字段并在写入前叠加既有的凭证脱敏器Webview 侧桥接Webview bundle 重定向全局console.*方法把格式化后的日志消息通过既有的 Webview → Extension Host 消息桥发送回宿主宿主校验消息并转义换行后写入同一通道。与此同时构建脚本与测试代码不运行在扩展进程内因此继续使用console.*不受影响。这一点在仓库中也有印证对console.的搜索结果显示剩余使用点主要位于测试文件与 Webview 的 mock 回退路径中。Extension Host 侧共享日志器的接入激活时创建输出通道在 packages/vscode-ide-companion/src/extension.ts 的activate入口扩展创建输出通道并立即把共享 logger 的写入目标切到该通道outputChannel vscode.window.createOutputChannel(Qwen Code Companion); createLogger(outputChannel, redactLogCredentials); logger.info(Extension activated);createOutputChannel(Qwen Code Companion)创建的就是用户在「输出」面板中看到的下拉选项名称createLogger(outputChannel, redactLogCredentials)把 logger 的 sink 指向该通道并注册脱敏函数随后的logger.info(Extension activated)验证日志已进入新通道。对应的单元测试 packages/vscode-ide-companion/src/extension.test.ts 断言了生产模式激活时会调用createOutputChannel(Qwen Code Companion)且写入的第一行内容为[INFO] Extension activated。共享 logger 的实现细节共享 logger 位于 packages/vscode-ide-companion/src/utils/logger.ts其核心设计如下日志级别LOG_LEVELS [debug, error, info, log, warn]与console.*的方法名一一对应便于 Webview 侧做同构映射。可替换的 sinklogger 内部维护一个sink变量默认指向console调用createLogger后切换为向OutputChannel.appendLine写入export function createLogger( outputChannel: vscode.OutputChannel, sanitize: (message: string) string (message) message, ): void { sink (level, args) { const label level log ? INFO : level.toUpperCase(); const line sanitize([${label}] ${formatLogArgs(args)}); try { outputChannel.appendLine(line); } catch { globalThis.consolelevel; } }; }这里有几个值得注意的实现细节级别标签log级别被归一化为INFO标签其余级别大写显示最终每行形如[INFO]、[WARN]、[ERROR]失败兜底若appendLine抛出异常如通道已释放会回退到console输出保证日志不丢、不崩deactivate时的清理extension.ts 在扩展停用时先resetLoggerSink()恢复 console 默认 sink再outputChannel.dispose()释放通道。参数格式化对象、Error、BigInt 与循环引用formatLogArgs逐参数调用formatValue后以空格拼接。formatValue的规则见 logger.ts字符串原样返回Error实例返回stack ?? message保留完整堆栈其他值走JSON.stringify的自定义 replacer敏感键见下替换为redactedbigint序列化为2n形式避免丢失大整数语义嵌套的Error展开为堆栈借助WeakSet检测循环引用并输出[Circular]防止 JSON 序列化抛错序列化整体失败时兜底为String(value)。双层脱敏字段级 凭证级设计文档强调「redacts sensitive object fields, and applies the existing log-credential redactor before writing」对应仓库中的两层脱敏第一层对象敏感字段脱敏logger 内建。sensitiveKeys集合覆盖accesstoken、apikey、authorization、cookie、password、refreshtoken、secret、token等键名replacer 先把键名去掉-/_并转小写再匹配因此api_key、API-Key、refreshToken等变体都能命中。第二层凭证脱敏复用 acp-bridge。redactLogCredentials来自 packages/acp-bridge/src/logRedaction.ts它以 12 条正则顺序处理整行文本覆盖模式示例Bearer 令牌飞书、微信、Daemon SDKBearer xxxxQQ Bot 令牌QQBot xxxxAuthorization 头含 Basic 等 schemeAuthorization: xxxx钉钉自定义 access token 头x-acs-dingtalk-access-token: xxxxsk-前缀 API Key≥20 字符sk-proj-xxxxGitHub/GitLab/Slack 令牌ghp_...、glpat-...、xoxb-...AWS Access Key IDAKIA.../ASIA...keyvalue形式密钥赋值tokenxxxx、api_key: xxxx以_KEY/_TOKEN/_SECRET/_PASSWORD结尾的环境变量AWS_SECRET_ACCESS_KEYxxxxJSON 引号内的密钥字段client_secret:xxxxURL 内嵌凭证https://user:passhost脱敏发生在整行渲染之后sanitize(...)包裹[LABEL]前缀保证「最终落盘的行」不包含明文凭证。Webview 侧把全局 console 重定向到消息桥Webview bundle 无法直接访问 Extension Host 的OutputChannel因此设计采用「重定向console.* 消息桥回传」的方式实现在 packages/vscode-ide-companion/src/webview/hooks/useVSCode.ts 的initializeWebviewLogger中const postLog (level: LogLevel, args: unknown[]) { vscode.postMessage({ type: log, data: { level, message: formatLogArgs(args) }, }); }; for (const level of LOG_LEVELS) { const original globalThis.console[level].bind(globalThis.console); globalThis.console[level] (...args: unknown[]) { original(...args); // 保留 Webview 自身控制台输出 try { postLog(level, args); // 同时回传宿主 } catch { // 日志失败绝不能崩溃调用方 } }; }关键点同构格式化消息体直接复用 Extension Host 侧的formatLogArgs保证两侧日志的格式一致原始输出保留重定向后的方法仍先调用原始console实现Webview 开发者工具中依旧能看到日志只是多了一条回传路径幂等初始化用模块级标志__qwenWebviewLoggerInitialized防止重复包裹入口时机webview/index.tsx 在 bundle 入口处即调用initializeWebviewLogger()覆盖共享 Web UI 的全局日志。宿主侧校验与写入Webview 消息到达 Extension Host 后由 packages/vscode-ide-companion/src/webview/providers/WebViewProvider.ts 的消息处理器接收if (message.type log) { const data message.data as { level?: unknown; message?: unknown } | undefined; if (isLogLevel(data?.level) typeof data.message string) { const logMessage data.message.length MAX_WEBVIEW_LOG_LENGTH ? ${data.message.slice(0, MAX_WEBVIEW_LOG_LENGTH)}...[truncated] : data.message; loggerdata.level, ); } return true; }这里体现了设计文档所说的「host validates each message and escapes line breaks」级别校验isLogLevel只放行debug/error/info/log/warn五个已知级别trace、undefined等一律拒绝见 logger.ts 与对应单测防止任意字符串被当作方法名调用类型校验message必须是字符串长度截断超过MAX_WEBVIEW_LOG_LENGTH 10_000字符的消息被截断并追加...[truncated]常量定义于 WebViewProvider.ts防止超大日志拖垮输出通道换行转义把\r\n、\r、\n统一转义为字面\n避免 Webview 侧的多行内容破坏输出通道「一行一条日志」的结构来源标记写入时统一加[Webview]前缀用户在输出面板中可一眼区分日志来自宿主还是 Webview。如何查看与使用这份日志在 VS Code 中激活 Qwen Code Companion 扩展后打开菜单View → Output或快捷键CtrlShiftU在输出面板右上角的下拉框中选中Qwen Code Companion此时 Extension Host 与 Webview 两端的运行日志都会实时出现在同一面板中可直接全选复制或通过 VS Code 自带的导出功能保存为日志文件作为 issue 报告或本地排障的完整依据。由于日志写入不区分开发/生产模式activate中的createLogger调用与ExtensionMode无关无论是本地调试还是用户环境中的生产版本都能得到同一条收集路径。测试与验证设计文档的 Verification 小节列出的验收点在仓库中均有对应测试支撑验收点测试位置验证内容生产激活写入Qwen Code Companion通道extension.test.ts断言createOutputChannel(Qwen Code Companion)被调用且首行写入[INFO] Extension activated多参数、对象、循环引用、Error 保持可读logger.test.tsError: boom、apiKey:redacted、count:2n、self:[Circular]敏感字段与常见凭证被脱敏logger.test.ts最终行包含Authorization: redacted不含明文 tokenWebview 日志到达宿主 loggerinitializeWebviewLogger WebViewProvider.tstype: log消息经校验后写入共享 logger通道写入失败时安全降级logger.test.tsappendLine抛错后回退 console脱敏仍生效通道释放后恢复 console 日志logger.test.tsresetLoggerSink后logger.warn走回 console此外单测中的isLogLevel校验用例error通过、trace/undefined拒绝直接对应 Webview 消息的安全过滤逻辑杜绝了外部注入任意日志方法名的可能。总结VS Code 输出通道日志方案用一次「sink 切换 消息桥回传」的改造把原本散落在 Extension Host 开发者工具与 Webview 开发者工具两处的诊断日志统一收拢到用户可一键访问的Qwen Code Companion输出通道。其价值不仅在于便捷性更在于安全性与可靠性对象级与凭证级双层脱敏确保日志可安全外发级别/类型/长度/换行四重校验保证通道内容结构稳定写入失败兜底与停用清理则让日志系统本身足够健壮。对排查 qwen-code 在 VS Code 中的集成问题而言这份统一日志已经是第一手的诊断入口。【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价