diff --git a/src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor b/src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor
index 044d9c6b9bd..2a02d262009 100644
--- a/src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor
+++ b/src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor
@@ -144,7 +144,8 @@
@FormatHelpers.FormatTimeWithOptionalDate(TimeProvider, context.TimeStamp, MillisecondsDisplay.Truncated)
-
+
+ @* Tooltip is displayed by the message GridValue instance *@
diff --git a/src/Aspire.Dashboard/Components/ResourcesGridColumns/LogMessageColumnDisplay.razor b/src/Aspire.Dashboard/Components/ResourcesGridColumns/LogMessageColumnDisplay.razor
index 8170fc4be37..f5ff52d18d2 100644
--- a/src/Aspire.Dashboard/Components/ResourcesGridColumns/LogMessageColumnDisplay.razor
+++ b/src/Aspire.Dashboard/Components/ResourcesGridColumns/LogMessageColumnDisplay.razor
@@ -3,11 +3,13 @@
@using Aspire.Dashboard.Extensions
@using Aspire.Dashboard.Otlp.Model
@using Aspire.Dashboard.Resources
+@using Aspire.Dashboard.Utils
@inject IStringLocalizer Loc
-
diff --git a/src/Aspire.Dashboard/Utils/FormatHelpers.cs b/src/Aspire.Dashboard/Utils/FormatHelpers.cs
index 1f04ab39c86..48fd7c3cf7b 100644
--- a/src/Aspire.Dashboard/Utils/FormatHelpers.cs
+++ b/src/Aspire.Dashboard/Utils/FormatHelpers.cs
@@ -18,6 +18,11 @@ public enum MillisecondsDisplay
internal static partial class FormatHelpers
{
+ // Limit size of very long data that is written in large grids.
+ public const int ColumnMaximumTextLength = 250;
+ public const int TooltipMaximumTextLength = 1500;
+ public const string Ellipsis = "…";
+
// There are an unbound number of CultureInfo instances so we don't want to use it as the key.
// Someone could have also customized their culture so we don't want to use the name as the key.
// 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
};
return value.ToString(formatString, provider ?? CultureInfo.CurrentCulture);
}
+
+ public static string TruncateText(string? text, int maxLength)
+ {
+ if (string.IsNullOrEmpty(text))
+ {
+ return string.Empty;
+ }
+
+ if (text.Length <= maxLength)
+ {
+ return text;
+ }
+
+ return string.Concat(text.AsSpan(0, maxLength - Ellipsis.Length), Ellipsis);
+ }
}
diff --git a/tests/Aspire.Dashboard.Tests/FormatHelpersTests.cs b/tests/Aspire.Dashboard.Tests/FormatHelpersTests.cs
index 010fb7af17f..0851d1f6aa1 100644
--- a/tests/Aspire.Dashboard.Tests/FormatHelpersTests.cs
+++ b/tests/Aspire.Dashboard.Tests/FormatHelpersTests.cs
@@ -82,6 +82,16 @@ public void FormatDateTime_WithMilliseconds_NewZealandCulture(string expected, M
Assert.Equal(expected, FormatHelpers.FormatDateTime(CreateTimeProvider(), date, includeMilliseconds, cultureInfo: CultureInfo.GetCultureInfo("en-NZ")), ignoreWhiteSpaceDifferences: true, ignoreCase: true);
}
+ [Theory]
+ [InlineData(null, 5, "")]
+ [InlineData("", 5, "")]
+ [InlineData("abcdef", 5, "abcd" + FormatHelpers.Ellipsis)]
+ [InlineData("abcdef", 10, "abcdef")]
+ public void TruncateText(string? initialText, int maxLength, string expected)
+ {
+ Assert.Equal(expected, FormatHelpers.TruncateText(initialText, maxLength: maxLength));
+ }
+
private static DateTime GetLocalDateTime(string value)
{
Assert.True(DateTime.TryParseExact(value, "o", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var date));