Skip to content

feat: linkify Java stack traces in text documents (#1654)#1657

Draft
wenytang-ms wants to merge 6 commits into
mainfrom
feature/stacktrace-console-1654
Draft

feat: linkify Java stack traces in text documents (#1654)#1657
wenytang-ms wants to merge 6 commits into
mainfrom
feature/stacktrace-console-1654

Conversation

@wenytang-ms

@wenytang-ms wenytang-ms commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Closes #1654 (draft for design review — not ready to merge).

What & why

Developers frequently receive Java stack traces from log files, CI failures, bug reports, chat messages, and production logs. Eclipse ("Java Stack Trace Console") and IntelliJ ("Analyze Stack Trace") both let you take such an external trace and click each frame to jump to source — without a running debug session. VS Code has no equivalent today: our existing linkifier only works on text that has already flowed through the integrated terminal.

This PR adds that missing surface.

Approach (passive-first, reuse-first)

  • Automatic by default — no command required. A DocumentLinkProvider (src/stackTraceLinkProvider.ts) linkifies stack frames on its own, mirroring how registerTerminalLinkProvider is already wired in extension.ts.
  • Activated on Java workspaces. activationEvents now includes workspaceContains:**/*.java, so the extension wakes up as soon as a Java project is opened — the user does not have to open a .java file first or run any command.
  • Gated on Java language server readiness. The provider is only registered once redhat.java reaches ServerMode.STANDARD (via onDidServerModeChange), mirroring initializeCodeLensProvider. Frame resolution goes through jdtls (resolveSourceUri), which needs a fully-loaded workspace; registering earlier would produce links that cannot resolve. Commands stay registered immediately, so Java: Analyze Stack Trace is always available and any already-open doc gets linkified the moment the server becomes ready.
  • Backend is reused as-is. Each frame resolves through the existing, session-independent resolveSourceUri -> vscode.java.resolveSourceUri. Zero backend changes.
  • Lazy resolution. provideDocumentLinks only does a cheap per-line regex and emits a command: link; the (more expensive) source resolution runs only when a link is clicked.
  • Optional convenience command Java: Analyze Stack Trace opens a scratch document, prefilled from the clipboard when it looks like a trace.

Scope of matching (kept narrow on purpose)

DocumentSelector = untitled + log language + **/*.log. This covers the two natural flows (paste into a new tab / open a .log) without scanning every plaintext file the user opens.

Safety

  • Navigation only opens URIs with an allowlisted scheme (file / jdt) returned by the language server.
  • Per-line length cap (1000), max-links cap (2000), and a clipboard scan cap (20000) guard against ReDoS on the nested-quantifier regex and against pathological large logs.
  • Telemetry stays content-free (operation name only — never the pasted text).

Telemetry

A single content-free event tracks usage, mirroring the existing handleJavaTerminalLink proxy metric:

  • navigateToJavaStackFrame — emitted when a user clicks a linkified frame. No dimensions — just a click count for adoption. Pasted trace text / class names / paths are never recorded.

The Java: Analyze Stack Trace command is already auto-instrumented via instrumentOperationAsVsCodeCommand, so no extra event is added for it.

Not in scope (deliberately)

Thread-dump analysis, de-obfuscation/unscramble, dSYM, and multi-project same-named-class disambiguation (backend currently returns the first match). These are IntelliJ super-set features / a separate backend change and can be follow-ups.

How to test

  1. Open any Java project and let the language server finish importing (reach Standard mode).
  2. Paste flow: open a new untitled tab, paste a Java stack trace (e.g. at com.foo.Bar.baz(Bar.java:42)); each frame becomes a clickable link -> jumps to the source line.
  3. File flow: open a .log containing a trace -> frames are linkified in place.
  4. Command flow: copy a trace, run Java: Analyze Stack Trace from the palette -> opens a prefilled, already-clickable document.

Open questions for reviewers

  • A loose .log opened with no Java project won't linkify (and couldn't resolve anyway). Do we also want onLanguage:log activation to cover that edge, accepting activation in non-Java windows?
  • Command entry point: keep the untitled scratch doc, or a named persistent document closer to Eclipse's "Console" mental model?

Add a DocumentLinkProvider that makes Java stack frames clickable in untitled documents and .log files, so a trace pasted from a log/CI/bug report can be navigated to source without an active debug session. Reuses the session-independent resolveSourceUri backend; frames are resolved lazily on click, with a source-scheme allowlist and length/ReDoS guards. Also adds an optional 'Java: Analyze Stack Trace' command that opens a scratch document prefilled from the clipboard.
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

… usage

Add three content-free telemetry events (with __GDPR__ annotations) forming an adoption funnel: provideJavaStackTraceLinks (reach, deduped once per document), navigateToJavaStackFrame (click engagement, with documentSource + resolution outcome), and analyzeJavaStackTrace (command entry usage, with prefilledFromClipboard). All dimensions are categorical; the pasted trace text is never recorded. Also bound clipboard scanning length.
…events

Simplify to one usage signal (navigateToJavaStackFrame with a documentSource dimension), mirroring the existing handleJavaTerminalLink pattern. Drop the per-document reach event (and its WeakSet) and the manual command event - command invocations are already auto-instrumented by instrumentOperationAsVsCodeCommand.
…ault

Add workspaceContains:**/*.java so the passive DocumentLinkProvider is registered as soon as a Java project is opened - without waiting for the user to open a .java file or run a command. This matches exactly the scope where resolveSourceUri can resolve frames to source, so the feature is automatic wherever it can deliver value.
Frame resolution (resolveSourceUri) requires a fully-loaded workspace, so registering the document link provider before jdtls is ready produces links that cannot resolve. Defer provider registration until ServerMode.STANDARD via redhat.java's onDidServerModeChange, mirroring initializeCodeLensProvider. Commands stay registered immediately.
…lick count

The single navigateToJavaStackFrame event is enough to measure adoption; the documentSource breakdown is not needed. Remove the dimension, the IStackFrameLinkArgs field, and the categorizeDocumentSource helper.
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.

[Feature Request] Standalone "Java Stack Trace Console" (paste-and-navigate stack traces, independent of an active debug session)

1 participant