Add tracked browser logs and network capture#16310
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 16310Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 16310" |
Add a child browser logs resource that can launch tracked Chromium sessions, stream console and network request events, and expose the builder through polyglot export.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
5c31105 to
eab2c02
Compare
Add typed CDP protocol parsing, preserve connection failure reasons in resource logs, and strengthen reconnect handling for tracked browser sessions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
mitchdenny
left a comment
There was a problem hiding this comment.
5 issues found (1 security, 2 bugs, 1 race condition, 1 formatting).
Fix indentation of <remarks> block in BrowserLogsBuilderExtensions.cs to match surrounding XML doc tags. Thread TimeProvider through RunningSession and its factory so timeout calculations in WaitForBrowserEndpointAsync and TryReconnectAsync use the injected provider instead of TimeProvider.System/DateTime.UtcNow. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Extract the running-session lifecycle, CDP websocket transport, and event/diagnostic logging into focused files so the browser connection layers can be tested in isolation. Also add targeted comments describing the browser and CDP quirks these layers handle. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the global certificate-bypass flag from tracked browser launches and make session-manager disposal wait for completion observers without publishing shutdown updates through torn-down services. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds a new Aspire.Hosting capability (WithBrowserLogs(...)) that attaches a *-browser-logs child resource to endpoint-capable resources. The child resource can launch and track Chromium-based browser sessions (CDP), streaming console/errors/exceptions and network lifecycle activity into the dashboard logs, and surfaces live “Browser sessions” metadata/properties for downstream tooling.
Changes:
- Introduces browser log resources, session orchestration, CDP websocket transport, protocol parsing, and event-to-log projection in
src/Aspire.Hosting. - Adds unit tests for resource wiring/config refresh, diagnostics logging, protocol parsing, target selection, session lifecycle, and network log formatting.
- Updates polyglot AppHost/codegen snapshots + capability scanning, and adds localized command strings + a playground demo to validate the end-to-end experience.
Show a summary per file
| File | Description |
|---|---|
| tests/Aspire.Hosting.Tests/BrowserLogsSessionManagerTests.cs | Adds tests for endpoint parsing, user-data-dir resolution, target selection, and diagnostics log formatting. |
| tests/Aspire.Hosting.Tests/BrowserLogsProtocolTests.cs | Adds focused protocol parsing tests for events and command error reporting. |
| tests/Aspire.Hosting.Tests/BrowserLogsBuilderExtensionsTests.cs | Adds extensive tests for resource wiring, config precedence/refresh, session tracking, and network log projection. |
| tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.ts | Updates generated TS SDK snapshot to include withBrowserLogs(...) capability and options. |
| tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Snapshots/HostingContainerResourceCapabilities.verified.txt | Updates capability list snapshot to include Aspire.Hosting/withBrowserLogs. |
| tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/AtsTypeScriptCodeGeneratorTests.cs | Adds ATS scanner test validating the new capability signature. |
| tests/Aspire.Hosting.CodeGeneration.Rust.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.rs | Updates generated Rust SDK snapshot to include with_browser_logs(...). |
| tests/Aspire.Hosting.CodeGeneration.Python.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.py | Updates generated Python SDK snapshot to include with_browser_logs(...) and kwargs support. |
| tests/Aspire.Hosting.CodeGeneration.Java.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.java | Updates generated Java SDK snapshot to include withBrowserLogs(...) and options DTO. |
| tests/Aspire.Hosting.CodeGeneration.Go.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.go | Updates generated Go SDK snapshot to include WithBrowserLogs(...). |
| src/Aspire.Hosting/Resources/xlf/CommandStrings.zh-Hant.xlf | Adds localization entries for the “Open tracked browser” command. |
| src/Aspire.Hosting/Resources/xlf/CommandStrings.zh-Hans.xlf | Adds localization entries for the “Open tracked browser” command. |
| src/Aspire.Hosting/Resources/xlf/CommandStrings.tr.xlf | Adds localization entries for the “Open tracked browser” command. |
| src/Aspire.Hosting/Resources/xlf/CommandStrings.ru.xlf | Adds localization entries for the “Open tracked browser” command. |
| src/Aspire.Hosting/Resources/xlf/CommandStrings.pt-BR.xlf | Adds localization entries for the “Open tracked browser” command. |
| src/Aspire.Hosting/Resources/xlf/CommandStrings.pl.xlf | Adds localization entries for the “Open tracked browser” command. |
| src/Aspire.Hosting/Resources/xlf/CommandStrings.ko.xlf | Adds localization entries for the “Open tracked browser” command. |
| src/Aspire.Hosting/Resources/xlf/CommandStrings.ja.xlf | Adds localization entries for the “Open tracked browser” command. |
| src/Aspire.Hosting/Resources/xlf/CommandStrings.it.xlf | Adds localization entries for the “Open tracked browser” command. |
| src/Aspire.Hosting/Resources/xlf/CommandStrings.fr.xlf | Adds localization entries for the “Open tracked browser” command. |
| src/Aspire.Hosting/Resources/xlf/CommandStrings.es.xlf | Adds localization entries for the “Open tracked browser” command. |
| src/Aspire.Hosting/Resources/xlf/CommandStrings.de.xlf | Adds localization entries for the “Open tracked browser” command. |
| src/Aspire.Hosting/Resources/xlf/CommandStrings.cs.xlf | Adds localization entries for the “Open tracked browser” command. |
| src/Aspire.Hosting/Resources/CommandStrings.resx | Adds the new command name/description resources. |
| src/Aspire.Hosting/Resources/CommandStrings.Designer.cs | Regenerates designer accessors for new resource strings. |
| src/Aspire.Hosting/IBrowserLogsSessionManager.cs | Introduces internal session manager abstraction used by the command handler. |
| src/Aspire.Hosting/BrowserLogsSessionManager.cs | Implements session orchestration + dashboard property/health projection for tracked sessions. |
| src/Aspire.Hosting/BrowserLogsRunningSession.cs | Implements per-browser lifecycle: launch, endpoint discovery, CDP connect/attach, reconnect, cleanup. |
| src/Aspire.Hosting/BrowserLogsResource.cs | Adds internal child resource model + config re-resolution for launch-time refresh. |
| src/Aspire.Hosting/BrowserLogsProtocol.cs | Adds CDP frame parsing/serialization + typed envelopes for key CDP domains. |
| src/Aspire.Hosting/BrowserLogsEventLogger.cs | Projects CDP events into consistent dashboard log lines + connection diagnostics. |
| src/Aspire.Hosting/BrowserLogsDevToolsConnection.cs | Adds CDP websocket transport, command/response correlation, and receive loop. |
| src/Aspire.Hosting/BrowserLogsBuilderExtensions.cs | Adds the public WithBrowserLogs(...) API and the dashboard command wiring/config resolution. |
| playground/BrowserTelemetry/BrowserTelemetry.Web/Scripts/index.js | Expands sample UI logic to emit console, exception, and network activity for validation. |
| playground/BrowserTelemetry/BrowserTelemetry.Web/Pages/Index.cshtml | Updates sample page UI with buttons/status area for browser logging demo. |
| playground/BrowserTelemetry/BrowserTelemetry.AppHost/BrowserTelemetry.AppHost.csproj | Adds UserSecretsId to support configuration overrides in the playground. |
| playground/BrowserTelemetry/BrowserTelemetry.AppHost/AppHost.cs | Enables browser logs in the playground by calling .WithBrowserLogs(). |
Copilot's findings
Files not reviewed (1)
- src/Aspire.Hosting/Resources/CommandStrings.Designer.cs: Language not supported
- Files reviewed: 36/37 changed files
- Comments generated: 3
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
JamesNK
left a comment
There was a problem hiding this comment.
Reviewed the new tracked browser logs feature. Found 4 issues:
- 2 bugs: missing early-exit detection during endpoint polling + stale
DevToolsActivePortfile with persistent profiles - 1 resource leak: no disposal guard in
StartSessionAsyncallows post-dispose browser process leaks - 1 hang risk: unbounded
CloseAsyncinChromeDevToolsConnection.DisposeAsynccan block shutdown indefinitely
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
JamesNK
left a comment
There was a problem hiding this comment.
Thorough review of the new browser logs feature. Very well-structured code with clean separation of concerns across the CDP transport, protocol parsing, event logging, session lifecycle, and resource state management. One resource leak issue flagged (1 bug).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
🎬 CLI E2E Test Recordings — 72 recordings uploaded (commit View recordings
📹 Recordings uploaded automatically from CI run #24783280098 |
…t routing Code-review feedback from gpt-5.4, gpt-5.3-codex, and claude-opus-4.7 on the Phase 2 foundation commits, plus a mechanical pass applying the same lens James used on the original feature PR (#16310). BrowserHostIdentity changes: - Removed ProfileDirectory from the identity. Chromium's singleton is keyed by user-data-dir, not by profile, so different profiles under the same user data root share a browser process. Profile selection is per-target, not per-host. The previous doc comment claiming otherwise was wrong. - Replaced record-struct synthesized equality (which is ordinal case-sensitive on strings) with explicit Equals/GetHashCode using StringComparer.OrdinalIgnoreCase on Windows / Ordinal elsewhere. Without this, paths that differ only in casing would create duplicate hosts on Windows. - Constructor now normalizes paths via Path.GetFullPath + TrimEndingDirectorySeparator so 'C:/foo' and 'C:\foo\' collapse to the same identity. - GetHashCode is null-safe against default(BrowserHostIdentity) since StringComparer.GetHashCode(null) throws. Protocol changes: - Documented above the new Target.* event records that the SUBJECT of these events lives in params (targetId / params.sessionId), not the envelope sessionId. The existing dispatch in BrowserLogsRunningSession filters on envelope sessionId only, so any future fanout layer that naively reuses that filter would silently drop these events. The comment makes the routing requirement unmissable. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Description
Adds
WithBrowserLogs(...)toAspire.Hostingso endpoint-capable resources can attach an internal*-browser-logschild resource. The child resource exposesopen-tracked-browser, launches a Chromium-based browser in tracked mode, and streams browser activity back into Aspire’s resource log stream.This PR includes:
BrowserLogsruntime split across builder, resource, session manager, running session, websocket transport, protocol, and event-logging components;.ExcludeFromManifest()andNameValidationPolicyAnnotation.None, so the child stays internal to the AppHost model;IConfiguration, including global and resource-scoped overrides plus launch-time re-resolution whenopen-tracked-browserruns;Browser sessionsmetadata;DevToolsActivePorthandling, post-dispose launch rejection, and failed-websocket-connect cleanup;AspireExportsupport sowithBrowserLogs(...)is emitted in the polyglot AppHost generators while the child resource remains out of manifest publishing.Process management and dataflow
flowchart LR subgraph AppHost["Aspire AppHost"] Parent["Parent endpoint resource"] Child["BrowserLogs child resource"] Command["open-tracked-browser"] SessionMgr["Session manager"] end subgraph Session["One tracked browser session"] Create["Create session-000N"] Launch["Launch browser process"] Discover["Wait for DevToolsActivePort"] Attach["Attach target + navigate URL"] Running["Running session"] Cleanup["Stop / cleanup session"] end Dashboard["Dashboard / aspire logs / aspire describe"] Clients["playwright-cli / CDP clients"] Parent --> Child Child --> Command --> SessionMgr SessionMgr --> Create --> Launch --> Discover --> Attach --> Running Running -->|logs + health + active session state| SessionMgr SessionMgr --> Dashboard SessionMgr -->|Browser sessions property<br/>cdpEndpoint / targetUrl| Clients SessionMgr --> Cleanup Cleanup -->|close browser + release temp profile| LaunchHow Aspire manages browser instances
WithBrowserLogs(...)adds one internal*-browser-logschild resource beneath an endpoint-capable parent resource.open-tracked-browserinvocation asksBrowserLogsSessionManagerto create a new tracked session.BrowserLogsSessionManagerowns per-resource concurrency, assignssession-0001,session-0002, etc., aggregates active sessions, and publishes health/properties for the child resource.BrowserLogsRunningSessionowns exactly one launched browser process plus its attached CDP target. It resolves browser/profile settings at launch time, launches the browser, readsDevToolsActivePort, reuses or creates the page target, enables the required CDP domains, and navigates to the parent resource URL.ChromeDevToolsConnectiontransports raw websocket frames,BrowserLogsProtocolparses and serializes CDP messages, andBrowserEventLoggerturns runtime/log/network events into resource log lines.Browser sessionsproperty as serialized JSON so CLI and dashboard consumers can readbrowser,browserExecutable,profile,processId,targetUrl,cdpEndpoint,pageCdpEndpoint, andtargetId.Validation
Validation included:
Aspire.Hosting.Testscoverage for resource wiring, config refresh, session behavior, protocol parsing, target selection, diagnostics logging, and websocket cleanup on failed connect attempts;withBrowserLogs(...)capability;playground/BrowserTelemetryruns confirming tracked browser launches plus real[network.*], console, and error lines inweb-browser-logs;aspire describe web-browser-logs --format jsonvalidation confirmingBrowser sessionsincludescdpEndpoint,pageCdpEndpoint,targetId, andtargetUrl;playwright-clivalidation against the BrowserTelemetry sample using the surfaced CDP metadata to attach to the tracked browser and confirm the page title/log flow;playground/BrowserTelemetry/BrowserTelemetry.AppHostafter the latest feedback fixes, including the websocket-connect cleanup fix.Checklist
<code/>elements on your triple slash comments?aspire.devissue: