From 75e086854bafbfd7c6689ea188c98518c24236b7 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Tue, 3 Sep 2024 10:09:13 +0800 Subject: [PATCH 1/2] Prevent duplicate filters on structured logs page --- .../Components/Pages/StructuredLogs.razor.cs | 5 ++- src/Aspire.Dashboard/Model/Otlp/LogFilter.cs | 27 ++++++++++++- .../Model/StructuredLogsViewModel.cs | 17 +++++--- .../Pages/StructuredLogsTests.cs | 40 +++++++++++++++++++ 4 files changed, 81 insertions(+), 8 deletions(-) diff --git a/src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor.cs b/src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor.cs index 5f8757434d4..92c858bbc90 100644 --- a/src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor.cs +++ b/src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor.cs @@ -434,7 +434,10 @@ public void UpdateViewModelFromQuery(StructuredLogsPageViewModel viewModel) if (filters.Count > 0) { ViewModel.ClearFilters(); - ViewModel.AddFilters(filters); + foreach (var filter in filters) + { + ViewModel.AddFilter(filter); + } } } diff --git a/src/Aspire.Dashboard/Model/Otlp/LogFilter.cs b/src/Aspire.Dashboard/Model/Otlp/LogFilter.cs index 7903676391d..4966fada425 100644 --- a/src/Aspire.Dashboard/Model/Otlp/LogFilter.cs +++ b/src/Aspire.Dashboard/Model/Otlp/LogFilter.cs @@ -10,7 +10,7 @@ namespace Aspire.Dashboard.Model.Otlp; [DebuggerDisplay("{FilterText,nq}")] -public class LogFilter +public class LogFilter : IEquatable { public const string KnownMessageField = "log.message"; public const string KnownCategoryField = "log.category"; @@ -142,4 +142,29 @@ public IEnumerable Apply(IEnumerable input) } } } + + public bool Equals(LogFilter? other) + { + if (other == null) + { + return false; + } + + if (Field != other.Field) + { + return false; + } + + if (Condition != other.Condition) + { + return false; + } + + if (!string.Equals(Value.Trim(), other.Value.Trim(), StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + return true; + } } diff --git a/src/Aspire.Dashboard/Model/StructuredLogsViewModel.cs b/src/Aspire.Dashboard/Model/StructuredLogsViewModel.cs index 24c92ee3011..d05cfe55d46 100644 --- a/src/Aspire.Dashboard/Model/StructuredLogsViewModel.cs +++ b/src/Aspire.Dashboard/Model/StructuredLogsViewModel.cs @@ -34,17 +34,21 @@ public void ClearFilters() _logs = null; } - public void AddFilters(IEnumerable filters) - { - _filters.AddRange(filters); - _logs = null; - } - public void AddFilter(LogFilter filter) { + // Don't add duplicate filters. + foreach (var existingFilter in _filters) + { + if (existingFilter.Equals(filter)) + { + return; + } + } + _filters.Add(filter); _logs = null; } + public bool RemoveFilter(LogFilter filter) { if (_filters.Remove(filter)) @@ -54,6 +58,7 @@ public bool RemoveFilter(LogFilter filter) } return false; } + public int StartIndex { get => _logsStartIndex; set => SetValue(ref _logsStartIndex, value); } public int? Count { get => _logsCount; set => SetValue(ref _logsCount, value); } public LogLevel? LogLevel { get => _logLevel; set => SetValue(ref _logLevel, value); } diff --git a/tests/Aspire.Dashboard.Components.Tests/Pages/StructuredLogsTests.cs b/tests/Aspire.Dashboard.Components.Tests/Pages/StructuredLogsTests.cs index 8861dcdd717..a143b60b38c 100644 --- a/tests/Aspire.Dashboard.Components.Tests/Pages/StructuredLogsTests.cs +++ b/tests/Aspire.Dashboard.Components.Tests/Pages/StructuredLogsTests.cs @@ -5,6 +5,7 @@ using Aspire.Dashboard.Components.Resize; using Aspire.Dashboard.Components.Tests.Shared; using Aspire.Dashboard.Configuration; +using Aspire.Dashboard.Extensions; using Aspire.Dashboard.Model; using Aspire.Dashboard.Model.BrowserStorage; using Aspire.Dashboard.Model.Otlp; @@ -64,6 +65,45 @@ public void Render_TraceIdAndSpanId_FilterAdded() }); } + [Fact] + public void Render_DuplicateFilters_SingleFilterAdded() + { + // Arrange + SetupStructureLogsServices(); + + var logFilter = new LogFilter { Field = "TestField", Condition = FilterCondition.Contains, Value = "TestValue" }; + var serializedFilter = LogFilterFormatter.SerializeLogFiltersToString([logFilter]); + + var navigationManager = Services.GetRequiredService(); + var uri = navigationManager.GetUriWithQueryParameters(new Dictionary + { + ["filters"] = serializedFilter + "+" + serializedFilter, + }); + navigationManager.NavigateTo(uri); + + var viewport = new ViewportInformation(IsDesktop: true, IsUltraLowHeight: false, IsUltraLowWidth: false); + + var dimensionManager = Services.GetRequiredService(); + dimensionManager.InvokeOnBrowserDimensionsChanged(viewport); + + // Act + var cut = RenderComponent(builder => + { + builder.Add(p => p.ViewportInformation, viewport); + }); + + // Assert + var viewModel = Services.GetRequiredService(); + + Assert.Collection(viewModel.Filters, + f => + { + Assert.Equal(logFilter.Field, f.Field); + Assert.Equal(logFilter.Condition, f.Condition); + Assert.Equal(logFilter.Value, f.Value); + }); + } + private void SetupStructureLogsServices() { var version = typeof(FluentMain).Assembly.GetName().Version!; From f4917da6c158a12c9d001d4eb14d1c1729dfc1bc Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Tue, 3 Sep 2024 10:22:49 +0800 Subject: [PATCH 2/2] Remove trim --- src/Aspire.Dashboard/Model/Otlp/LogFilter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Aspire.Dashboard/Model/Otlp/LogFilter.cs b/src/Aspire.Dashboard/Model/Otlp/LogFilter.cs index 4966fada425..f7a028f4438 100644 --- a/src/Aspire.Dashboard/Model/Otlp/LogFilter.cs +++ b/src/Aspire.Dashboard/Model/Otlp/LogFilter.cs @@ -160,7 +160,7 @@ public bool Equals(LogFilter? other) return false; } - if (!string.Equals(Value.Trim(), other.Value.Trim(), StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase)) { return false; }