diff --git a/src/Aspire.Dashboard/Otlp/Model/OtlpTrace.cs b/src/Aspire.Dashboard/Otlp/Model/OtlpTrace.cs index 01b7979c48a..bf268ae3999 100644 --- a/src/Aspire.Dashboard/Otlp/Model/OtlpTrace.cs +++ b/src/Aspire.Dashboard/Otlp/Model/OtlpTrace.cs @@ -64,6 +64,12 @@ public void AddSpan(OtlpSpan span) if (!added) { Spans.Insert(0, span); + + // If there isn't a root span then the first span is used as the trace name. + if (_rootSpan == null && !string.IsNullOrEmpty(span.ParentSpanId)) + { + FullName = BuildFullName(span); + } } if (string.IsNullOrEmpty(span.ParentSpanId)) @@ -75,13 +81,18 @@ public void AddSpan(OtlpSpan span) if (string.IsNullOrEmpty(existingSpan.ParentSpanId)) { _rootSpan = existingSpan; - FullName = $"{existingSpan.Source.ApplicationName}: {existingSpan.Name}"; + FullName = BuildFullName(existingSpan); break; } } } AssertSpanOrder(); + + static string BuildFullName(OtlpSpan existingSpan) + { + return $"{existingSpan.Source.ApplicationName}: {existingSpan.Name}"; + } } [Conditional("DEBUG")] diff --git a/tests/Aspire.Dashboard.Tests/TelemetryRepositoryTests/TraceTests.cs b/tests/Aspire.Dashboard.Tests/TelemetryRepositoryTests/TraceTests.cs index cb0e5db2604..8706ff2ec41 100644 --- a/tests/Aspire.Dashboard.Tests/TelemetryRepositoryTests/TraceTests.cs +++ b/tests/Aspire.Dashboard.Tests/TelemetryRepositoryTests/TraceTests.cs @@ -944,4 +944,119 @@ public void GetTraces_MultipleInstances() AssertId("2", trace.TraceId); }); } + + [Fact] + public void AddTraces_OutOfOrder_FullName() + { + // Arrange + var repository = CreateRepository(); + var request = new GetTracesRequest + { + ApplicationKey = new ApplicationKey("TestService", "TestId"), + FilterText = string.Empty, + StartIndex = 0, + Count = 10 + }; + + // Act 1 + var addContext = new AddContext(); + repository.AddTraces(addContext, new RepeatedField() + { + new ResourceSpans + { + Resource = CreateResource(), + ScopeSpans = + { + new ScopeSpans + { + Scope = CreateScope(), + Spans = + { + CreateSpan(traceId: "1", spanId: "1-3", startTime: s_testTime.AddMinutes(10), endTime: s_testTime.AddMinutes(10), parentSpanId: "1-1") + } + } + } + } + }); + Assert.Equal(0, addContext.FailureCount); + + // Assert 1 + var trace = Assert.Single(repository.GetTraces(request).PagedResult.Items); + Assert.Equal("TestService: Test span. Id: 1-3", trace.FullName); + + // Act 2 + repository.AddTraces(addContext, new RepeatedField() + { + new ResourceSpans + { + Resource = CreateResource(), + ScopeSpans = + { + new ScopeSpans + { + Scope = CreateScope(), + Spans = + { + CreateSpan(traceId: "1", spanId: "1-2", startTime: s_testTime.AddMinutes(5), endTime: s_testTime.AddMinutes(10), parentSpanId: "1-1") + } + } + } + } + }); + Assert.Equal(0, addContext.FailureCount); + + // Assert 2 + trace = Assert.Single(repository.GetTraces(request).PagedResult.Items); + Assert.Equal("TestService: Test span. Id: 1-2", trace.FullName); + + // Act 3 + repository.AddTraces(addContext, new RepeatedField() + { + new ResourceSpans + { + Resource = CreateResource(), + ScopeSpans = + { + new ScopeSpans + { + Scope = CreateScope(), + Spans = + { + CreateSpan(traceId: "1", spanId: "1-1", startTime: s_testTime.AddMinutes(10), endTime: s_testTime.AddMinutes(10)) + } + } + } + } + }); + Assert.Equal(0, addContext.FailureCount); + + // Assert 3 + trace = Assert.Single(repository.GetTraces(request).PagedResult.Items); + Assert.Equal("TestService: Test span. Id: 1-1", trace.FullName); + + // Act 4 + repository.AddTraces(addContext, new RepeatedField() + { + new ResourceSpans + { + Resource = CreateResource(), + ScopeSpans = + { + new ScopeSpans + { + Scope = CreateScope(), + Spans = + { + CreateSpan(traceId: "1", spanId: "1-4", startTime: s_testTime, endTime: s_testTime.AddMinutes(10), parentSpanId: "1-1") + } + } + } + } + }); + Assert.Equal(0, addContext.FailureCount); + + // Assert 4 + trace = Assert.Single(repository.GetTraces(request).PagedResult.Items); + Assert.Equal("TestService: Test span. Id: 1-1", trace.FullName); + } } diff --git a/tests/Shared/Telemetry/TelemetryTestHelpers.cs b/tests/Shared/Telemetry/TelemetryTestHelpers.cs index fc7d5b4cb48..7497d29119e 100644 --- a/tests/Shared/Telemetry/TelemetryTestHelpers.cs +++ b/tests/Shared/Telemetry/TelemetryTestHelpers.cs @@ -152,7 +152,7 @@ public static Span CreateSpan(string traceId, string spanId, DateTime startTime, ParentSpanId = parentSpanId is null ? ByteString.Empty : ByteString.CopyFrom(Encoding.UTF8.GetBytes(parentSpanId)), StartTimeUnixNano = DateTimeToUnixNanoseconds(startTime), EndTimeUnixNano = DateTimeToUnixNanoseconds(endTime), - Name = "Test span" + Name = $"Test span. Id: {spanId}" }; if (events != null) {