Skip to content
| Marketplace
Sign in
Visual Studio Code>Other>.NET DiagnosticsNew to Visual Studio Code? Get it now.
.NET Diagnostics

.NET Diagnostics

pedrosakuma

| (0) | Free
Live runtime counters, GC pauses, and point-in-time CPU captures for .NET processes using dotnet-diagnostics-cli.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

.NET Diagnostics for VS Code

This desktop/workspace-host extension provides a live runtime-counters and GC-pauses panel, plus a point-in-time CPU capture, backed by the Core-owned EventPipe/CPU-sampling sessions in dotnet-diagnostics-cli. It does not collect diagnostics in TypeScript and does not use the MCP server as a data transport.

Prerequisites

  • VS Code 1.96 or newer with a Node.js extension host.
  • dotnet-diagnostics-cli built from this repository and a compatible .NET 10 runtime, or a self-contained CLI executable for the host platform.
  • Permission to attach to the selected process's diagnostic IPC endpoint. The CLI must run as the same OS user as the target. Linux remote-process privilege requirements remain those documented by the CLI/Core.

Install the CLI explicitly; the extension never installs or updates tools:

dotnet tool install -g dotnet-diagnostics-cli --version '>=0.29.0'

The extension requires CLI 0.29.0 or later (JSONL protocol version 2). Older CLIs are rejected with a protocol mismatch error; update with dotnet tool update -g dotnet-diagnostics-cli.

The extension adds a .NET Diagnostics icon to the Activity Bar. Open its Live Diagnostics view and select Start Live Counters, or use the same command from the Command Palette. Choose a discovered process, then use the panel's Stop/Start controls. One streaming session now carries both the live counters chart and a GC pauses table (timestamp, generation, reason, type, pause duration, plus a running pause count and total paused time) — both signals start and stop together. The extension runs dotnet-diagnostics-cli processes --json for discovery and starts dotnet-diagnostics-cli stream --protocol jsonl for live samples. Stdout is parsed only as protocol frames. The CLI path can be set in the machine-scoped dotnetDiagnostics.cliPath setting; the extension host must be able to execute it. Runtime, missing-tool, and protocol-version errors are shown with actionable guidance.

Use Capture CPU Now (tree-view action or Command Palette command dotnetDiagnostics.captureCpu) to take a single point-in-time CPU sample of the selected process. Unlike the counters/GC timeline, a capture is a one-shot snapshot: it reuses the panel's active streaming connection if one is open, or opens (and then closes) a short-lived CLI connection otherwise, and renders its own top-hotspot table (module, method, inclusive/exclusive sample counts) that is replaced by the next capture rather than appended to a history. A capture does not start or stop the live counters/GC session, and it is not compared against any baseline.

Use Capture Heap Snapshot (tree-view action or Command Palette command dotnetDiagnostics.captureHeap) to take a single point-in-time heap snapshot. Unlike CPU sampling, this capture requires choosing a source: Live (ClrMD via ptrace) or GC Dump (EventPipe). Both sources are classified High risk / Acknowledge in Core's invocation-safety registry (CPU sampling is only Moderate), so after picking a source the extension shows a native modal describing its impact — a live walk attaches with ptrace, suspends the target, and exposes heap type and object-graph metadata; a GC dump induces a managed GC and exposes aggregate heap type metadata; both may expose possibly confidential data — and only sends the capture request once you select Acknowledge and Capture. The result panel shows the top types by total bytes (type, instance count, bytes), the suspend duration for live captures, and any concerning GC-dump completion flags (e.g. timed out, reader failed) for gcdump captures; each capture replaces the previous rendering. A live heap walk needs the same ptrace/CAP_SYS_PTRACE access as other live memory readers (see AGENTS.md's "🪪 CAP_SYS_PTRACE for live memory readers" section) and fails with an actionable permission-denied message when that access is unavailable. A GC dump instead goes through the diagnostic IPC channel but induces a blocking Gen2 GC pause on the target while it runs.

Use Capture Thread Snapshot (tree-view action or Command Palette command dotnetDiagnostics.captureThreadSnapshot) to take a single point-in-time snapshot of the selected process's managed threads. Unlike heap capture, there is only one source: a live ClrMD attach (the CLI's offline --dump-file option does not apply to a live VS Code panel), so no source QuickPick is shown. It is classified High risk / Acknowledge in Core's invocation-safety registry, the same tier as heap's live source, so the extension shows a native modal before sending the request — explaining that a live thread snapshot attaches with ptrace, briefly suspends the target, and exposes stack, type, and method names, some of which may be confidential — and only sends the capture request once you select Acknowledge and Capture. The result panel shows each thread's managed thread id, state (flagged when likely blocked), inferred wait reason, and its top stack frame, bounded to a summary-first table; each capture replaces the previous rendering. A live thread snapshot needs the same ptrace/CAP_SYS_PTRACE access as the heap capture's live source (see AGENTS.md's "🪪 CAP_SYS_PTRACE for live memory readers" section) and fails with an actionable permission-denied message when that access is unavailable.

Follow-up drilldown views. After a heap or thread capture succeeds, the extension issues follow-up query requests against the capture's handle (sequentially, over the same streaming connection) and renders each result as its own collapsible section below the summary table; one failing view shows an inline error without blocking the others.

  • Heap (7 always queried): roots-by-kind, finalizer-queue, fragmentation, gchandles, async, timers, alc. Four more are opt-in via a multi-select QuickPick shown before a live capture (all unchecked by default): Static fields (static-fields), Delegate targets (delegate-targets), Retention paths (retention-paths) and Retained exceptions (retained-exceptions). The gcdump source skips the picker and the follow-up views, since the CLI rejects every drilldown view for it.
  • Thread snapshot (4): deadlocks (open by default and highlighted — an inferred wait-for cycle), unique-stacks, wait-chains, threadpool. thread-statics needs an exact type name, so it is never queried automatically: after a thread snapshot, type the exact type name into the Query thread statics box and press the button (an empty name is rejected in the panel; one query runs at a time, and the result is capped server-side with explicit omitted counts).
  • Analyze Dump File runs the same heap/thread views, with the same opt-in picker shown after you choose the file.

Drilldown results use purpose-built summaries, metric cards, tables, and expandable chains rather than a generic JSON dump. The same renderer is used for live captures and dump analysis; it keeps provenance and evidence limitations visible, labels inferred deadlocks as candidates, and treats retained exception messages as potentially sensitive application data. Unknown future views use a compact key/value fallback. Heap and thread object addresses are serialized as hexadecimal strings so JavaScript preserves all 64 bits for future address-based navigation. Address-targeted views (object, gcroot, objsize, duplicate-strings) are not exposed through the streaming protocol yet. These views require a CLI build from #1116 or later; retained-exceptions and thread-statics require a CLI build from #1126 or later, and an older CLI rejects the new capture option or query and surfaces it as an unavailable view.

Use Analyze Dump File (tree-view action or Command Palette command dotnetDiagnostics.analyzeDumpFile) to inspect heap types and threads/locks from a process dump file that already exists on disk. This opens a native file picker (no extension filter — dumps can be .dmp, .dump, or extensionless) and, once you choose a file, a new, dedicated webview panel titled after the dump's file name — separate from the live counters panel, because that panel's entire model (selected target, start/stop session) assumes a live PID, and a dump file has none. The panel opens a short-lived capture-only CLI connection and fires both a heap-from-dump and a thread-snapshot-from-dump request against it, rendering a heap top-types table (type, instance count, bytes, plus the dump's file size and any analysis warnings) and a thread/lock table (thread id, state, inferred wait reason, top stack frame) as each result arrives; the connection stays open until the panel is closed so on-demand drilldown queries can reuse the thread snapshot. Dump-sourced heap and thread-snapshot analysis is classified Moderate risk / Warn in Core's invocation-safety registry — not the High risk / Acknowledge tier of their live counterparts — because there is no live attach or target suspension involved, only offline parsing of a file already on disk. Matching CPU sampling's existing no-modal posture, this command proceeds straight from the file picker to analysis with no risk-acknowledgement modal. This command only analyzes an existing dump file — it does not capture/generate a new process dump, and it does not support interactive gcroot/object-graph drilldown by address; both remain out of scope for this command.

Live streaming requires a CLI build that supports stream --protocol jsonl and the multi-kind kinds/capture protocol (CLI builds from this repository starting with #1099); the heap capture kind requires a CLI build from #1110 or later, and the thread-snapshot capture kind requires a CLI build from #1112 or later. Analyzing a dump file requires a CLI build from #1114 or later, which adds the dump heap-capture source and the dumpFile field accepted by both the heap and thread-snapshot capture kinds. A CLI installed from an older package may still support process discovery (or CPU/heap capture) but reject an unrecognized capture kind or field; update it or point dotnetDiagnostics.cliPath at a compatible executable. The extension fails with a concise compatibility message instead of displaying CLI help output in the counters panel.

The counters chart and GC pauses table only keep a rolling trailing window of history, not the full session — matching how other real-time diagnostics panels (e.g. VS Code's own vscode-js-profile-flame real-time view) bound their visible window instead of rendering an unbounded timeline. The window length is controlled by the window-scoped dotnetDiagnostics.liveView.historyDurationSeconds setting (default 120 seconds); changing it takes effect immediately in any already-open panel. The running GC pause count and total paused time in the headline remain session-wide totals — only the chart points and table rows are windowed.

Host support

The extension runs in VS Code desktop Node.js hosts on Windows, macOS, and Linux, including workspace extension hosts in Remote SSH, WSL, and Dev Containers. The CLI must be installed and runnable in that same workspace host environment. Web extension hosts are not supported because they cannot spawn the CLI child process. Exact OS/architecture support follows the CLI's published RID matrix.

Development

npm install
npm test

Open this folder in VS Code and press F5 to launch an Extension Development Host. The package manifest is scoped to the workspace/machine; no executable path can be supplied by workspace settings.

Releasing

The extension is versioned independently from the CLI and the .NET packages. Bump version in package.json (and package-lock.json) and push a matching ext-vscode-v<version> tag, for example:

npm version --no-git-tag-version 0.2.0
npm test
git tag ext-vscode-v0.2.0
git push origin ext-vscode-v0.2.0

The VS Code Extension Release workflow verifies that the tag matches the package version, runs the extension tests, packages a VSIX, uploads it as a workflow artifact, and publishes it to the Visual Studio Marketplace. Configure the repository Actions secret VSCE_PAT with a publisher token that has Marketplace management/publish access. The normal CI workflow continues to test extension changes on pushes to main and pull requests; it does not publish from those builds.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft