Add minimum span duration filtering#17299
Conversation
Add dashboard trace-detail filtering for spans shorter than a configured duration, expose the same minDurationMs filter through telemetry APIs, and add CLI --min-duration support for spans and traces. 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 -- 17299Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 17299" |
There was a problem hiding this comment.
Pull request overview
Adds a minimum span duration filter across the Dashboard telemetry APIs, Dashboard trace detail UI, and Aspire CLI telemetry commands so very short spans can be hidden to reduce trace noise.
Changes:
- Adds
minDurationMsquery support to dashboard telemetry endpoints (spans, traces, trace detail) and applies filtering inTelemetryApiService. - Adds a “Minimum duration (ms)” filter control to the Trace Detail page and filters spans client-side in the grid.
- Adds
--min-duration/--min-duration-msto CLIotel spans/otel traces, plus test coverage and localization resources.
Show a summary per file
| File | Description |
|---|---|
| tests/Aspire.Dashboard.Tests/TelemetryApiServiceTests.cs | Adds unit tests for minimum-duration filtering behavior in telemetry APIs. |
| tests/Aspire.Dashboard.Tests/DashboardUrlsTests.cs | Verifies minDurationMs is appended to telemetry API URLs. |
| tests/Aspire.Dashboard.Components.Tests/Shared/FluentUISetupHelpers.cs | Updates Fluent UI JS interop test setup for text/number fields. |
| tests/Aspire.Dashboard.Components.Tests/Pages/TraceDetailsTests.cs | Adds component test for minimum-duration filtering in trace details grid. |
| tests/Aspire.Cli.Tests/Commands/TelemetryTracesCommandTests.cs | Tests CLI traces command includes minDurationMs in requests. |
| tests/Aspire.Cli.Tests/Commands/TelemetrySpansCommandTests.cs | Tests CLI spans command includes minDurationMs in requests. |
| src/Shared/DashboardUrls.cs | Adds optional minDurationMs query parameter to telemetry URL builders. |
| src/Aspire.Dashboard/DashboardEndpointsBuilder.cs | Wires minDurationMs from query string into telemetry API service calls. |
| src/Aspire.Dashboard/Api/TelemetryApiService.cs | Implements minimum-duration filtering for spans/traces/trace detail + follow streaming. |
| src/Aspire.Dashboard/Components/Pages/TraceDetail.razor | Adds minimum-duration input control (desktop + mobile toolbars). |
| src/Aspire.Dashboard/Components/Pages/TraceDetail.razor.cs | Applies minimum-duration filter when computing visible span view models. |
| src/Aspire.Dashboard/Components/Pages/TraceDetail.razor.css | Styles the new minimum-duration filter UI. |
| src/Aspire.Dashboard/Resources/TraceDetail.resx | Adds localized strings for the new UI label/placeholder/title. |
| src/Aspire.Dashboard/Resources/TraceDetail.Designer.cs | Generated accessors for new TraceDetail resource strings. |
| src/Aspire.Dashboard/Resources/xlf/TraceDetail.cs.xlf | Localization entries for new TraceDetail strings (cs). |
| src/Aspire.Dashboard/Resources/xlf/TraceDetail.de.xlf | Localization entries for new TraceDetail strings (de). |
| src/Aspire.Dashboard/Resources/xlf/TraceDetail.es.xlf | Localization entries for new TraceDetail strings (es). |
| src/Aspire.Dashboard/Resources/xlf/TraceDetail.fr.xlf | Localization entries for new TraceDetail strings (fr). |
| src/Aspire.Dashboard/Resources/xlf/TraceDetail.it.xlf | Localization entries for new TraceDetail strings (it). |
| src/Aspire.Dashboard/Resources/xlf/TraceDetail.ja.xlf | Localization entries for new TraceDetail strings (ja). |
| src/Aspire.Dashboard/Resources/xlf/TraceDetail.ko.xlf | Localization entries for new TraceDetail strings (ko). |
| src/Aspire.Dashboard/Resources/xlf/TraceDetail.pl.xlf | Localization entries for new TraceDetail strings (pl). |
| src/Aspire.Dashboard/Resources/xlf/TraceDetail.pt-BR.xlf | Localization entries for new TraceDetail strings (pt-BR). |
| src/Aspire.Dashboard/Resources/xlf/TraceDetail.ru.xlf | Localization entries for new TraceDetail strings (ru). |
| src/Aspire.Dashboard/Resources/xlf/TraceDetail.tr.xlf | Localization entries for new TraceDetail strings (tr). |
| src/Aspire.Dashboard/Resources/xlf/TraceDetail.zh-Hans.xlf | Localization entries for new TraceDetail strings (zh-Hans). |
| src/Aspire.Dashboard/Resources/xlf/TraceDetail.zh-Hant.xlf | Localization entries for new TraceDetail strings (zh-Hant). |
| src/Aspire.Cli/Commands/TelemetryCommandHelpers.cs | Introduces the shared --min-duration/--min-duration-ms option definition. |
| src/Aspire.Cli/Commands/TelemetrySpansCommand.cs | Passes minimum duration through to spans API URL. |
| src/Aspire.Cli/Commands/TelemetryTracesCommand.cs | Passes minimum duration through to traces/trace detail API URLs. |
| src/Aspire.Cli/Resources/TelemetryCommandStrings.resx | Adds description string for the new CLI option. |
| src/Aspire.Cli/Resources/TelemetryCommandStrings.Designer.cs | Generated accessor for the new CLI option description. |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.cs.xlf | Localization entry for new CLI option description (cs). |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.de.xlf | Localization entry for new CLI option description (de). |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.es.xlf | Localization entry for new CLI option description (es). |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.fr.xlf | Localization entry for new CLI option description (fr). |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.it.xlf | Localization entry for new CLI option description (it). |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.ja.xlf | Localization entry for new CLI option description (ja). |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.ko.xlf | Localization entry for new CLI option description (ko). |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.pl.xlf | Localization entry for new CLI option description (pl). |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.pt-BR.xlf | Localization entry for new CLI option description (pt-BR). |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.ru.xlf | Localization entry for new CLI option description (ru). |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.tr.xlf | Localization entry for new CLI option description (tr). |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.zh-Hans.xlf | Localization entry for new CLI option description (zh-Hans). |
| src/Aspire.Cli/Resources/xlf/TelemetryCommandStrings.zh-Hant.xlf | Localization entry for new CLI option description (zh-Hant). |
Copilot's findings
Files not reviewed (2)
- src/Aspire.Cli/Resources/TelemetryCommandStrings.Designer.cs: Language not supported
- src/Aspire.Dashboard/Resources/TraceDetail.Designer.cs: Language not supported
Comments suppressed due to low confidence (2)
src/Aspire.Cli/Commands/TelemetrySpansCommand.cs:101
- --min-duration accepts negative/NaN/Infinity values and they’ll be silently treated as “no duration filter” by the dashboard API (since minDurationMs <= 0 or non-finite becomes null). This makes the CLI option misleading. Add validation similar to --limit (e.g., require a finite value >= 0, or reject < 0/non-finite with an InvalidCommand exit and a clear error message).
var traceId = parseResult.GetValue(s_traceIdOption);
var hasError = parseResult.GetValue(s_hasErrorOption);
var dashboardUrl = parseResult.GetValue(s_dashboardUrlOption);
var apiKey = parseResult.GetValue(s_apiKeyOption);
var search = parseResult.GetValue(s_searchOption);
var minimumDuration = parseResult.GetValue(s_minimumDurationOption);
// Validate --limit value
if (limit.HasValue && limit.Value < 1)
{
return CommandResult.Failure(CliExitCodes.InvalidCommand, TelemetryCommandStrings.LimitMustBePositive);
}
src/Aspire.Cli/Commands/TelemetryTracesCommand.cs:99
- --min-duration accepts negative/NaN/Infinity values and they’ll be silently treated as “no duration filter” by the dashboard API (minDurationMs <= 0 or non-finite becomes null). This makes the CLI option misleading. Add validation similar to --limit (e.g., require a finite value >= 0, or reject < 0/non-finite with an InvalidCommand exit and a clear error message).
var format = parseResult.GetValue(s_formatOption);
var limit = parseResult.GetValue(s_limitOption);
var traceId = parseResult.GetValue(s_traceIdOption);
var hasError = parseResult.GetValue(s_hasErrorOption);
var dashboardUrl = parseResult.GetValue(s_dashboardUrlOption);
var apiKey = parseResult.GetValue(s_apiKeyOption);
var search = parseResult.GetValue(s_searchOption);
var minimumDuration = parseResult.GetValue(s_minimumDurationOption);
// Validate --limit value
if (limit.HasValue && limit.Value < 1)
{
return CommandResult.Failure(CliExitCodes.InvalidCommand, TelemetryCommandStrings.LimitMustBePositive);
}
- Files reviewed: 43/45 changed files
- Comments generated: 2
# Conflicts: # src/Aspire.Dashboard/Components/Pages/TraceDetail.razor # src/Aspire.Dashboard/Components/Pages/TraceDetail.razor.css
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Fixed values don’t cut it (though we can be smart about calculating a scale). I think it needs to be possible to enter a value. I am too worried about horizontal space as it doesn’t scale well for general filters |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Acknowledged. I addressed the performance issue from the inline thread and pushed the fix. |
|
❓ CLI E2E Tests unknown — 94 passed, 0 failed, 2 unknown (commit View all recordings
📹 Recordings uploaded automatically from CI run #26171097209 |

Description
Adds minimum span duration filtering so performance profiling can hide very short spans that add noise to trace analysis.
Users can now filter the dashboard trace detail view by entering a minimum duration in milliseconds. The same filter is available through the dashboard telemetry APIs via
minDurationMsand through the Aspire CLI via--min-duration/--min-duration-msfor spans and traces.The duration filter is applied after trace selection filters, so filters like
hasErrorand text search still select matching traces from the full trace whileminDurationMscontrols which spans are returned or displayed.User-facing usage
Dashboard telemetry API:
CLI:
Command help:
Validation
dotnet test --project tests/Aspire.Dashboard.Tests/Aspire.Dashboard.Tests.csproj --no-launch-profile -- --filter-class "*.TelemetryApiServiceTests" --filter-class "*.DashboardUrlsTests" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"dotnet test --project tests/Aspire.Cli.Tests/Aspire.Cli.Tests.csproj --no-launch-profile -- --filter-class "*.TelemetrySpansCommandTests" --filter-class "*.TelemetryTracesCommandTests" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"dotnet test --project tests/Aspire.Dashboard.Components.Tests/Aspire.Dashboard.Components.Tests.csproj --no-launch-profile -- --filter-class "*.TraceDetailsTests" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"otel spans --min-duration 50otel traces --trace-id <trace-id> --min-duration 50git diff --checkFixes # (issue)
Checklist
<remarks />and<code />elements on your triple slash comments?