Skip to content

feat: collect VS Code diagnostics in support bundles#971

Open
EhabY wants to merge 5 commits into
mainfrom
feat/support-bundle-diagnostics
Open

feat: collect VS Code diagnostics in support bundles#971
EhabY wants to merge 5 commits into
mainfrom
feat/support-bundle-diagnostics

Conversation

@EhabY
Copy link
Copy Markdown
Collaborator

@EhabY EhabY commented May 21, 2026

Summary

  • add vscode-logs/settings.json with inspect-style coder.* / remote.* settings; redacts 14 sensitive values (paths, hostnames, URLs, command strings) to <set> or <empty>
  • store the active Coder SSH proxy log under vscode-logs/proxy/, preserving its original filename (e.g. coder-ssh-12345.log) so diagnostic PIDs survive
  • keep recent proxy logs under vscode-logs/proxy/
  • collect actual Remote-SSH logs and recent cross-session Coder extension logs under stable session/window paths
  • split support bundle diagnostics into src/supportBundle/ modules for ZIP mutation, log discovery, and settings collection

Follow-up

Tests

  • pnpm format:check
  • pnpm lint
  • pnpm typecheck
  • pnpm test:extension ./test/unit/supportBundle/appendVsCodeLogs.test.ts
  • pnpm test:extension

Closes #955.
Refs #970.

Generated by Coder Agents.

@EhabY EhabY force-pushed the feat/support-bundle-diagnostics branch from 6a3af1c to c3c4c49 Compare May 21, 2026 15:21
@EhabY EhabY self-assigned this May 21, 2026
@EhabY EhabY force-pushed the feat/support-bundle-diagnostics branch 6 times, most recently from 76e7ff2 to 2c03701 Compare May 26, 2026 14:12
@EhabY
Copy link
Copy Markdown
Collaborator Author

EhabY commented May 26, 2026

/coder-agents-review

@coder-agents-review
Copy link
Copy Markdown

coder-agents-review Bot commented May 26, 2026

Review posted | Chat
Requested: 2026-05-26 17:25 UTC by @EhabY
Spend: $65.14 / $100.00

Review history
  • R1 (2026-05-26): 15 reviewers, 2 Nit, 7 P3, 1 P4, COMMENT. Review
  • R2 (2026-05-26), 2 Nit, 7 P3, 1 P4, COMMENT. Review
  • R3 (2026-05-26): 6 reviewers, 2 Nit, 9 P3, 1 P4, COMMENT. Review
  • R4 (2026-05-26): 4 reviewers, 2 Nit, 9 P3, 1 P4, APPROVE. Review

deep-review v0.5.0 | Round 4 | 21d88bb..7e8a79d

Last posted: Round 4, 12 findings (9 P3, 1 P4, 2 Nit), APPROVE. Review

Finding inventory

Findings

# Sev Status Location Summary Round Reviewer Posted
CRF-1 P3 Author fixed (3690c44) logFiles.ts:133 Sort comparator returns -1 for equal elements R1 Netero Yes
CRF-2 P3 Author fixed (3690c44) logFiles.ts:98 readWindowDir duplicates readDirents from files.ts R1 Netero, Mafu-san P3 Yes
CRF-3 Note Dropped by orchestrator (best-effort, TOCTOU requires local file access) files.ts:55 TOCTOU between lstat and readFile R1 Netero No
CRF-4 P3 Author fixed (3690c44) logFiles.ts:149 Active proxy log bypasses symlink guard and age cutoff R1 Hisoka P2, Chopper P3, Meruem P3 Yes
CRF-5 P3 Author fixed (3690c44) settings.ts:27 COLLECTED_SETTINGS allowlist already drifted from package.json R1 Kite P3, Razor P3, Mafuuu Note Yes
CRF-6 P3 Author fixed (3690c44) appendVsCodeLogs.ts:52 Variable logFiles and message misidentify content when settings included R1 Gon P3, Zoro P3, Mafuuu Nit Yes
CRF-7 P3 Author fixed (3690c44) logFiles.ts:270 Missing doc comments on key exports (collectVsCodeDiagnostics, collectSettingsFile) R1 Leorio P3 Yes
CRF-8 P3 Author fixed (162b611) logFiles.ts:39 Remote SSH log heuristics duplicated between logFiles.ts and sshProcess.ts R1 Robin P3 Yes
CRF-9 P4 Author accepted R2 (composition is 10 lines; both arms have unmocked coverage) logFiles.ts:270 collectVsCodeDiagnostics never tested without mocking R1 Bisky P4, Chopper Note Yes
CRF-10 Nit Author fixed (3690c44) logFiles.ts:152 Error message omits the file path unlike every sibling R1 Leorio Nit, Chopper Nit Yes
CRF-11 Nit Author fixed (3690c44) (PR description) Description says active.log but code preserves real filename R1 Mafu-san P3, Razor Nit Yes
CRF-12 P3 Author fixed (7e8a79d) files.ts:50 readLogFile reads without size check; active proxy log can OOM extension host R3 Meruem P3 Yes
CRF-13 P3 Author fixed (7e8a79d) settings.ts:66 maybeRedact redacts defaultValue for sensitive settings, losing diagnostic signal without privacy benefit R3 Meruem P3 Yes

Contested and acknowledged

CRF-9 (P4, logFiles.ts:270) - collectVsCodeDiagnostics untested

  • Finding: The 10-line composition function is never tested without mocking.
  • Author defense: Both arms (collectSupportLogFiles, collectSettingsFile) already have unmocked coverage. Will add integration test alongside the CRF-8 refactor.
  • Author accepted R2: Risk is bounded by the function's minimal size and independent test coverage of both composed functions.

Round log

Round 1

Panel. Netero first pass: 2 P3, 1 Note (Note dropped). Panel: 7 P3, 1 P4, 1 Nit new. Reviewed against 87a6831..31a7f15.

Round 2

BLOCKED. CRF-8 deferred without ticket. 8 addressed, 1 acknowledged (CRF-9), 1 deferred without ticket (CRF-8). No review.

Round 3

Panel. CRF-8 addressed (162b611). All R1/R2 findings resolved. Netero clean. Panel: 2 P3 new. Reviewed against 21d88bb..162b611.

Round 4

CRF-12, CRF-13 addressed (7e8a79d). Netero clean. All findings resolved. CI green. APPROVE. Reviewed against 21d88bb..7e8a79d.

About deep-review

CRF = Coder Review Finding (P0-P4, Nit, Note)

Reviewer Focus
Bisky tests
Chopper ops/errors
Churn-guard change verification
Ging language modernization
Gon naming
Hisoka edge cases
Killua perf
Kite change integrity
Knov contracts
Knuckle SQL
Kurapika security
Leorio docs
Luffy product
Mafu-san process
Mafuuu contracts
Melody dispatch/pairing
Meruem structural
Nami frontend
Netero mechanical checks
Pariston premise testing
Pen-botter product gaps
Razor verification
Robin duplication
Ryosuke Go arch
Takumi concurrency
Zoro shape

🤖 Managed by Coder Agents.

Copy link
Copy Markdown

@coder-agents-review coder-agents-review Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean modular decomposition of support bundle diagnostics. The split into four focused modules is well-motivated: each has clear responsibility, independent testability, and the test suite (32 tests across 4 files) exercises real filesystem operations, real zip round-trips, and the settings redaction boundary.

Particular strengths: the symlink guard via lstat in file-read paths, the DO_NOT_LEAK_SECRET canary pattern in the settings redaction test, cross-session log collection scoped to windows that actually hosted the Coder extension, the non-canonical layout fallback, and the atomic rename with permission preservation.

"Bungee Gum. Pull the thread: sshProcess.ts:searchForLogFile() discovers the log via readdir (no withFileTypes, no lstat), stashes the path in this.logFilePath." -- Hisoka, tracing the active proxy log path

7 P3, 1 P4, 2 Nit.

PR description note: see inline CRF-11.

Body-level observations:

  • The promoted SSH log basename can be ambiguous when the source is an exthost log (e.g., 1.log at vscode-logs/remote-ssh/1.log). Full per-window paths are always present alongside, so no data loss. Worth noting for support engineers. (Meruem)
  • No size cap on individual file reads. A fresh 500MB proxy log from a debug session gets loaded in full during rezip. Plausible when coder.httpClientLogLevel is debug, which is also when support bundles are created. (Hisoka)
  • 15 of 20 in-scope comments open with a restatement of the code before the actual why. Each adds ~5 extra words of padding. The comments carry genuine information; the pattern is verbosity, not inaccuracy. (Gon)

🤖 This review was automatically generated with Coder Agents.

Comment thread src/supportBundle/logFiles.ts Outdated
Comment thread src/supportBundle/logFiles.ts Outdated
Comment thread src/supportBundle/logFiles.ts Outdated
Comment thread src/supportBundle/settings.ts Outdated
Comment thread src/supportBundle/appendVsCodeLogs.ts Outdated
Comment thread src/supportBundle/logFiles.ts
Comment thread src/supportBundle/logFiles.ts
Comment thread src/supportBundle/logFiles.ts
Comment thread src/supportBundle/logFiles.ts Outdated
Comment thread src/supportBundle/logFiles.ts Outdated
EhabY added a commit that referenced this pull request May 26, 2026
- Fix sort comparator equality case in collectWindowLogDirs (CRF-1)
- Drop readWindowDir; reuse exported readDirents (CRF-2)
- Route active proxy log through readLogFile so it gets the lstat
  symlink guard and a path-bearing warn message (CRF-4, CRF-10)
- Add coder.experimental.oauth, coder.telemetry.level,
  coder.telemetry.local to COLLECTED_SETTINGS (CRF-5)
- Rename logFiles/writeBundleWithLogs to diagnosticFiles/
  writeBundleWithDiagnostics and update log copy (CRF-6)
- Add JSDoc on collectVsCodeDiagnostics and collectSettingsFile (CRF-7)
EhabY added a commit that referenced this pull request May 26, 2026
- Fix sort comparator equality case in collectWindowLogDirs (CRF-1)
- Drop readWindowDir; reuse exported readDirents (CRF-2)
- Route active proxy log through readLogFile so it gets the lstat
  symlink guard and a path-bearing warn message (CRF-4, CRF-10)
- Add coder.experimental.oauth, coder.telemetry.level,
  coder.telemetry.local to COLLECTED_SETTINGS (CRF-5)
- Rename logFiles/writeBundleWithLogs to diagnosticFiles/
  writeBundleWithDiagnostics and update log copy (CRF-6)
- Add JSDoc on collectVsCodeDiagnostics and collectSettingsFile (CRF-7)
@EhabY EhabY force-pushed the feat/support-bundle-diagnostics branch from 96bb4c6 to 3690c44 Compare May 26, 2026 16:06
@EhabY
Copy link
Copy Markdown
Collaborator Author

EhabY commented May 26, 2026

/coder-agents-review

Copy link
Copy Markdown

@coder-agents-review coder-agents-review Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

8 of 11 findings addressed in 3690c44. Clean fixes across the board: sort comparator corrected, readWindowDir consolidated, symlink guard extended via readLogFile factoring, allowlist completed, naming/messages aligned, doc comments added, PR description updated.

CRF-9 (P4) acknowledged with bounded justification: the 10-line composition function's risk is limited by independent test coverage of both composed arms. Accepted.

One finding blocks further review:

CRF-8 (P3) Remote SSH log heuristics duplicated between logFiles.ts and sshProcess.ts. Author acknowledged the duplication and described the fix approach (shared predicate module), but deferred without linking a ticket. The duplication is a maintenance concern: if VS Code changes its log layout, both files need independent, untested-against-each-other updates. This needs a human decision: file a tracking issue, or explicitly accept the gap.

Further panel review is blocked until CRF-8 has a linked ticket or explicit human acceptance. Pushing fixes or responding unblocks the next round.

🤖 This review was automatically generated with Coder Agents.

EhabY added a commit that referenced this pull request May 26, 2026
Address PR #971 CRF-8: extract the Remote-SSH log layout knowledge
(extension exthost dirs, `output_logging_` prefix, `Remote - SSH`
filename fragment) into `sshExtension.ts` as predicates and consume
them from both `sshProcess.ts` and `supportBundle/logFiles.ts`. A
future VS Code log layout change now touches one place.
EhabY and others added 4 commits May 26, 2026 19:27
Address code review findings and collapse the support-bundle module
from 6 files to 4. Behavioral fixes:
- redact Coder paths, URLs, and hostnames in shared bundles
- lstat in readRecentFile so a planted symlink can't pull host files in
- create the temp zip with the source's mode (no umask window, no chmod
  failure path that deletes the otherwise-valid bundle)
- pick the active SSH log only from the current window, never fall back
- drop the literal extension-id check so rebranded forks work; anchor
  the session-name regex
- collect Remote-SSH logs from exthost dirs (the path-branch was dead)
  and proxy logs named bare <pid>.log
- preserve the active proxy log's real filename and dedup it against
  the dir scan
- stable lexicographic tie-break in newestLog
- suppress ENOENT warnings during rotation-racey recursive walks

Structural cleanup: replace package.json setting discovery with an
explicit allowlist, merge vscodeLogs.ts and diagnostics.ts into
logFiles.ts, fuse the per-window extension and Remote-SSH walks, drop
the readDir overload and the dead collectExtensionLogs fallback.
- Fix sort comparator equality case in collectWindowLogDirs (CRF-1)
- Drop readWindowDir; reuse exported readDirents (CRF-2)
- Route active proxy log through readLogFile so it gets the lstat
  symlink guard and a path-bearing warn message (CRF-4, CRF-10)
- Add coder.experimental.oauth, coder.telemetry.level,
  coder.telemetry.local to COLLECTED_SETTINGS (CRF-5)
- Rename logFiles/writeBundleWithLogs to diagnosticFiles/
  writeBundleWithDiagnostics and update log copy (CRF-6)
- Add JSDoc on collectVsCodeDiagnostics and collectSettingsFile (CRF-7)
Address PR #971 CRF-8: extract the Remote-SSH log layout knowledge
(extension exthost dirs, `output_logging_` prefix, `Remote - SSH`
filename fragment) into `sshExtension.ts` as predicates and consume
them from both `sshProcess.ts` and `supportBundle/logFiles.ts`. A
future VS Code log layout change now touches one place.
@EhabY EhabY force-pushed the feat/support-bundle-diagnostics branch from 5386867 to 162b611 Compare May 26, 2026 16:27
@EhabY
Copy link
Copy Markdown
Collaborator Author

EhabY commented May 26, 2026

/coder-agents-review

Copy link
Copy Markdown

@coder-agents-review coder-agents-review Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All R1 findings resolved. The CRF-8 fix (shared predicates in sshExtension.ts) is verified clean: both sshProcess.ts and logFiles.ts now consume from one location, no duplicate literals remain in predicate logic. The settings allowlist is in sync with package.json (26/26 coder.* keys). The readLogFile factoring correctly extends the symlink guard to the active proxy log with an explicit comment on the age cutoff bypass.

R3 panel (6 reviewers, Netero clean): 2 new P3 findings, both from Meruem.

"Extension defaults are defined in the public package.json manifest and are identical for every installation. They contain no user data." -- Meruem, on redacting defaultValue

2 P3.

Body-level observations:

  • setAge test helper is still duplicated verbatim across files.test.ts:28 and logFiles.test.ts:29. Minor, but consistently flagged across rounds. (Bisky, Robin)
  • collectWindowLogDirs scans all session directories without a directory-level age filter. Individual files are filtered by the 3-day cutoff, so this is overhead, not correctness. VS Code cleans old sessions, and the extLogs.size === 0 short-circuit limits downstream work. (Meruem)

🤖 This review was automatically generated with Coder Agents.

Comment thread src/supportBundle/files.ts
Comment thread src/supportBundle/settings.ts Outdated
EhabY added a commit that referenced this pull request May 26, 2026
Address PR #971 review findings:
- CRF-12: tail-truncate log files over 50 MB in readLogFile to prevent
  OOM during rezip when a long-lived session has a multi-GB debug log
- CRF-13: passthrough `defaultValue` in maybeRedact so package.json
  defaults (public, no user data) stay visible for triage
EhabY added a commit that referenced this pull request May 26, 2026
Address PR #971 review findings:
- CRF-12: tail-truncate log files over 50 MB in readLogFile to prevent
  OOM during rezip when a long-lived session has a multi-GB debug log
- CRF-13: passthrough `defaultValue` in maybeRedact so package.json
  defaults (public, no user data) stay visible for triage
@EhabY EhabY force-pushed the feat/support-bundle-diagnostics branch from c1d6bca to f124bf0 Compare May 26, 2026 17:22
Address PR #971 review findings:
- CRF-12: tail-truncate log files over 50 MB in readLogFile to prevent
  OOM during rezip when a long-lived session has a multi-GB debug log
- CRF-13: passthrough `defaultValue` in maybeRedact so package.json
  defaults (public, no user data) stay visible for triage
@EhabY EhabY force-pushed the feat/support-bundle-diagnostics branch from f124bf0 to 7e8a79d Compare May 26, 2026 17:22
@EhabY
Copy link
Copy Markdown
Collaborator Author

EhabY commented May 26, 2026

/coder-agents-review

Copy link
Copy Markdown

@coder-agents-review coder-agents-review Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All 13 findings resolved across 4 rounds. CRF-12 (50MB size cap with tail-truncation) and CRF-13 (defaultValue passthrough) verified fixed in 7e8a79d. Netero R4 clean. CI green (13/13).

This PR is solid. The module split is clean, the test coverage is thorough (33 tests, real filesystem I/O, real zip round-trips), the redaction boundary is well-designed with an explicit allowlist, and every finding from 4 review rounds was addressed with proportional fixes.

🤖 This review was automatically generated with Coder Agents.

@mtojek mtojek self-requested a review May 27, 2026 08:05
Copy link
Copy Markdown
Member

@mtojek mtojek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nothing blocking, well done!

Comment on lines +75 to +82
try {
await fs.rm(outputBundlePath, { force: true });
} catch (cleanupError) {
logger.warn(
`Could not clean up partial bundle at ${outputBundlePath}`,
cleanupError,
);
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Cleanup sounds to me like "finally" step.

`Adding ${diagnosticFiles.size} VS Code diagnostic file(s) to support bundle`,
);

const outputBundlePath = vscodeBundlePath(zipPath);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: should we append ".incomplete" or something to indicate that the artifact is pending renaming?

);
}

function newestLog(logs: CollectedFile[]): CollectedFile | undefined {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm... should we check logs earlier than return undefined here?

* and a redacted `coder.*` / `remote.*` settings snapshot. Keys are
* zip-relative paths under `vscode-logs/`.
*/
export async function collectVsCodeDiagnostics(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

readability and ordering: should we move exported functions to the top and let a developer just read the flow from top to the bottom?

return files;
}

async function collectVsCodeWindowLogs(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need special support for Windows FS?


// Paths, hostnames, URLs, and command strings: anything user-supplied that
// could identify a machine or deployment in a shared bundle.
const REDACTED_SETTINGS: ReadonlySet<string> = new Set([
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curious if we should make redacting configurable, sometimes these options can be crucial for root cause analysis

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.

Capture more diagnostic context in support bundle

2 participants