Skip to content

Commit d6ae0ba

Browse files
authored
Hide limit reached messages on remove (#7782)
1 parent bd23957 commit d6ae0ba

File tree

8 files changed

+70
-34
lines changed

8 files changed

+70
-34
lines changed

playground/Stress/Stress.ApiService/Program.cs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
IncludeBrokenLinks = true
7979
};
8080

81-
await traceCreator.CreateTraceAsync(count: 10, createChildren: true);
81+
await traceCreator.CreateTraceAsync("bigtrace", count: 10, createChildren: true);
8282

8383
return "Big trace created";
8484
});
@@ -93,7 +93,13 @@
9393

9494
for (var i = 0; i < TraceCount; i++)
9595
{
96-
await traceCreator.CreateTraceAsync(count: 1, createChildren: false);
96+
// Delay so OTEL has the opportunity to send traces.
97+
if (i % 1000 == 0)
98+
{
99+
await Task.Delay(TimeSpan.FromSeconds(0.5));
100+
}
101+
102+
await traceCreator.CreateTraceAsync($"tracelimit-{i}", count: 1, createChildren: false);
97103
}
98104

99105
Activity.Current = current;
@@ -117,7 +123,7 @@
117123
app.MapGet("/log-message-limit", async ([FromServices] ILogger<Program> logger) =>
118124
{
119125
const int LogCount = 10_000;
120-
const int BatchSize = 10;
126+
const int BatchSize = 100;
121127

122128
for (var i = 0; i < LogCount / BatchSize; i++)
123129
{
@@ -270,9 +276,9 @@ async IAsyncEnumerable<string> WriteOutput()
270276
Activity.Current = null;
271277
var traceCreator = new TraceCreator();
272278

273-
await traceCreator.CreateTraceAsync(count: 1, createChildren: true, rootName: "LinkedTrace1");
274-
await traceCreator.CreateTraceAsync(count: 1, createChildren: true, rootName: "LinkedTrace2");
275-
await traceCreator.CreateTraceAsync(count: 1, createChildren: true, rootName: "LinkedTrace3");
279+
await traceCreator.CreateTraceAsync("trace1", count: 1, createChildren: true, rootName: "LinkedTrace1");
280+
await traceCreator.CreateTraceAsync("trace2", count: 1, createChildren: true, rootName: "LinkedTrace2");
281+
await traceCreator.CreateTraceAsync("trace3", count: 1, createChildren: true, rootName: "LinkedTrace3");
276282

277283
Activity.Current = current;
278284

playground/Stress/Stress.ApiService/TraceCreator.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public class TraceCreator
3232
return activity;
3333
}
3434

35-
public async Task CreateTraceAsync(int count, bool createChildren, string? rootName = null)
35+
public async Task CreateTraceAsync(string traceName, int count, bool createChildren, string? rootName = null)
3636
{
3737
var activityStack = new Stack<Activity>();
3838

@@ -43,7 +43,7 @@ public async Task CreateTraceAsync(int count, bool createChildren, string? rootN
4343
await Task.Delay(Random.Shared.Next(10, 50));
4444
}
4545

46-
var name = $"Span-{i}";
46+
var name = $"{traceName}-Span-{i}";
4747
using var activity = s_activitySource.StartActivity(rootName ?? name, ActivityKind.Client);
4848
if (activity == null)
4949
{

src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor.cs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -113,18 +113,21 @@ private async ValueTask<GridItemsProviderResult<OtlpLogEntry>> GetData(GridItems
113113

114114
var logs = ViewModel.GetLogs();
115115

116-
if (DashboardOptions.Value.TelemetryLimits.MaxLogCount == logs.TotalItemCount && !TelemetryRepository.HasDisplayedMaxLogLimitMessage)
116+
if (logs.IsFull && !TelemetryRepository.HasDisplayedMaxLogLimitMessage)
117117
{
118-
await MessageService.ShowMessageBarAsync(options =>
119-
{
120-
options.Title = Loc[nameof(Dashboard.Resources.StructuredLogs.MessageExceededLimitTitle)];
121-
options.Body = string.Format(CultureInfo.InvariantCulture, Loc[nameof(Dashboard.Resources.StructuredLogs.MessageExceededLimitBody)], DashboardOptions.Value.TelemetryLimits.MaxLogCount);
122-
options.Intent = MessageIntent.Info;
123-
options.Section = "MessagesTop";
124-
options.AllowDismiss = true;
125-
});
118+
TelemetryRepository.MaxLogLimitMessage = await DashboardUIHelpers.DisplayMaxLimitMessageAsync(
119+
MessageService,
120+
Loc[nameof(Dashboard.Resources.StructuredLogs.MessageExceededLimitTitle)],
121+
string.Format(CultureInfo.InvariantCulture, Loc[nameof(Dashboard.Resources.StructuredLogs.MessageExceededLimitBody)], DashboardOptions.Value.TelemetryLimits.MaxLogCount),
122+
() => TelemetryRepository.MaxLogLimitMessage = null);
123+
126124
TelemetryRepository.HasDisplayedMaxLogLimitMessage = true;
127125
}
126+
else if (!logs.IsFull && TelemetryRepository.MaxLogLimitMessage is { } message)
127+
{
128+
// Telemetry could have been cleared from the dashboard. Automatically remove full message on data update.
129+
message.Close();
130+
}
128131

129132
// Updating the total item count as a field doesn't work because it isn't updated with the grid.
130133
// The workaround is to explicitly update and refresh the control.

src/Aspire.Dashboard/Components/Pages/Traces.razor.cs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -117,18 +117,21 @@ private async ValueTask<GridItemsProviderResult<OtlpTrace>> GetData(GridItemsPro
117117
TracesViewModel.Count = request.Count ?? DashboardUIHelpers.DefaultDataGridResultCount;
118118
var traces = TracesViewModel.GetTraces();
119119

120-
if (DashboardOptions.Value.TelemetryLimits.MaxTraceCount == traces.TotalItemCount && !TelemetryRepository.HasDisplayedMaxTraceLimitMessage)
120+
if (traces.IsFull && !TelemetryRepository.HasDisplayedMaxTraceLimitMessage)
121121
{
122-
await MessageService.ShowMessageBarAsync(options =>
123-
{
124-
options.Title = Loc[nameof(Dashboard.Resources.Traces.MessageExceededLimitTitle)];
125-
options.Body = string.Format(CultureInfo.InvariantCulture, Loc[nameof(Dashboard.Resources.Traces.MessageExceededLimitBody)], DashboardOptions.Value.TelemetryLimits.MaxTraceCount);
126-
options.Intent = MessageIntent.Info;
127-
options.Section = "MessagesTop";
128-
options.AllowDismiss = true;
129-
});
122+
TelemetryRepository.MaxTraceLimitMessage = await DashboardUIHelpers.DisplayMaxLimitMessageAsync(
123+
MessageService,
124+
Loc[nameof(Dashboard.Resources.Traces.MessageExceededLimitTitle)],
125+
string.Format(CultureInfo.InvariantCulture, Loc[nameof(Dashboard.Resources.Traces.MessageExceededLimitBody)], DashboardOptions.Value.TelemetryLimits.MaxTraceCount),
126+
() => TelemetryRepository.MaxTraceLimitMessage = null);
127+
130128
TelemetryRepository.HasDisplayedMaxTraceLimitMessage = true;
131129
}
130+
else if (!traces.IsFull && TelemetryRepository.MaxTraceLimitMessage is { } message)
131+
{
132+
// Telemetry could have been cleared from the dashboard. Automatically remove full message on data update.
133+
message.Close();
134+
}
132135

133136
// Updating the total item count as a field doesn't work because it isn't updated with the grid.
134137
// The workaround is to explicitly update and refresh the control.

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -401,12 +401,12 @@ public static string ConcatProperties(this KeyValuePair<string, string>[] proper
401401
return sb.ToString();
402402
}
403403

404-
public static PagedResult<T> GetItems<T>(IEnumerable<T> results, int startIndex, int count)
404+
public static PagedResult<T> GetItems<T>(IEnumerable<T> results, int startIndex, int count, bool isFull)
405405
{
406-
return GetItems<T, T>(results, startIndex, count, null);
406+
return GetItems<T, T>(results, startIndex, count, isFull, null);
407407
}
408408

409-
public static PagedResult<TResult> GetItems<TSource, TResult>(IEnumerable<TSource> results, int startIndex, int count, Func<TSource, TResult>? select)
409+
public static PagedResult<TResult> GetItems<TSource, TResult>(IEnumerable<TSource> results, int startIndex, int count, bool isFull, Func<TSource, TResult>? select)
410410
{
411411
var query = results.Skip(startIndex).Take(count);
412412
List<TResult> items;
@@ -423,7 +423,8 @@ public static PagedResult<TResult> GetItems<TSource, TResult>(IEnumerable<TSourc
423423
return new PagedResult<TResult>
424424
{
425425
Items = items,
426-
TotalItemCount = totalItemCount
426+
TotalItemCount = totalItemCount,
427+
IsFull = isFull
427428
};
428429
}
429430
}
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Licensed to the .NET Foundation under one or more agreements.
1+
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
namespace Aspire.Dashboard.Otlp.Storage;
@@ -8,9 +8,11 @@ public sealed class PagedResult<T>
88
public static readonly PagedResult<T> Empty = new()
99
{
1010
TotalItemCount = 0,
11-
Items = new List<T>()
11+
Items = new List<T>(),
12+
IsFull = false
1213
};
1314

1415
public required int TotalItemCount { get; init; }
1516
public required List<T> Items { get; init; }
17+
public required bool IsFull { get; init; }
1618
}

src/Aspire.Dashboard/Otlp/Storage/TelemetryRepository.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using Aspire.Dashboard.Otlp.Model.MetricValues;
1313
using Google.Protobuf.Collections;
1414
using Microsoft.Extensions.Options;
15+
using Microsoft.FluentUI.AspNetCore.Components;
1516
using OpenTelemetry.Proto.Common.V1;
1617
using OpenTelemetry.Proto.Logs.V1;
1718
using OpenTelemetry.Proto.Metrics.V1;
@@ -47,7 +48,10 @@ public sealed class TelemetryRepository
4748
internal readonly OtlpContext _otlpContext;
4849

4950
public bool HasDisplayedMaxLogLimitMessage { get; set; }
51+
public Message? MaxLogLimitMessage { get; set; }
52+
5053
public bool HasDisplayedMaxTraceLimitMessage { get; set; }
54+
public Message? MaxTraceLimitMessage { get; set; }
5155

5256
// For testing.
5357
internal List<OtlpSpanLink> SpanLinks => _spanLinks;
@@ -406,7 +410,7 @@ public PagedResult<OtlpLogEntry> GetLogs(GetLogsContext context)
406410
results = filter.Apply(results);
407411
}
408412

409-
return OtlpHelpers.GetItems(results, context.StartIndex, context.Count);
413+
return OtlpHelpers.GetItems(results, context.StartIndex, context.Count, _logs.IsFull);
410414
}
411415
finally
412416
{
@@ -532,7 +536,7 @@ public GetTracesResponse GetTraces(GetTracesRequest context)
532536
// Traces can be modified as new spans are added. Copy traces before returning results to avoid concurrency issues.
533537
var copyFunc = static (OtlpTrace t) => OtlpTrace.Clone(t);
534538

535-
var pagedResults = OtlpHelpers.GetItems(results, context.StartIndex, context.Count, copyFunc);
539+
var pagedResults = OtlpHelpers.GetItems(results, context.StartIndex, context.Count, _traces.IsFull, copyFunc);
536540
var maxDuration = pagedResults.TotalItemCount > 0 ? results.Max(r => r.Duration) : default;
537541

538542
return new GetTracesResponse

src/Aspire.Dashboard/Utils/DashboardUIHelpers.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,23 @@ public static TextMask GetMaskingText(int length)
6262
.ToString();
6363
});
6464
}
65+
66+
public static async Task<Message> DisplayMaxLimitMessageAsync(IMessageService messageService, string title, string message, Action onClose)
67+
{
68+
return await messageService.ShowMessageBarAsync(options =>
69+
{
70+
options.Title = title;
71+
options.Body = message;
72+
options.Intent = MessageIntent.Info;
73+
options.Section = "MessagesTop";
74+
options.AllowDismiss = true;
75+
options.OnClose = m =>
76+
{
77+
onClose();
78+
return Task.CompletedTask;
79+
};
80+
}).ConfigureAwait(false);
81+
}
6582
}
6683

6784
internal record TextMask(MarkupString MarkupString, string Text);

0 commit comments

Comments
 (0)