Skip to content

Dashboard: preserve resource selection in telemetry pages and metric charts - #21431

Open
David Fowler (davidfowl) wants to merge 3 commits into
mainfrom
aspireagent/fix-21419-dashboard-selection
Open

David Fowler (davidfowl) wants to merge 3 commits into
mainfrom
aspireagent/fix-21419-dashboard-selection

Conversation

@davidfowl

@davidfowl David Fowler (davidfowl) commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Fixes the two remaining selection-loss review findings tracked in #21419 (follow-up to #21412).

1. Structured logs / traces lose the resource scope when telemetry arrives later.
If a resource's logs or traces page is opened before that resource has sent telemetry, the route resolves to "(All)" and the view model keeps a null ResourceKey. When telemetry later arrives, GetSelectionTelemetryKeys returns null ("use the page's resource key"), so the page lists every resource's data under the selected resource. For structured logs, the read subscription with a null key also marks unrelated resources' errors as viewed.

Fix: when new telemetry resources are reported, StructuredLogs and Traces re-resolve the route's resource if the page is still on "(All)". This sets the selected resource, resource key/keys and subscription, then refreshes the grid. Metrics already does the same in OnResourcesUpdatedAsync. Until the route resolves, structured logs uses a non-read subscription and doesn't mark errors as viewed. Other resources' errors that arrive first, or in the same batch, therefore keep their unread counts.

2. Metrics chart loses its resource in a multi-resource selection.
With api and worker selected and api's instrument chart open, changing duration or graph/table view rebuilt the URL without /resource/api, so the page dropped back to the aggregate instrument list.

Fix: for multi-selection, GetUrlFromSerializableViewModel keeps the resource name when an instrument chart is open and the resource is part of the current selection. The aggregate list and stale names still drop it.

Regression tests (all three fail on main and pass with this change):

  • StructuredLogsTests.ResourcesLayout_SelectedResourceSendsTelemetryAfterPageOpened_ShowsOnlyThatResource: only api logs are shown. worker's errors stay unviewed, both the one sent before api's first telemetry and the one sent after.
  • TracesTests.ResourcesLayout_SelectedResourceSendsTelemetryAfterPageOpened_ShowsOnlyThatResource: only api traces are shown.
  • MetricsTests.ResourcesLayout_MultiSelectionInstrumentChart_ChangingViewKeepsActiveResource: the path stays /metrics/resource/api, with the instrument, view and selection kept.

Before the fix, the Metrics test navigated to /metrics instead of /metrics/resource/api. The logs and traces tests timed out waiting for the selected resource to become api (it stayed "(All)"). The full Aspire.Dashboard.Components.Tests suite passes locally (1164/1164).

No visual/layout change, so there are no screenshots.

Fixes #21419

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
    • No

🤖 Posted by AspireAgent (AI Agent)

…harts

- Structured logs and traces resolve the route's resource again when its
  telemetry arrives, so a page opened before the resource sent telemetry
  stops showing (and marking viewed) every resource's data.
- Metrics keeps the open chart's resource in the URL for a multi-resource
  selection, so changing duration or view no longer drops back to the
  aggregate instrument list.

Fixes #21419

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 21431

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 21431"

@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The unresolved-route all-resource read subscription can irrecoverably suppress worker unread counts when worker telemetry arrives first or in the same batch, requiring a fix and regression coverage.

1 open issue
What changed in this PR

Addresses resource-selection loss tracked in #21419 following the dashboard redesign in #21412.

Changes:

  • Re-resolves resource-scoped logs and traces pages when telemetry becomes available.
  • Preserves the active metrics chart resource during option changes in multi-resource selections.
  • Adds regression tests for delayed telemetry and chart navigation.
File Description
tests/​Aspire.Dashboard.Components.Tests/​Pages/​TracesTests.cs Tests trace scoping after delayed telemetry.
tests/​Aspire.Dashboard.Components.Tests/​Pages/​StructuredLogsTests.cs Tests log scoping and unrelated unread-error preservation.
tests/​Aspire.Dashboard.Components.Tests/​Pages/​MetricsTests.cs Tests chart resource retention when switching views.
src/​Aspire.Dashboard/​Components/​Pages/​Traces.razor.cs Resolves pending route resources and refreshes traces.
src/​Aspire.Dashboard/​Components/​Pages/​StructuredLogs.razor.cs Resolves pending route resources and updates log subscriptions.
src/​Aspire.Dashboard/​Components/​Pages/​Metrics.razor.cs Retains selected chart resources in navigation URLs.

Review effort: Balanced

… unresolved

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

No active review issues block approval of the resource-selection fixes.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@github-actions

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@davidfowl
David Fowler (davidfowl) marked this pull request as ready for review October 30, 2026 08:21
David Pine (IEvangelist) added a commit that referenced this pull request Nov 4, 2026
## Description

Selecting a resource that has not sent telemetry should not unexpectedly
move users from Traces or Structured logs to Overview. Keep the current
telemetry page and let its existing empty state explain the absence of
data, matching Metrics.

UX-30 only. This updates selection URL routing in `ResourcesLayout`; it
does not change telemetry arrival handling or chart scope in #21431, or
redesign Home/Details. Selecting a single parameter still opens
Overview.

Based on freshly fetched `microsoft/aspire` upstream `main` at
`9f0961d0c7173732f45ce88d571c8b53f8059934`.

### User-facing usage

While on Traces or Structured logs, select a resource with no telemetry.
The resource selection updates without leaving the page. Traces shows
its existing "No traces" empty state. Ctrl/Cmd-click to select multiple
resources, or select all to clear the explicit selection, without
changing telemetry pages.

### Validation

- `.\restore.cmd` - passed.
- Before the production fix, the following command reproduced two
failures: Traces and Structured logs generated `/resources/cache`
instead of their telemetry URLs. Four cases passed, including Metrics
and the single-parameter exception:

  ```powershell
dotnet test --project
tests\Aspire.Dashboard.Components.Tests\Aspire.Dashboard.Components.Tests.csproj
--no-launch-profile -- --filter-method
'*.Telemetry_ChangingTheSelectionStaysOnTheCurrentTabEvenWithoutTelemetry'
--filter-method '*.Telemetry_SelectingOnlyAParameterNavigatesToOverview'
--filter-not-trait 'quarantined=true' --filter-not-trait
'outerloop=true'
  ```

- After the fix, the following command passed all 87 cases, including
no-telemetry single/multiple/no selection, parameter-only navigation,
and the rendered Traces empty state:

  ```powershell
dotnet test --project
tests\Aspire.Dashboard.Components.Tests\Aspire.Dashboard.Components.Tests.csproj
--no-launch-profile -- --filter-class '*.ResourcesLayoutTests'
--filter-not-trait 'quarantined=true' --filter-not-trait
'outerloop=true'
  ```

- `git diff --check` - passed.
- Real-browser verification against this branch's build passed using a
temporary Playwright fixture, with six interactions covering both pages
at all three viewport sizes. The fixture seeded one trace and one
structured log for `api`, and no telemetry for `cache`. It navigated
through the normal tab UI, verified the populated `api` page, then
selected `cache` at each target viewport. Assertions checked the scoped
URL, resource title, selected tab, explicit empty message, and absence
of document horizontal overflow. The fixture and browser were disposed
after capture; the capture harness is not part of this PR.

  ```powershell
dotnet test --project
tests\Aspire.Dashboard.Playwright.Tests\Aspire.Dashboard.Playwright.Tests.csproj
--no-launch-profile -- --filter-method '*.CaptureAffectedStates'
--filter-not-trait 'quarantined=true' --filter-not-trait
'outerloop=true'
  ```

### Screenshots / Recordings

Actual Chromium viewport captures from this branch, using synthetic test
resources only. Each screenshot shows `cache` selected after switching
from a resource with data. Traces remains at `/traces/resource/cache`
with **No traces found**; Structured logs remains at
`/structuredlogs/resource/cache` with **No structured logs found**.

At **390 x 844** and **768 x 1024**, selection used the responsive
resource picker: open the drawer, select `cache`, and verify it closes.
At **1440 x 900**, selection used the persistent resource pane. All six
images were visually inspected: resource scope and empty-state text
remain readable, the empty message stays within the viewport, and
document/body width equals viewport width. At mobile width, the existing
tab strip truncates trailing labels and exposes its overflow action; the
page heading identifies the current telemetry view.

| Viewport (pixels) | Traces: selected no-data resource | Structured
logs: selected no-data resource |
| --- | --- | --- |
| Mobile **390 x 844** | ![Traces no-data resource - mobile
390x844](https://github.com/user-attachments/assets/4eb6ff31-2230-41dd-a70d-38880ad5438b)
| ![Structured logs no-data resource - mobile
390x844](https://github.com/user-attachments/assets/48356570-d85b-4a32-bb2d-59dbcb3e4791)
|
| Tablet **768 x 1024** | ![Traces no-data resource - tablet
768x1024](https://github.com/user-attachments/assets/2ad72901-4cdf-4309-b7e7-7cbf4ac370d7)
| ![Structured logs no-data resource - tablet
768x1024](https://github.com/user-attachments/assets/79363849-f474-477c-8c58-09deb28b2bb1)
|
| Desktop **1440 x 900** | ![Traces no-data resource - desktop
1440x900](https://github.com/user-attachments/assets/556482a8-e75f-411d-8da7-8af8daee7a43)
| ![Structured logs no-data resource - desktop
1440x900](https://github.com/user-attachments/assets/9d33a3bf-0701-4863-814d-b5d180c13368)
|

Fixes # (issue)

## Checklist

- Is this feature complete?
  - [x] Yes. Ready to ship.
  - [ ] No. Follow-up changes expected.
- Are you including unit tests for the changes and scenario tests if
relevant?
  - [x] Yes
  - [ ] No
- Did you add public API?
  - [ ] Yes
    - If yes, did you have an API Review for it?
      - [ ] Yes
      - [ ] No
- Did you add `<remarks />` and `<code />` elements on your triple slash
comments?
      - [ ] Yes
      - [ ] No
  - [x] No
- Does the change make any security assumptions or guarantees?
  - [ ] Yes
    - If yes, have you done a threat model and had a security review?
      - [ ] Yes
      - [ ] No
  - [x] No

Co-authored-by: David Pine <7679720+IEvangelist@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@davidfowl David Fowler (davidfowl) added the agent:working An AI agent is actively working on this issue or PR label Nov 6, 2026 — with Copilot SWE Agent
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copy link
Copy Markdown
Collaborator Author

Merged main into this branch to resolve conflicts in StructuredLogs.razor.cs and Traces.razor.cs. main now subscribes to ResourcesLayout.ResourcesChanged just before the OnNewResources subscription. I kept that subscription and this PR's async callback, which awaits ResolveRouteResourceAsync(). No other changes.

Local tests: Aspire.Dashboard.Components.Tests passed 1371/1371. The MetricsTests, StructuredLogsTests and TracesTests classes ran 6 times. One early run had a single failure that didn't reproduce in the next 5 runs.

🤖 Posted by AspireAgent (AI Agent)

@davidfowl David Fowler (davidfowl) removed the agent:working An AI agent is actively working on this issue or PR label Nov 6, 2026
@aspire-repo-bot
aspire-repo-bot Bot requested a balanced review from Copilot November 6, 2026 07:26
@github-actions

github-actions Bot commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Tests selector

13 / 101 PR test projects · 2 PR jobs, from 6 changed files.

Selected PR test projects (13 / 101)

Aspire.Dashboard.Components.Tests, Aspire.Dashboard.Tests, Aspire.Hosting.Azure.Kubernetes.Tests, Aspire.Hosting.Azure.Tests, Aspire.Hosting.Blazor.Tests, Aspire.Hosting.Dotnet.Tests, Aspire.Hosting.DotnetTool.Tests, Aspire.Hosting.JavaScript.Tests, Aspire.Hosting.Radius.Tests, Aspire.Hosting.Testing.Tests, Aspire.Hosting.Tests, Aspire.Playground.Tests, Aspire.Templates.Tests

Selected PR jobs (2)

extension-e2e, native-dashboard-validation


How these were chosen — grouped by what changed

⚠️ 11 of the 13 selected test projects come from a single change — src/Aspire.Dashboard/Components/Pages/Metrics.razor.cs.

🔧 src/Aspire.Dashboard/Components/Pages/Metrics.razor.cs (changed source)
→ 11 via the project graph: Aspire.Dashboard.Tests, Aspire.Hosting.Azure.Kubernetes.Tests (3 hops), Aspire.Hosting.Azure.Tests (2 hops), Aspire.Hosting.Blazor.Tests (2 hops), Aspire.Hosting.Dotnet.Tests (2 hops), Aspire.Hosting.DotnetTool.Tests (2 hops), Aspire.Hosting.JavaScript.Tests, Aspire.Hosting.Radius.Tests (2 hops), Aspire.Hosting.Testing.Tests, Aspire.Hosting.Tests, Aspire.Playground.Tests (2 hops)

📦 affected project Aspire.Dashboard
→ 1 test: Aspire.Templates.Tests

🧪 tests/Aspire.Dashboard.Components.Tests/Pages/MetricsTests.cs (changed test)
→ 1 directly: Aspire.Dashboard.Components.Tests

🧪 tests/Aspire.Dashboard.Components.Tests/Pages/StructuredLogsTests.cs (changed test)
→ 1 directly: Aspire.Dashboard.Components.Tests

🧪 tests/Aspire.Dashboard.Components.Tests/Pages/TracesTests.cs (changed test)
→ 1 directly: Aspire.Dashboard.Components.Tests

Job reasons

Job Triggered by
extension-e2e • src/Aspire.Dashboard/Components/Pages/Metrics.razor.cs, src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor.cs, src/Aspire.Dashboard/Components/Pages/Traces.razor.cs
• affected project Aspire.Dashboard
native-dashboard-validation affected project Aspire.Dashboard

Selection computed for commit 15f4414.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

No active review issues remain for the resource-scoping and chart-selection changes.

No open issues 🎉

Review effort: Balanced

@github-actions

github-actions Bot commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dashboard: preserve resource selection in telemetry pages and metrics charts

2 participants