fix(telemetry): ignore unsupported OTel exporter selectors - #8703
Conversation
Verification reportEnvironment
Reproduction and resultFailure-first reproduction on the current upstream bundle: After the fix, the same The facade removes all three external exporter selectors only during synchronous Tests executed
EvidenceNo screenshot is applicable: this is non-visual telemetry startup behavior. The failure and fixed bundle outputs above are real local command results. 中文验证报告验证报告环境
复现与结果在当前 upstream bundle 上进行了修复前失败复现: 修复后,在同样设置 facade 只在同步 已执行测试
证据这是非视觉 telemetry 启动行为,不适用截图。上方的失败和修复后 bundle 输出均来自本地实际命令。 |
|
@qwen-code /takeover |
|
🤝 Takeover engaged: the autofix loop now manages this PR — it will address new review feedback and resolve base conflicts until the label is removed or the round cap is reached. This is a fork PR, so the first round comes from the next scheduled scan (usually within minutes). Remove the 中文说明🤝 已接管:autofix 循环现在管理此 PR —— 将持续处理新的评审反馈与 base 冲突,直到移除标签或达到轮次上限。本 PR 来自 fork,首轮处理将由下一次定时扫描执行(通常几分钟内)。移除 |
|
Re-run on commit
Moving on to code review. 🔍 中文说明在提交
进入代码审查 🔍 — Qwen Code · qwen3.8-max Reviewed at |
Code reviewIndependent proposal for this commit, written before reading its diff: F1 is fixed by recording the observed env values inside the mocked Both new tests are genuine guards now. I can't mutation-test here (triage never executes PR code), so I checked statically:
No blockers, and no new observations. The prior run's two non-blocking notes still stand as recorded (the no- TestingEvidence basis: unattended CI run — no code was built or executed here. The table quotes the PR's own CI checks on the reviewed commit via the API. One red artifact to name plainly: the The behavioral claim no longer rests on the author's word, so there is no sandboxed-lane line this round: @wenshao's independent six-arm A/B (real source-built bundles, real OTLP/gRPC collector,
Completed checks on the reviewed commit; skipped checks (macOS/Windows test matrix and integrations — gated for fork PRs) omitted. / reviewed commit 上已完成的 check;省略 skipped(fork PR 受限的 macOS/Windows 测试矩阵与集成测试)。 中文说明代码审查读 diff 之前先写独立方案:F1 的正确修法是在被 mock 的 两个新测试现在都是真正的守护。triage 不执行 PR 代码,无法做 mutation 测试,故以静态方式核对:
无阻塞项,也无新观察。上次运行的两条非阻塞记录仍然有效(无 测试证据基础: 无人值守 CI 运行——此处未构建或执行任何代码。表格通过 API 引用 reviewed commit 上 PR 自身的 CI 检查结果。 一个需要明说的红色项:本 head 上的 行为结论不再依赖作者自述,因此本轮不再列沙箱验证通道:@wenshao 的独立六组 A/B(真实源码构建 bundle、真实 OTLP/gRPC collector、base 与 PR head 各跑 CI 结果见英文版表格。 — Qwen Code · qwen3.8-max Reviewed at |
|
Confidence: 4/5 — everything the gate can check is clean on the new head; the only remainder is the two follow-up items from #8697 that the maintainer explicitly said should not block. The prior run deferred with one open question: who owns the telemetry-policy call? The answer came in the strongest form possible — @wenshao built both bundles from source, ran a six-arm A/B against a real OTLP/gRPC collector, reproduced the bug on base and confirmed the repair on this branch (including the Stepping back: the root cause is independently verified, the fix is the smallest one that works, the tests now pin it, the maintainer approved this exact commit, and the only red CI artifact is a zero-job startup failure of the review-bot workflow itself. The one standing nit: #8697's other two asks — a warning visible without Approving, pinned to the reviewed commit. ✅ 中文说明置信度:4/5 —— 新 head 上门禁能查的一切均干净;唯一遗留是 #8697 的两个后续项,maintainer 已明确表示不应阻塞本 PR。 上次运行带着一个未决问题搁置:telemetry 策略决定由谁拍板?答案以最有力的形式给出——@wenshao 从源码构建了两份 bundle,对接真实 OTLP/gRPC collector 跑了六组 A/B,在 base 上复现了 bug、在本分支上确认了修复(包括 退一步看:根因已被独立核实,修复是可行的最小方案,测试现在钉住了它,maintainer 已批准这个确切的提交,唯一的红色 CI 项是评审机器人工作流自身的零 job 启动失败。唯一的遗留小项:#8697 的另外两点诉求——不依赖 予以批准,钉在 reviewed commit 上。✅ — Qwen Code · qwen3.8-max Reviewed at |
|
✅ Resolved (re-run, 2026-08-08): the sign-off this deferral asked for has arrived — @wenshao verified the fix end-to-end (six-arm A/B, real bundles, real OTLP/gRPC collector), his two test findings were addressed and mutation-checked in commit ⏸️ Deferring to @wenshao — this PR is a clean, minimal, well-evidenced fix for #8697, but it settles a telemetry-policy question (standard
No code blockers found; CI was still running at review time. Needs a human call on this one. 中文说明✅ 已解决(重跑,2026-08-08): 本次搁置所等待的签核已经给出——@wenshao 端到端验证了修复(六组 A/B、真实 bundle、真实 OTLP/gRPC collector),他提出的两个测试问题已在提交 ⏸️ 转交 @wenshao —— 本 PR 是对 #8697 干净、最小且证据充分的修复,但它确定了一个 telemetry 策略问题(qwen-code 启动 SDK 期间忽略标准
未发现代码阻塞项;review 时 CI 仍在运行。这一项需要人工决定。 — Qwen Code · qwen3.8-max |
|
🤖 Reviewed the latest feedback — no changes needed. Why, point by point: · 已审阅最新反馈——无需改动。逐点说明原因如下: Autofix review round: no action neededNo actionable feedback arrived since the last evaluation, so this round makes no changes. What was checked
Result No code changes were made. The PR head remains at 中文说明Autofix 评审轮次:无需处理自上次评估以来没有收到需要处理的反馈,因此本轮不做任何改动。 已检查内容
结果 未做任何代码改动。PR 的 head 仍为 Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。 🧠 Handled by Qwen Code · model/模型 |
Verification report — real bundled CLI against a real OTLP/gRPC collectorVerdict: the fix is correct and I reproduced #8697 and its repair end-to-end. Recommend merge, with one non-blocking follow-up: the new unit test does not actually guard the fix (it passes with the fix reverted). HarnessNot a mock of the SDK — the actual shipped artifact:
Linux (Debian 13, kernel 6.12), Node v22.22.2, npm 10.9.7 — so this also covers the 🐧 Linux row the PR left as N/A. A/B results
Arm 1 reproduced the issue's error line verbatim: Two things worth flagging for merge priority:
Arms 2 and 4 also confirm that Caller environment is genuinely restoredVerified in the real process rather than only in a unit test: a child process spawned by the
Static checks (PR worktree)
Findings (non-blocking)F1 — the new test is a false green. Recording inside the mock and asserting after + const observed: Record<string, string | undefined> = {};
vi.mocked(NodeSDK.prototype.start).mockImplementationOnce(() => {
startCalled = true;
for (const name of Object.keys(exporterEnv)) {
- expect(process.env[name]).toBeUndefined();
+ observed[name] = process.env[name];
}
});
try {
await initializeTelemetry(mockConfig);
expect(startCalled).toBe(true);
+ for (const name of Object.keys(exporterEnv)) {
+ expect(observed[name]).toBeUndefined();
+ }F2 — the Scope notes (not objections)
中文完整版验证报告 —— 真实 bundle CLI 对接真实 OTLP/gRPC collector结论:修复正确,我端到端复现了 #8697 并验证了修复效果,建议合入。 有一个不阻塞合入的后续项:新增的单元测试实际上并不能守护这个修复(把修复回退掉,它照样通过)。 验证环境不是对 SDK 打桩,而是真实的发布产物:
Linux(Debian 13,内核 6.12)、Node v22.22.2、npm 10.9.7 —— 因此也补上了 PR 中标为 N/A 的 🐧 Linux 一行。 A/B 结果
第 1 组一字不差地复现了 issue 中的报错: 有两点值得在合入优先级上强调:
第 2、4 组同时证明 调用方环境确实被还原了不只靠单元测试,而是在真实进程里验证:telemetry 启动之后由
静态检查(PR worktree)
发现的问题(不阻塞合入)F1 —— 新增测试是"假绿"。 改成在 mock 内部记录、在 + const observed: Record<string, string | undefined> = {};
vi.mocked(NodeSDK.prototype.start).mockImplementationOnce(() => {
startCalled = true;
for (const name of Object.keys(exporterEnv)) {
- expect(process.env[name]).toBeUndefined();
+ observed[name] = process.env[name];
}
});
try {
await initializeTelemetry(mockConfig);
expect(startCalled).toBe(true);
+ for (const name of Object.keys(exporterEnv)) {
+ expect(observed[name]).toBeUndefined();
+ }F2 —— 范围说明(不是反对意见)
|
…enLM#8697) The env-scrub assertions ran inside the mocked start(), where initializeTelemetry's init-failure catch swallowed them — the test passed even with the fix reverted. Record observations during start() and assert after init resolves, add a throw-path test proving the finally block restores the caller's environment, and note in sdk-impl that spanProcessors/logRecordProcessors must stay unconditional arrays because the sdk-node logs env fallback runs in the NodeSDK constructor, outside the scrub window around start().
|
🤖 Addressed the latest review feedback (round 1/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 1/100 轮)。改动内容与我反驳保留之处如下: Autofix review round — PR #8703The round's feedback is @wenshao's end-to-end verification report (real bundled CLI against a real OTLP/gRPC collector), which confirms the fix is correct and reproducible, and raises two non-blocking findings plus one suggestion. All three are addressed; both test findings were additionally mutation-verified locally. Feedback points and dispositionsF1 — the new unit test is a false green (fixed). Verified against the code: the F2 — the Invariant comment at the Scope notes — warning without The remaining report content (A/B reproduction, blast-radius analysis, caller-environment restore verification, Changes
No production logic changed this round. Commit: VerificationCommands actually run (from the repository root unless noted):
Integration tests were not run: this round changed tests and comments only, with zero production-behavior change; the bundled-CLI A/B behavior was already verified end-to-end by the maintainer's report against the previous commit. 中文说明Autofix 评审轮次 — PR #8703本轮反馈是 @wenshao 的端到端验证报告(真实 bundle CLI 对接真实 OTLP/gRPC collector)。该报告确认修复正确且可复现,并提出了两个不阻塞合入的问题和一条建议。三者均已处理;两个测试问题还在本地额外做了 mutation 验证。 反馈点及处理F1 —— 新增单元测试是"假绿"(已修复)。 对照代码核实: F2 ——
范围说明 —— 不依赖 报告中的其余内容(A/B 复现、影响面分析、调用方环境还原验证、 改动内容
本轮没有改动任何生产逻辑。提交: 验证实际执行的命令(如无特别说明均在仓库根目录执行):
未运行集成测试:本轮只改了测试和注释,生产行为零变化;bundle CLI 的 A/B 行为已由评审人的报告在上一个提交上完成端到端验证。未执行 Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。 Re-review when you have a moment. After round 100 this bot stops and leaves the PR for a human. · 有空请复审;第 100 轮后本 bot 停止并将 PR 交给人工。 🧠 Handled by Qwen Code · model/模型 |
|
@qwen-code /review |
| _Qwen Code review request accepted. Review is queued in [workflow run](https://github.com/QwenLM/qwen-code/actions/runs/31243238704)._ |
|
Qwen Code review timed out. Qwen review timed out after 10800 seconds (of the 180-minute budget). For large PRs, retry with a longer timeout by commenting: |
|
🤖 Reviewed the latest feedback — no changes needed. Why, point by point: · 已审阅最新反馈——无需改动。逐点说明原因如下: Autofix review round: no changesThe only new feedback since the last evaluation is the automated reviewer's own notice that its review run timed out after 10800 seconds. That is an infrastructure event, not a code finding:
The branch is unchanged: 中文说明Autofix 审查轮次:无变更自上次评估以来,唯一的新反馈是自动审查器自身发出的通知,说明其审查运行在 10800 秒后超时。这是一次基础设施事件,而不是代码问题:
分支保持不变: Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。 🧠 Handled by Qwen Code · model/模型 |
|
@qwen-code /triage |
|
Sandboxed verification: ✅ passed — merge-ready (agent verdict) - workflow run Ran the PR in an isolated, token-free container: A/B against the base build, mock-free harness assertions, targeted gates. Advisory evidence for human reviewers — not a review, an approval, or a CI check. Scripted assertions: 85 passed · 0 failed · 85 total 中文 — 判定:✅ 通过 · 可合入(agent 判定)沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查。 脚本断言:85 通过 · 0 失败 · 85 总计 Verification reportPR 8703 — fix(telemetry): ignore unsupported OTel exporter selectorsVerdict: 中文摘要
Central claim + A/BCentral claim: while the bundled CLI starts its telemetry SDK, Mechanism confirmed from installed Harness: real bundled CLI (
All cells exit 0 — the base failure is silent at the process level, exactly the reported symptom. Witness: Secondary claim 1 — exact env restore. Real-path probe through the real (dev-tree) Secondary claim 2 — the new tests are load-bearing. Mutation matrix on
Partitioning nuance (completeness, not a defect): M1 kills only test 1 and M2 kills both — test 1 pins the scrub, test 2 pins the finally-restore on throw; together they cover the property, and M1 being exactly base code also proves the new test fails against the pre-fix source for the intended reason. Targeted gate: Reviewer Test Plan walk: (1) bundle built ✓ (via FindingsF1 (informational, pre-existing, non-blocking): the telemetry init failure is observable only in the F2 (positive): the sibling door Not covered
MethodologyEnvironment: Evidence imagesHarness scripts and raw logs are in the workflow run artifacts (7-day retention). — Qwen Code · sandboxed verification |
|
🤖 Reviewed the latest feedback — no changes needed. Why, point by point: · 已审阅最新反馈——无需改动。逐点说明原因如下: Autofix review round: no action takenNo changes were made to PR #8703 in this round. Feedback triage:
Since there is no actionable feedback, no code changes are needed and no commit was created. The branch remains at its current head commit. 中文说明Autofix 审查轮次:未采取任何操作本轮未对 PR #8703 做任何修改。 反馈分类结果:
由于没有可处理的反馈,无需修改代码,也未创建任何提交。分支保持在当前 head 提交不变。 Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。 🧠 Handled by Qwen Code · model/模型 |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
|
Released in v0.21.9. |






What this PR does
This PR prevents sdk-node from reading the standard
OTEL_TRACES_EXPORTER,OTEL_LOGS_EXPORTER, andOTEL_METRICS_EXPORTERselector variables while Qwen Code starts its telemetry SDK. The variables are restored immediately after the synchronous SDK start call.Why it's needed
Qwen Code already supplies explicit exporters for each enabled signal. In the bundled CLI, sdk-node's environment auto-configuration can nevertheless construct an omitted OTLP exporter when
OTEL_METRICS_EXPORTER=otlpis present. That constructor throws after partial SDK setup, so Qwen Code's own telemetry remains uninitialized and metrics are silently lost while unrelated instrumentation can continue exporting.Fixes #8697
Reviewer Test Plan
How to verify
npm run build -- --cli-only && npm run bundle.OTEL_METRICS_EXPORTER=otlpand an explicit Qwen Code gRPC OTLP endpoint.OTEL_*_EXPORTERvalues are unchanged after startup.Before this change, the bundled SDK fails with
qwen-code bundles @opentelemetry/sdk-node without @opentelemetry/exporter-metrics-otlp-proto ... Attempted to construct: OTLPMetricExporter. After this change, the same invocation reportsinitialized:true.Evidence (Before & After)
N/A — this is a non-visual telemetry startup behavior. Exact command output and test results are included in the verification report below.
Tested on
Environment (optional)
Risk & Scope
Linked Issues
Fixes #8697
中文说明
What this PR does
本 PR 防止 sdk-node 在 Qwen Code 启动 telemetry SDK 时读取标准的
OTEL_TRACES_EXPORTER、OTEL_LOGS_EXPORTER和OTEL_METRICS_EXPORTER选择变量。变量会在同步 SDK 启动调用结束后立即恢复。Why it's needed
Qwen Code 已经为每个启用的信号显式提供 exporter,但在 bundle CLI 中,即使设置了
OTEL_METRICS_EXPORTER=otlp,sdk-node 的环境变量自动配置仍可能构造一个被 bundle 排除的 OTLP exporter。该构造器会在 SDK 部分初始化后抛错,导致 Qwen Code 自身的 telemetry 未初始化,metrics 静默丢失,而无关的 instrumentation 仍可能继续导出。Fixes #8697
Reviewer Test Plan
How to verify
npm run build -- --cli-only && npm run bundle构建 CLI bundle。OTEL_METRICS_EXPORTER=otlp和显式的 Qwen Code gRPC OTLP endpoint。OTEL_*_EXPORTER值在启动后保持不变。修复前,bundle SDK 报错:
qwen-code bundles @opentelemetry/sdk-node without @opentelemetry/exporter-metrics-otlp-proto ... Attempted to construct: OTLPMetricExporter。修复后,同一调用输出initialized:true。Evidence (Before & After)
不适用——这是非视觉 telemetry 启动行为。精确命令输出和测试结果会在下面的验证报告中列出。
Tested on
Environment (optional)
Risk & Scope
Linked Issues
Fixes #8697