Add VS Code attach debugger resource action#18602
Conversation
…e names
Replace the implicit `microsoft-aspire.aspire-vscode/` extension-id prefix
that VS Code's `TelemetryLogger` adds to every telemetry event with an
explicit, dashboard-native namespace:
* Extension-emitted events → `aspire/vscode/<area>/<event>`
* Dashboard passthrough → `aspire/dashboard/<route>`
Route every send through `reporter.sendDangerousTelemetryEvent` /
`sendDangerousTelemetryErrorEvent`. Those bypass the prefix-applying
`TelemetryLogger` but also bypass the reporter's built-in opt-in gate, so
gating is enforced explicitly via `reporter.telemetryLevel`:
* `'all'` → regular and error events emit
* `'error'` → only error events emit
* `'crash'`/`'off'` → nothing emits
Renames cover the registry (`extension/src/utils/telemetryRegistry.ts`),
all 22 callsites, the data classification catalog
(`extension/telemetry.json`), and every test fake. Existing event
schemas / property unions are unchanged; only the wire names move.
Adds proof tests in `extension/src/test/telemetry.test.ts` pinning:
* `sendTelemetryEvent` routes through `sendDangerousTelemetryEvent`
with the registry-declared name and no extension-id prefix
* `sendTelemetryErrorEvent` routes through the dangerous error channel
* dashboard-namespaced events emit verbatim
* `'off'` / `'crash'` suppress everything; `'error'` allows only error
events
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fail test telemetry immediately if the regular sendTelemetryEvent path is used, proving the extension bypasses VS Code's extension-id prefix channel. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add explicit property value sanitization and restore common telemetry dimensions before using the dangerous telemetry send path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a tree context action for running .NET project resources that starts a CoreCLR attach session by process name, with stale-resource and C# debugger gating. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 18602Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 18602" |
There was a problem hiding this comment.
Pull request overview
This PR adds the first VS Code extension lane for #18538: a right-click Attach debugger action on running .NET project resources in the Aspire panel. It builds a CoreCLR attach debug configuration that targets the project's process by processName (best-effort resolving <AssemblyName> from the project file), rather than executable.pid, because DCP reports the dotnet run launcher PID rather than the child app process. The action is gated on a running top-level Project resource with a dotnet executable and a .csproj/.fsproj/.vbproj path, and only when the C# extension is installed; it re-resolves the latest resource before attaching so stale/ambiguous/missing resources fail closed with a warning.
Bundled alongside the feature is a broad telemetry overhaul: every event is renamed to its final wire name (aspire/vscode/... and aspire/dashboard/...) and routed through sendDangerousTelemetryEvent/sendDangerousTelemetryErrorEvent to bypass VS Code's automatic <extensionId>/ prefix, with manual opt-in gating (telemetryLevel), manual common properties, and explicit value sanitization.
Changes:
- Add
aspire-vscode.attachDebuggerToResourcecommand, menu contribution (canAttachDebuggercontext value), attachability helpers, and the attach execution flow with latest-resource re-resolution. - Rename all telemetry events to final wire names and route them through the "dangerous" send path with explicit gating/sanitization and manually-added common properties.
- Add localized strings and extensive unit tests for both the attach flow and the telemetry changes.
Show a summary per file
| File | Description |
|---|---|
extension/src/views/AspireAppHostTreeProvider.ts |
Core attach logic: attachability helpers, process-name derivation, attachDebuggerToResource, latest-resource resolution; propagates appHostPath through tree items. |
extension/src/extension.ts |
Registers the new attach command; renames the extension/activated telemetry event. |
extension/package.json |
Contributes the command, hidden palette entry, and view/item/context menu item; reorders action groups. |
extension/package.nls.json / extension/src/loc/strings.ts / extension/loc/xlf/aspire-vscode.xlf |
Adds/regenerates localized strings for the attach action. |
extension/src/utils/telemetry.ts |
Switches to dangerous-send path, adds manual gating, common properties, and value sanitization; hard-codes telemetry client version. |
extension/src/utils/telemetryRegistry.ts |
Renames event schema keys to final aspire/vscode/... and aspire/dashboard/... wire names; documents the convention. |
extension/telemetry.json |
Updates classification inventory keys to the new wire names. |
extension/src/dcp/DashboardTelemetryPassthrough.ts / AspireDcpServer.ts / AspireDebugSession.ts / AppHostLaunchService.ts / AppHostsViewTelemetry.ts / meaningfulEngagement.ts / appHostDiscovery.ts / workspace.ts / interactionService.ts |
Update event-name call sites and passthrough comments to the new namespaces. |
extension/src/test/*.test.ts, extension/src/test-e2e/packageSurface.e2e.test.ts |
Extensive tests for the attach flow, telemetry gating/sanitization/naming, and the manifest/surface contributions. |
Review details
- Files reviewed: 29/29 changed files
- Comments generated: 3
- Review effort level: Medium
| // EVENT NAMING CONVENTION: | ||
| // Extension-emitted events are namespaced under `aspire/vscode/...` and | ||
| // dashboard passthrough events are namespaced under `aspire/dashboard/...`, | ||
| // matching what other Aspire dashboard hosts (Visual Studio, C# Dev Kit) | ||
| // emit. The names here are the FINAL wire names — the helpers in | ||
| // `telemetry.ts` deliberately bypass VS Code's automatic | ||
| // `<extensionId>/<eventName>` prefix (added by `vscode.env.createTelemetryLogger`) | ||
| // so this convention is what reaches the telemetry backend. |
| }); | ||
|
|
||
| test('attachDebuggerToResource uses AssemblyName when the project file declares one', async () => { | ||
| const directory = fs.mkdtempSync(path.join(process.cwd(), '.assembly-name-test-')); |
| 'common.os': os.platform(), | ||
| 'common.nodeArch': os.arch(), | ||
| 'common.platformversion': os.release().replace(/^(\d+)(\.\d+)?(\.\d+)?(.*)/, '$1$2$3'), | ||
| 'common.telemetryclientversion': '1.5.1', |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
| .replace(/([?&]sig=)[^&\s"',;}]+/gi, '$1<redacted>') | ||
| .replace(/\b(authorization\s*:\s*bearer\s+)[^\s"',;}]+/gi, '$1<redacted>') | ||
| .replace(/\b(bearer\s+)[A-Za-z0-9._~+/=-]+/gi, '$1<redacted>') | ||
| .replace(/\b[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\b/gi, '<guid>'); |
| // telemetry pipeline (consistent with the synchronous launch-failure path | ||
| // above and the dashboard fault path in DashboardTelemetryPassthrough). |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
I tried to place these as inline tracking comments, but GitHub rejected new inline comments because there is already a pending review draft for this user on the PR. I kept the tracking here instead while the branch was fixed:
These were fixed before the later Windows punctuation redaction follow-up. This is a top-level tracking comment, so there is no review thread to resolve; final tracking is in #18602 (comment). |
|
Pushed Validation on the live head passed locally: Remaining non-agent gates: live CoreCLR attach/manual readiness pass, plus telemetry/reviewer sign-off for the |
…ed home usernames
The attachDebuggerToResource command handles three user-visible guard failures
(stale/missing resource, resource no longer attachable, and missing C# extension)
by showing a warning and returning. Because the command is registered through
withCommandTelemetry, returning void recorded these as a success outcome. Return a
handled-failure object ({ success: false, errorKind }) so each is recorded as an
error outcome with a specific error_kind, without triggering VS Code's generic
command-failed notification. The genuine startDebugging-declined path still throws.
Also fix sanitizeTelemetryValue home-directory redaction, which stopped at the
first whitespace and leaked the rest of a username that contains spaces (and the
following path). Redact the full username segment up to the next same-type path
separator for both POSIX and Windows homes, while leaving unrelated following path
segments intact.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Ignore AssemblyName values that depend on unevaluated MSBuild conditions when building VS Code attach configurations. Preserve the project filename fallback when no unconditional literal AssemblyName is available. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep the attach debugger AssemblyName tests out of the repository working tree so aborted runs do not leave .assembly-name-test-* directories behind and concurrent test runs avoid repo-local temp path collisions. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Keep the last unconditional simple AssemblyName when building the CoreCLR attach process name, matching MSBuild property override ordering, and cover the regression in the attach debugger tests. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Restore VS Code common telemetry dimensions on the dangerous send path and make the current-home sanitizer test use USERPROFILE on Windows. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Make the optional VS Code product metadata lookup best-effort so malformed product.json cannot fail extension activation. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Summary
Adds a VS Code Attach debugger resource action for running .NET project resources in the Aspire view.
The action builds a CoreCLR attach configuration from the selected resource, routes through the existing debugger service, and keeps the command hidden unless the current CLI/extension capability path can support it.
Fixes #18538.
Changes
AssemblyNameattributes.operation_idstays useful across the dashboard route.startDebuggingreturningfalseand rejecting.Validation
PATH="$PWD/.dotnet:$PWD/.dotnet/x64:$PATH" ./extension/build.shcd extension && corepack yarn run compile-tests && corepack yarn run lint/tmp/aspire-pr18602-test: 1136 passing, 1 pending.packageSurfaceE2E: 7/7 passed. Evidence:/Users/adamratzman/.copilot/session-state/4263d434-e095-4dc4-8bb2-7c57d71bc533/files/pr18602-e2e/all/.cd /tmp/a18602v/extension && yarn run compile-tests && yarn run compile && yarn run lint && yarn run unit-test --run out/test/appHostTreeView.test.js --grep 'attachDebuggerToResource ignores conditional AssemblyName values': 1 passing.ecb3b65f25bc9676777a05c83df507465251d528: 328 success, 3 skipped, 0 pending, 0 failures.Manual follow-up
Still draft until I do a live CoreCLR attach pass from a running AppHost resource. The current proof covers the real Extension Host/package surface and unit-level debugger configuration, but not the full live debugger attach loop.