From 0f679441439066e11a91bb5603552d67449b7e58 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Fri, 27 Mar 2026 07:30:22 +0800 Subject: [PATCH] [release/13.2] Simplify TelemetryApiService.GetTrace and support short trace IDs (#15613) * Simplify TelemetryApiService.GetTrace and support short trace IDs - Use TelemetryRepository.GetTrace instead of fetching all traces - Add early return in GetTraceUnsynchronized for IDs shorter than ShortenedIdLength - Add parameterized unit test for full, short, and nonexistent trace IDs * Use hex constant in GetTrace test for explicit trace ID relationship * Remove early return for short trace IDs in GetTraceUnsynchronized MatchTelemetryId already handles short IDs correctly with exact equality fallback, so the guard was preventing valid exact-match lookups. * Clean up --- .../Api/TelemetryApiService.cs | 11 +---- .../TelemetryApiServiceTests.cs | 45 +++++++++++++++++++ 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/Aspire.Dashboard/Api/TelemetryApiService.cs b/src/Aspire.Dashboard/Api/TelemetryApiService.cs index 112c2502a79..80617479ca7 100644 --- a/src/Aspire.Dashboard/Api/TelemetryApiService.cs +++ b/src/Aspire.Dashboard/Api/TelemetryApiService.cs @@ -167,16 +167,7 @@ internal sealed class TelemetryApiService( /// public TelemetryApiResponse? GetTrace(string traceId) { - var result = telemetryRepository.GetTraces(new GetTracesRequest - { - ResourceKey = null, - StartIndex = 0, - Count = MaxQueryCount, - Filters = [], - FilterText = string.Empty - }); - - var trace = result.PagedResult.Items.FirstOrDefault(t => OtlpHelpers.MatchTelemetryId(t.TraceId, traceId)); + var trace = telemetryRepository.GetTrace(traceId); if (trace is null) { return null; diff --git a/tests/Aspire.Dashboard.Tests/TelemetryApiServiceTests.cs b/tests/Aspire.Dashboard.Tests/TelemetryApiServiceTests.cs index 08be66566a8..8bd11576896 100644 --- a/tests/Aspire.Dashboard.Tests/TelemetryApiServiceTests.cs +++ b/tests/Aspire.Dashboard.Tests/TelemetryApiServiceTests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Text; using Aspire.Dashboard.Api; using Aspire.Dashboard.Model; using Aspire.Dashboard.Otlp.Model; @@ -408,6 +409,50 @@ public async Task FollowLogsAsync_WithInvalidResourceName_ReturnsNoLogs() Assert.Empty(receivedItems); } + [Theory] + [InlineData("747261636531", true)] // full hex trace ID + [InlineData("7472616", true)] // shortened (7 char) prefix + [InlineData("747261", false)] // too short + [InlineData("nonexistent", false)] + public void GetTrace_VariousTraceIds_ReturnsExpectedResult(string lookupId, bool expectFound) + { + var repository = CreateRepository(); + var traceId = Encoding.UTF8.GetString(Convert.FromHexString("747261636531")); + + repository.AddTraces(new AddContext(), new RepeatedField + { + new ResourceSpans + { + Resource = CreateResource(name: "service1", instanceId: "inst1"), + ScopeSpans = + { + new ScopeSpans + { + Scope = CreateScope(), + Spans = + { + CreateSpan(traceId: traceId, spanId: "span1", startTime: s_testTime, endTime: s_testTime.AddMinutes(1)) + } + } + } + } + }); + + var service = CreateService(repository); + + var result = service.GetTrace(lookupId); + + if (expectFound) + { + Assert.NotNull(result); + Assert.Equal(1, result.ReturnedCount); + } + else + { + Assert.Null(result); + } + } + /// /// Creates a TelemetryApiService instance for testing with optional custom dependencies. ///