Skip to content

Commit 02c7350

Browse files
authored
Truncate large messages displayed in log grid (#10882)
* Truncate large messages displayed in log grid * Test * Update
1 parent 831a733 commit 02c7350

File tree

4 files changed

+35
-2
lines changed

4 files changed

+35
-2
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@
144144
<AspireTemplateColumn ColumnId="@TimestampColumn" ColumnManager="@_manager" Title="@Loc[nameof(Dashboard.Resources.StructuredLogs.StructuredLogsTimestampColumnHeader)]" TooltipText="@(context => FormatHelpers.FormatDateTime(TimeProvider, context.TimeStamp, MillisecondsDisplay.Full, CultureInfo.CurrentCulture))" Tooltip="true">
145145
@FormatHelpers.FormatTimeWithOptionalDate(TimeProvider, context.TimeStamp, MillisecondsDisplay.Truncated)
146146
</AspireTemplateColumn>
147-
<AspireTemplateColumn ColumnId="@MessageColumn" ColumnManager="@_manager" Title="@Loc[nameof(Dashboard.Resources.StructuredLogs.StructuredLogsMessageColumnHeader)]" Tooltip="true" TooltipText="(e) => e.Message">
147+
<AspireTemplateColumn ColumnId="@MessageColumn" ColumnManager="@_manager" Title="@Loc[nameof(Dashboard.Resources.StructuredLogs.StructuredLogsMessageColumnHeader)]">
148+
@* Tooltip is displayed by the message GridValue instance *@
148149
<LogMessageColumnDisplay FilterText="@(ViewModel.FilterText)" LogEntry="@context" />
149150
</AspireTemplateColumn>
150151
<AspireTemplateColumn ColumnId="@TraceColumn" ColumnManager="@_manager" Title="@Loc[nameof(Dashboard.Resources.StructuredLogs.StructuredLogsTraceColumnHeader)]">

src/Aspire.Dashboard/Components/ResourcesGridColumns/LogMessageColumnDisplay.razor

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
@using Aspire.Dashboard.Extensions
44
@using Aspire.Dashboard.Otlp.Model
55
@using Aspire.Dashboard.Resources
6+
@using Aspire.Dashboard.Utils
67

78
@inject IStringLocalizer<StructuredLogs> Loc
89

9-
<GridValue Value="@LogEntry.Message"
10+
<GridValue Value="@FormatHelpers.TruncateText(LogEntry.Message, FormatHelpers.ColumnMaximumTextLength)"
1011
ValueDescription="@Loc[nameof(StructuredLogs.StructuredLogsMessageColumnHeader)]"
12+
ToolTip="@FormatHelpers.TruncateText(LogEntry.Message, FormatHelpers.TooltipMaximumTextLength)"
1113
EnableHighlighting="true"
1214
HighlightText="@FilterText"
1315
StopClickPropagation="true">

src/Aspire.Dashboard/Utils/FormatHelpers.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ public enum MillisecondsDisplay
1818

1919
internal static partial class FormatHelpers
2020
{
21+
// Limit size of very long data that is written in large grids.
22+
public const int ColumnMaximumTextLength = 250;
23+
public const int TooltipMaximumTextLength = 1500;
24+
public const string Ellipsis = "…";
25+
2126
// There are an unbound number of CultureInfo instances so we don't want to use it as the key.
2227
// Someone could have also customized their culture so we don't want to use the name as the key.
2328
// This struct contains required information from the culture that is used in cached format strings.
@@ -133,4 +138,19 @@ public static string FormatNumberWithOptionalDecimalPlaces(double value, int max
133138
};
134139
return value.ToString(formatString, provider ?? CultureInfo.CurrentCulture);
135140
}
141+
142+
public static string TruncateText(string? text, int maxLength)
143+
{
144+
if (string.IsNullOrEmpty(text))
145+
{
146+
return string.Empty;
147+
}
148+
149+
if (text.Length <= maxLength)
150+
{
151+
return text;
152+
}
153+
154+
return string.Concat(text.AsSpan(0, maxLength - Ellipsis.Length), Ellipsis);
155+
}
136156
}

tests/Aspire.Dashboard.Tests/FormatHelpersTests.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,16 @@ public void FormatDateTime_WithMilliseconds_NewZealandCulture(string expected, M
8282
Assert.Equal(expected, FormatHelpers.FormatDateTime(CreateTimeProvider(), date, includeMilliseconds, cultureInfo: CultureInfo.GetCultureInfo("en-NZ")), ignoreWhiteSpaceDifferences: true, ignoreCase: true);
8383
}
8484

85+
[Theory]
86+
[InlineData(null, 5, "")]
87+
[InlineData("", 5, "")]
88+
[InlineData("abcdef", 5, "abcd" + FormatHelpers.Ellipsis)]
89+
[InlineData("abcdef", 10, "abcdef")]
90+
public void TruncateText(string? initialText, int maxLength, string expected)
91+
{
92+
Assert.Equal(expected, FormatHelpers.TruncateText(initialText, maxLength: maxLength));
93+
}
94+
8595
private static DateTime GetLocalDateTime(string value)
8696
{
8797
Assert.True(DateTime.TryParseExact(value, "o", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var date));

0 commit comments

Comments
 (0)