CLI: Hide hidden resources by default in describe/logs/export, add --include-hidden option#16146
CLI: Hide hidden resources by default in describe/logs/export, add --include-hidden option#16146
Conversation
…nt by default and add --include-hidden option
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 16146Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 16146" |
- Replace inclusion-based log filtering with exclusion-based filtering so logs from resources appearing after the initial snapshot are not silently dropped. - Always fetch all snapshots to build the hidden set, then derive the visible list separately. - Add LogsCommand_NewResourceAfterInitialSnapshot_LogsAreIncluded test. - Use LINQ OrderBy instead of in-place Sort in GetResourceSnapshotsAsync.
|
There is a small behavior change if an old CLI is are used with new AppHost: aspire-dashboard will appear in decribe/logs/export. I think this is fine and making something completely backwards compatible would be more trouble than it's worth. |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR updates the CLI (describe, logs, export) to hide hidden resources by default and adds a --include-hidden flag to include them when desired, enabled by a server-side change to expose hidden state in backchannel snapshots.
Changes:
- Server: include dashboard in backchannel results and add
IsHiddentoResourceSnapshotDTO. - CLI: add
--include-hiddento commands and centralize hidden-resource filtering logic. - Tests/resources: add/adjust tests for hidden filtering behavior and add localized strings for the new option.
Reviewed changes
Copilot reviewed 59 out of 63 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Aspire.Hosting.Tests/Backchannel/AuxiliaryBackchannelRpcTargetTests.cs | Updates assertions to expect dashboard resource inclusion and removes dashboard log exclusion assertion. |
| tests/Aspire.Cli.Tests/TestServices/TestAppHostAuxiliaryBackchannel.cs | Updates test backchannel to accept includeHidden and filters snapshots/watch accordingly. |
| tests/Aspire.Cli.Tests/Commands/LogsCommandTests.cs | Adds tests validating default hidden filtering and --include-hidden behavior for logs. |
| tests/Aspire.Cli.Tests/Commands/ExportCommandTests.cs | Adds tests validating default hidden filtering and --include-hidden behavior for export output. |
| tests/Aspire.Cli.Tests/Commands/DescribeCommandTests.cs | Adds tests validating default hidden filtering and --include-hidden behavior for describe (snapshot and follow). |
| src/Aspire.Hosting/Backchannel/BackchannelDataTypes.cs | Adds IsHidden to the backchannel ResourceSnapshot DTO. |
| src/Aspire.Hosting/Backchannel/AuxiliaryBackchannelRpcTarget.cs | Removes hard-coded dashboard skipping and maps IsHidden into returned snapshots. |
| src/Aspire.Cli/Resources/xlf/LogsCommandStrings.zh-Hant.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/LogsCommandStrings.zh-Hans.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/LogsCommandStrings.tr.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/LogsCommandStrings.ru.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/LogsCommandStrings.pt-BR.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/LogsCommandStrings.pl.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/LogsCommandStrings.ko.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/LogsCommandStrings.ja.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/LogsCommandStrings.it.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/LogsCommandStrings.fr.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/LogsCommandStrings.es.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/LogsCommandStrings.de.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/LogsCommandStrings.cs.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/ExportCommandStrings.zh-Hant.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/ExportCommandStrings.zh-Hans.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/ExportCommandStrings.tr.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/ExportCommandStrings.ru.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/ExportCommandStrings.pt-BR.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/ExportCommandStrings.pl.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/ExportCommandStrings.ko.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/ExportCommandStrings.ja.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/ExportCommandStrings.it.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/ExportCommandStrings.fr.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/ExportCommandStrings.es.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/ExportCommandStrings.de.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/ExportCommandStrings.cs.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/DescribeCommandStrings.zh-Hant.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/DescribeCommandStrings.zh-Hans.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/DescribeCommandStrings.tr.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/DescribeCommandStrings.ru.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/DescribeCommandStrings.pt-BR.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/DescribeCommandStrings.pl.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/DescribeCommandStrings.ko.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/DescribeCommandStrings.ja.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/DescribeCommandStrings.it.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/DescribeCommandStrings.fr.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/DescribeCommandStrings.es.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/DescribeCommandStrings.de.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/xlf/DescribeCommandStrings.cs.xlf | Adds localized resource entry for --include-hidden description. |
| src/Aspire.Cli/Resources/LogsCommandStrings.resx | Adds IncludeHiddenOptionDescription resource. |
| src/Aspire.Cli/Resources/ExportCommandStrings.resx | Adds IncludeHiddenOptionDescription resource. |
| src/Aspire.Cli/Resources/DescribeCommandStrings.resx | Adds IncludeHiddenOptionDescription resource. |
| src/Aspire.Cli/Mcp/Tools/ListResourcesTool.cs | Updates MCP tool to request snapshots including hidden resources. |
| src/Aspire.Cli/Mcp/McpResourceToolRefreshService.cs | Updates tool refresh service to request snapshots including hidden resources. |
| src/Aspire.Cli/Commands/PsCommand.cs | Updates ps to request snapshots including hidden resources. |
| src/Aspire.Cli/Commands/McpToolsCommand.cs | Updates mcp tools to request snapshots including hidden resources. |
| src/Aspire.Cli/Commands/LogsCommand.cs | Adds --include-hidden and filters hidden snapshot/log output by default. |
| src/Aspire.Cli/Commands/ExportCommand.cs | Adds --include-hidden and filters hidden snapshots/log output by default. |
| src/Aspire.Cli/Commands/DescribeCommand.cs | Adds --include-hidden and filters hidden snapshots by default (including follow). |
| src/Aspire.Cli/Backchannel/ResourceSnapshotMapper.cs | Adds shared helpers to detect/filter hidden resources. |
| src/Aspire.Cli/Backchannel/IAppHostAuxiliaryBackchannel.cs | Changes backchannel API to accept includeHidden for snapshots/watch. |
| src/Aspire.Cli/Backchannel/AppHostAuxiliaryBackchannel.cs | Implements includeHidden filtering for snapshots and watch on the client side. |
Files not reviewed (3)
- src/Aspire.Cli/Resources/DescribeCommandStrings.Designer.cs: Language not supported
- src/Aspire.Cli/Resources/ExportCommandStrings.Designer.cs: Language not supported
- src/Aspire.Cli/Resources/LogsCommandStrings.Designer.cs: Language not supported
Comments suppressed due to low confidence (3)
tests/Aspire.Cli.Tests/TestServices/TestAppHostAuxiliaryBackchannel.cs:1
includeHiddenis ignored whenGetResourceSnapshotsHandleris set, which means tests using the handler bypass hidden filtering entirely. To make the test double consistently respectincludeHidden, either (a) change the handler signature to acceptincludeHidden, or (b) always post-filter the handler result whenincludeHidden == false.
tests/Aspire.Cli.Tests/Commands/LogsCommandTests.cs:1Assert.All(...)will pass vacuously iflogsOutput.Logsis empty, which would make this test succeed even if the command produced no log entries. Add an assertion that at least one expected entry exists (e.g.,Assert.Contains(... \"redis\" ...)orAssert.NotEmpty(logsOutput.Logs)) before theAssert.All.
tests/Aspire.Cli.Tests/Commands/LogsCommandTests.cs:1- Same issue as above:
Assert.All(...)passes iflogsOutput.Logsis empty. Add an explicit non-empty assertion (orAssert.Contains) so the test fails if no logs are returned for the specified hidden resource.
|
|
||
| private static bool IsHiddenResource(ResourceSnapshot snapshot) | ||
| { | ||
| return snapshot.IsHidden || string.Equals(snapshot.State, "Hidden", StringComparison.OrdinalIgnoreCase); |
There was a problem hiding this comment.
Hidden-resource detection logic is now duplicated here and in ResourceSnapshotMapper.IsHiddenResource (and again in the CLI test backchannel). This is easy to let drift over time. Consider centralizing it in a single internal helper (e.g., reuse ResourceSnapshotMapper.IsHiddenResource from this class, or extract a small shared HiddenResourceClassifier utility used by both production and test code).
| return snapshot.IsHidden || string.Equals(snapshot.State, "Hidden", StringComparison.OrdinalIgnoreCase); | |
| return ResourceSnapshotMapper.IsHiddenResource(snapshot); |
| // Always fetch all snapshots so we know which resources are hidden. | ||
| var allSnapshots = await connection.GetResourceSnapshotsAsync(includeHidden: true, cancellationToken).ConfigureAwait(false); | ||
|
|
||
| // Filter hidden resources, deriving the visible list and the hidden set for log filtering. | ||
| var (_, snapshots, hiddenResourceNames) = ResourceSnapshotMapper.FilterHiddenResources(allSnapshots, includeHidden, resourceName); |
There was a problem hiding this comment.
This code fetches allSnapshots specifically to understand hidden resources, but then passes the filtered snapshots list downstream. If later logic uses the snapshot list to pre-resolve deterministic resource metadata (e.g., color assignment), using filtered snapshots can make results depend on whether hidden resources are excluded. Consider using allSnapshots for any deterministic global precomputation, while continuing to use snapshots for what you actually display.
| ResourceType = snapshot.ResourceType, | ||
| State = snapshot.State?.Text, | ||
| StateStyle = snapshot.State?.Style, | ||
| IsHidden = snapshot.IsHidden, |
There was a problem hiding this comment.
What happens if someone updates Aspire.Hosting in their app but is still on the previous CLI? The older CLI still talks to the v1 backchannel methods and relies on the server-side filtering that used to skip dashboard/hidden resources here. This refactor removes that filtering from the v1 path and only adds IsHidden to the payload for newer clients, so an older CLI against a newer AppHost will start surfacing dashboard/hidden resources again in describe/logs/export. That is a regression from the previous brownfield behavior; the likely fix is to preserve the old filtering on the v1 RPC surface and only move the hidden-resource decision to the newer/v2 contract.
There was a problem hiding this comment.
There is no app host filtering of hidden resources. The only filter is of aspire-dashboard. I mentioned in a comment that it will now appear in older hosts. I don't think that's very important. Other system resources (i.e. rebuilders, installers) show up.
| }); | ||
|
|
||
| // Filter hidden resources, deriving the visible list and the hidden set for log filtering. | ||
| var (_, snapshots, hiddenResourceNames) = ResourceSnapshotMapper.FilterHiddenResources(allSnapshots, includeHidden, resourceName); |
There was a problem hiding this comment.
What happens if a hidden resource emits structured logs or traces? FilterHiddenResources gives you the visible snapshot list and hidden-name set here, but that information never reaches AddStructuredLogsAsync / AddTracesAsync, so the archive still writes structuredlogs/<hidden>.json and traces/<hidden>.json for every dashboard resource by default. In practice that means export only hides hidden resources from the resource snapshot and console-log sections; the telemetry sections still leak them, so --include-hidden becomes a no-op for the most important payloads. This is a hidden-contract mismatch with the sibling filtering above; the likely fix is to pass an allowed resource set into the telemetry export path and filter the dashboard response (or request) before writing files.
| // When streaming all resources, skip logs from hidden resources. | ||
| // We filter by exclusion so that new resources appearing after the | ||
| // initial snapshot are included by default. | ||
| if (resourceName is null && hiddenResourceNames.Contains(logLine.ResourceName)) |
There was a problem hiding this comment.
What happens if a hidden auxiliary resource appears after logs --follow has already started? This check only excludes names that were hidden in the initial snapshot; the set is never updated from later resource snapshots, so a late-created hidden resource will stream straight through here even without --include-hidden. That breaks the new default contract precisely in the delayed-start case that follow mode needs to handle, and it disagrees with describe --follow, which continues to filter hidden resources as they appear. The likely fix is to keep the hidden-name set in sync from snapshot updates (or resolve unknown resources before emitting), and add a focused test for a late-appearing hidden resource.
|
🎬 CLI E2E Test Recordings — 71 recordings uploaded (commit View recordings
📹 Recordings uploaded automatically from CI run #24402027377 |
PR test reportTested PR #16146 on exe.dev Linux x64 VMs with the dogfood CLI installed from the PR artifacts. Version verification
Scenarios1. New CLI + new AppHost (PR AppHost SDK)To exercise the hosting-side backchannel change, I created a fresh starter app from the PR packages and pinned the temporary AppHost to
2. New CLI + old AppHost (
|
| Command | Result |
|---|---|
aspire describe --format json |
✅ App worked, but the output still included rebuilders and did not include aspire-dashboard. |
aspire describe --include-hidden --format json |
ℹ️ Same effective resource set as default; the old AppHost does not surface hidden-resource metadata. |
aspire describe aspire-dashboard --format json |
ℹ️ Resource 'aspire-dashboard' not found. |
aspire logs --format json |
✅ Logs for apiservice and webfrontend only. |
aspire logs --include-hidden --format json |
ℹ️ Same effective result as default. |
aspire logs aspire-dashboard --format json |
ℹ️ Resource 'aspire-dashboard' was not found. |
aspire export --output ... |
✅ Export worked, but default and --include-hidden were identical and still included rebuilders. |
aspire export aspire-dashboard --output ... |
ℹ️ Resource 'aspire-dashboard' not found. |
aspire ps --format json --resources |
✅ AppHost was listed, but no aspire-dashboard resource was present. |
Summary
- ✅ New CLI + new AppHost matches the PR intent.
- ✅ New CLI + old AppHost remains functional.
- ℹ️ The new hidden-resource behavior depends on the AppHost/backchannel side of the change: with an old AppHost,
--include-hiddenis effectively a no-op and direct dashboard targeting is unavailable because the old AppHost never exposes the hidden resources to the CLI.
Captured JSON/zip outputs for each command while testing.
Fixes #16014
Fixes #16013
Description
The CLI
describe,logs, andexportcommands now hide resources marked as hidden by default, and expose a new--include-hiddenoption to show them when needed.This is consistent with how the dashboard displays resources: hidden by default with an option to show them.
Changes
Server-side (Aspire.Hosting):
AuxiliaryBackchannelRpcTarget— the dashboard resource is now included in backchannel results like any other resource.IsHiddenproperty to the backchannelResourceSnapshotDTO so the CLI client can make filtering decisions.Client-side (Aspire.Cli):
FilterHiddenResourcesandIsHiddenResourcehelpers inResourceSnapshotMapperfor consistent hidden-resource filtering across commands.--include-hiddenoption toDescribeCommand,LogsCommand, andExportCommand.aspire describe myresource), hidden resources are automatically included so the user can always describe/log/export a resource by name.LogsCommandandExportCommandfilter log lines from hidden resources when no specific resource is requested.LogsCommanduses exclusion-based filtering so logs from resources that appear after the initial snapshot are included by default.Tests:
DescribeCommandhidden resource behavior (default, include-hidden, specific resource, follow mode variants).LogsCommandhidden resource behavior (default, include-hidden, specific hidden resource, new resource after initial snapshot).ExportCommandhidden resource behavior (default, include-hidden, specific hidden resource).TestAppHostAuxiliaryBackchannelto respectincludeHiddenparameter.AuxiliaryBackchannelRpcTargetTeststo reflect dashboard resource now being included.Checklist
aspire.devissue: