Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f3141e3

Browse files
authored
Improve span details percentage calculation (#10310)
1 parent 5f0ec57 commit f3141e3

File tree

3 files changed

+50
-8
lines changed

3 files changed

+50
-8
lines changed

src/Aspire.Dashboard/Model/Otlp/SpanWaterfallViewModel.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ static SpanWaterfallViewModel CreateViewModel(OtlpSpan span, int depth, bool hid
140140
var relativeStart = span.StartTime - traceStart;
141141
var rootDuration = span.Trace.Duration.TotalMilliseconds;
142142

143-
var leftOffset = relativeStart.TotalMilliseconds / rootDuration * 100;
144-
var width = span.Duration.TotalMilliseconds / rootDuration * 100;
143+
var leftOffset = CalculatePercent(relativeStart.TotalMilliseconds, rootDuration);
144+
var width = CalculatePercent(span.Duration.TotalMilliseconds, rootDuration);
145145

146146
// Figure out if the label is displayed to the left or right of the span.
147147
// If the label position is based on whether more than half of the span is on the left or right side of the trace.
@@ -163,7 +163,7 @@ static SpanWaterfallViewModel CreateViewModel(OtlpSpan span, int depth, bool hid
163163
{
164164
Index = currentSpanLogIndex++,
165165
LogEntry = log,
166-
LeftOffset = logRelativeStart.TotalMilliseconds / rootDuration * 100
166+
LeftOffset = CalculatePercent(logRelativeStart.TotalMilliseconds, rootDuration)
167167
});
168168
}
169169
}
@@ -192,6 +192,15 @@ static SpanWaterfallViewModel CreateViewModel(OtlpSpan span, int depth, bool hid
192192

193193
return viewModel;
194194
}
195+
196+
static double CalculatePercent(double value, double total)
197+
{
198+
if (total == 0)
199+
{
200+
return 0;
201+
}
202+
return value / total * 100;
203+
}
195204
}
196205

197206
private static string? ResolveUninstrumentedPeerName(OtlpSpan span, IOutgoingPeerResolver[] outgoingPeerResolvers)

tests/Aspire.Dashboard.Tests/Model/SpanWaterfallViewModelTests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
using Aspire.Dashboard.Model.Otlp;
66
using Aspire.Dashboard.Otlp.Model;
77
using Aspire.Tests.Shared.Telemetry;
8+
using Google.Protobuf.Collections;
89
using Microsoft.Extensions.Logging.Abstractions;
10+
using OpenTelemetry.Proto.Common.V1;
911
using Xunit;
1012

1113
namespace Aspire.Dashboard.Tests.Model;
@@ -42,6 +44,36 @@ public void Create_HasChildren_ChildrenPopulated()
4244
});
4345
}
4446

47+
[Fact]
48+
public void Create_RootSpanZeroDuration_ZeroPercentage()
49+
{
50+
// Arrange
51+
var context = new OtlpContext { Logger = NullLogger.Instance, Options = new() };
52+
var app1 = new OtlpApplication("app1", "instance", uninstrumentedPeer: false, context);
53+
var app1View = new OtlpApplicationView(app1, new RepeatedField<KeyValue>());
54+
55+
var date = new DateTime(2001, 1, 1, 1, 1, 2, DateTimeKind.Utc);
56+
var trace = new OtlpTrace(new byte[] { 1, 2, 3 });
57+
var scope = TelemetryTestHelpers.CreateOtlpScope(context);
58+
trace.AddSpan(TelemetryTestHelpers.CreateOtlpSpan(app1, trace, scope, spanId: "31", parentSpanId: null, startDate: date, endDate: date));
59+
var log = new OtlpLogEntry(TelemetryTestHelpers.CreateLogRecord(traceId: trace.TraceId, spanId: "1"), app1View, scope, context);
60+
61+
// Act
62+
var vm = SpanWaterfallViewModel.Create(trace, [log], new SpanWaterfallViewModel.TraceDetailState([], []));
63+
64+
// Assert
65+
Assert.Collection(vm,
66+
e =>
67+
{
68+
Assert.Equal("31", e.Span.SpanId);
69+
Assert.Equal(0, e.LeftOffset);
70+
Assert.Equal(0, e.Width);
71+
72+
var spanLog = Assert.Single(e.SpanLogs);
73+
Assert.Equal(0, spanLog.LeftOffset);
74+
});
75+
}
76+
4577
[Fact]
4678
public void Create_OutgoingPeers_BrowserLink()
4779
{

tests/Shared/Telemetry/TelemetryTestHelpers.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -184,15 +184,16 @@ public static Span CreateSpan(string traceId, string spanId, DateTime startTime,
184184
return span;
185185
}
186186

187-
public static LogRecord CreateLogRecord(DateTime? time = null, DateTime? observedTime = null, string? message = null, SeverityNumber? severity = null, IEnumerable<KeyValuePair<string, string>>? attributes = null, bool? skipBody = null)
187+
public static LogRecord CreateLogRecord(DateTime? time = null, DateTime? observedTime = null, string? message = null, SeverityNumber? severity = null, IEnumerable<KeyValuePair<string, string>>? attributes = null,
188+
bool? skipBody = null, string? traceId = null, string? spanId = null)
188189
{
189190
attributes ??= [new KeyValuePair<string, string>("{OriginalFormat}", "Test {Log}"), new KeyValuePair<string, string>("Log", "Value!")];
190191

191192
var logRecord = new LogRecord
192193
{
193194
Body = (skipBody ?? false) ? null : new AnyValue { StringValue = message ?? "Test Value!" },
194-
TraceId = ByteString.CopyFrom(Convert.FromHexString("5465737454726163654964")),
195-
SpanId = ByteString.CopyFrom(Convert.FromHexString("546573745370616e4964")),
195+
TraceId = (traceId != null) ? ByteString.CopyFrom(Encoding.UTF8.GetBytes(traceId)) : ByteString.CopyFrom(Convert.FromHexString("5465737454726163654964")),
196+
SpanId = (spanId != null) ? ByteString.CopyFrom(Encoding.UTF8.GetBytes(spanId)) : ByteString.CopyFrom(Convert.FromHexString("546573745370616e4964")),
196197
TimeUnixNano = time != null ? DateTimeToUnixNanoseconds(time.Value) : 1000,
197198
ObservedTimeUnixNano = observedTime != null ? DateTimeToUnixNanoseconds(observedTime.Value) : 1000,
198199
SeverityNumber = severity ?? SeverityNumber.Info
@@ -303,13 +304,13 @@ public static OtlpContext CreateContext(TelemetryLimitOptions? options = null, I
303304

304305
public static OtlpSpan CreateOtlpSpan(OtlpApplication app, OtlpTrace trace, OtlpScope scope, string spanId, string? parentSpanId, DateTime startDate,
305306
KeyValuePair<string, string>[]? attributes = null, OtlpSpanStatusCode? statusCode = null, string? statusMessage = null, OtlpSpanKind kind = OtlpSpanKind.Unspecified,
306-
OtlpApplication? uninstrumentedPeer = null)
307+
OtlpApplication? uninstrumentedPeer = null, DateTime? endDate = null)
307308
{
308309
return new OtlpSpan(app.GetView([]), trace, scope)
309310
{
310311
Attributes = attributes ?? [],
311312
BackLinks = [],
312-
EndTime = DateTime.MaxValue,
313+
EndTime = endDate ?? DateTime.MaxValue,
313314
Events = [],
314315
Kind = kind,
315316
Links = [],

0 commit comments

Comments
 (0)