Skip to content

Add filter, virtualization, and export UI to DebugLogModal and unify file save#513

Open
jschick04 wants to merge 1 commit intomainfrom
jschick/debug-log-filters
Open

Add filter, virtualization, and export UI to DebugLogModal and unify file save#513
jschick04 wants to merge 1 commit intomainfrom
jschick/debug-log-filters

Conversation

@jschick04
Copy link
Copy Markdown
Collaborator

@jschick04 jschick04 commented May 4, 2026

Summary

Redesigns the debug log modal with filters, virtualized rendering, and export/copy actions, and unifies the existing file-save export pattern (used by 3 other modals) behind a new IFileSaveService.

Base branch: targets main. Diff is rendered against main.

What this changes

DebugLogModal redesign

  • New DebugLogEntry record + DebugLogEntryParser parses [ISO-Timestamp] [ThreadId] [Level] message lines, folding continuation lines (stack traces) into the prior entry.
  • New DebugLogProjection (pure) applies the active filters and reverses into newest-entry-first order via ReversedListView<T> (now implements IList<T> so Blazor <Virtualize> gets the Enumerable.Skip / Take indexer fast-path for deep offsets).
  • Renders rows with <Virtualize> (RowHeightPx=18 initial estimate, monospace font, white-space: pre-wrap + overflow-wrap: anywhere so long lines and stack traces wrap within the viewport instead of forcing a horizontal scrollbar). Multi-line entries render across multiple visual lines, which makes <Virtualize>''s scroll-position math approximate for tall rows — accepted tradeoff vs. the prior nowrap+ellipsis approach (which was inaccessible to keyboard / touch users) and the prior horizontal-scroll approach (which the user explicitly disliked).
  • Filter bar adds a level filter (ValueSelect with Equals / NotEqual / MultiSelect operators) and a debounced (250ms) message string filter.
  • Footer adds Export to file, Copy to clipboard, and a centered X of Y entries counter.
  • Refresh wraps the streaming LoadAsync in try/finally so partial data and _hasLoaded remain consistent on exception (generation-guarded).
  • Clear awaits FileLogger.ClearAsync() first, mutates UI state only on success, surfaces failures via IAlertDialogService.
  • DebugLogService.WriteTrace formats the timestamp inside _writeLock.EnterScope() so the on-disk line order is monotonic in timestamp under contention. Backed by a new Trace_WhenCalledFromMultipleThreadsConcurrently_* regression test that fires 64×4 parallel writes and asserts (a) line count, (b) every line parses, (c) timestamps non-decreasing, (d) every unique payload appears exactly once.

Unified file-save service

  • New IFileSaveService (in EventLogExpert.UI.Interfaces) + FileSaveServiceFileTypes (Json / Log typed dicts) as the single source of truth for file-type choices.
  • New MauiFileSaveService implementation registered in MauiProgram. Adds SetLength(0) before WriteAsync so overwriting a larger existing file no longer leaves stale trailing bytes (rationale documented inline).
  • Refactors 3 pre-existing export sites (FilterGroup.ExportGroup, FilterCacheModal.OnExportAsync, FilterGroupModal.OnExportAsync) onto the new service, removing direct Windows.Storage.Pickers / WinRT.Interop dependencies from those razor.cs files.

Tests

  • 20 DebugLogEntryParserTests (prefix parsing, continuation folding, malformed lines, no-prior-entry edge cases).
  • 21 DebugLogProjectionTests (level operators, text filter case-insensitivity, ordering, empty filters).
  • 28 DebugLogModalTests (bUnit) covering filter bar interactions, counter text, export call, clear success/failure, copy.
  • 6 new ReversedListViewTests covering IndexOf (reversed semantics), Insert / RemoveAt / indexer setter throwing NotSupportedException, and the IList<T> interface assertion.
  • 1 new DebugLogServiceTests concurrent-write regression test (64×4 parallel writers, four invariants).
  • All 1870 tests pass; build clean (0 warnings).

Notes for reviewers

  • MauiFileSaveService truncation order (SetLength(0) before WriteAsync) was deliberately chosen over a temp-file-and-rename pattern. Trade-off: a rare mid-write failure leaves a partial file on disk and surfaces the propagated exception (loudly visible) rather than the prior bug''s silent corruption (mix of new prefix + stale tail). Note this is not a temp-file-and-rename atomic write; partial-file-with-loud-failure is preferred over silent truncation-by-overwrite. Comment in source documents this.
  • Clear() reorder is a small behavior change to a pre-existing path — file is now mutated before the UI, with explicit failure surfacing. Two new tests cover both branches.
  • Sibling alert message inconsistency between DebugLogModal (ex.Message) and the 3 filter modals ($"An exception occurred while exporting X: {ex.Message}") is intentional — each surface describes its own context.
  • Continuation-line ambiguity in DebugLogEntryParser is documented and intentional: the parser classifies any line matching the [ts] [tid] [Level] prefix as a new entry. A continuation line whose payload happens to start with that exact shape would be split as a new entry. Round 13 deliberately removed the previous timestamp-based heuristic because pre-PR-Add filter, virtualization, and export UI to DebugLogModal and unify file save #513 writers formatted the timestamp before acquiring the lock, so persisted legacy debug.log files can legitimately contain headers in non-chronological order — a timestamp-based heuristic that folded an "older-looking" header into the prior entry would corrupt those legacy logs. The format is inherently ambiguous when message bodies contain header-shaped lines; we accept that ambiguity (no current producer in this repo intentionally emits header-shaped continuation content) rather than corrupt legacy logs.

@jschick04 jschick04 requested a review from a team as a code owner May 4, 2026 02:07
@jschick04 jschick04 marked this pull request as draft May 4, 2026 02:07
@jschick04 jschick04 requested a review from Copilot May 4, 2026 02:09
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR redesigns the debug log experience in the components/UI layers by moving from raw line rendering to parsed entries plus filtered/virtualized projection, and it centralizes the app’s Windows file-save flow behind a reusable IFileSaveService. It fits into the ongoing component/library restructuring by keeping platform-specific save behavior in the MAUI head while letting lifted/shared UI code depend only on interfaces.

Changes:

  • Adds structured debug-log parsing/projection primitives and rewires DebugLogModal to support level/text filtering, virtualization, export, copy, and improved clear/refresh behavior.
  • Introduces IFileSaveService plus a MAUI/WinUI implementation, then refactors existing filter export paths to use it.
  • Adds parser/projection/component tests and shared test constants/utilities for the new debug-log behavior.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/EventLogExpert/wwwroot/css/app.css Adjusts shared modal footer layout to support extra footer content.
src/EventLogExpert/Services/MauiFileSaveService.cs Adds Windows MAUI implementation for unified text file saving.
src/EventLogExpert/MauiProgram.cs Registers the new file-save service in DI.
src/EventLogExpert/Components/Modals/Filters/FilterGroupModal.razor.cs Refactors saved-group export to use IFileSaveService.
src/EventLogExpert/Components/Modals/Filters/FilterGroup.razor.cs Refactors single-group export to use IFileSaveService.
src/EventLogExpert/Components/Modals/Filters/FilterCacheModal.razor.cs Refactors saved-filter export to use IFileSaveService.
src/EventLogExpert.UI/Services/DebugLogProjection.cs Adds pure projection/filtering logic for parsed debug-log entries.
src/EventLogExpert.UI/Services/DebugLogEntryParser.cs Adds parsing/folding of raw debug-log lines into structured entries.
src/EventLogExpert.UI/Models/DebugLogEntry.cs Defines the structured debug-log entry record.
src/EventLogExpert.UI/Interfaces/IFileSaveService.cs Introduces the shared file-save abstraction and common file-type maps.
src/EventLogExpert.UI.Tests/TestUtils/Constants/Constants.DebugLog.cs Adds shared UI-test constants for debug-log parsing/projection tests.
src/EventLogExpert.UI.Tests/Services/DebugLogProjectionTests.cs Covers projection ordering and filter behavior.
src/EventLogExpert.UI.Tests/Services/DebugLogEntryParserTests.cs Covers parser prefix handling, malformed lines, and continuation folding.
src/EventLogExpert.Components/_Imports.razor Imports Blazor virtualization support for components.
src/EventLogExpert.Components/Modals/DebugLogModal.razor.css Styles the new filter bar, virtualized rows, and footer layout.
src/EventLogExpert.Components/Modals/DebugLogModal.razor.cs Reworks modal state/behavior for parsing, filtering, export/copy, and refresh/clear flows.
src/EventLogExpert.Components/Modals/DebugLogModal.razor Replaces raw line rendering with filter controls, Virtualize, and enhanced footer actions.
src/EventLogExpert.Components.Tests/TestUtils/DebugLogUtils.cs Adds component-test helpers for building async debug-log data.
src/EventLogExpert.Components.Tests/TestUtils/Constants/Constants.DebugLog.cs Adds shared component-test constants for debug-log modal tests.
src/EventLogExpert.Components.Tests/Modals/DebugLogModalTests.cs Adds bUnit coverage for modal filtering, counter, export, copy, and clear behavior.
Comments suppressed due to low confidence (1)

src/EventLogExpert.Components/Modals/DebugLogModal.razor.cs:188

  • LoadAsync() can still throw here (for example on access or read failures), and with only a try/finally the exception will bubble out of the event/lifecycle handler. That means opening or refreshing the modal can still fail as an unhandled UI exception instead of surfacing a recoverable alert like Clear/Export do.
        try
        {
            await foreach (var line in FileLogger.LoadAsync())

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor
Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor Outdated
Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor
Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 22 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/EventLogExpert/Services/MauiFileSaveService.cs Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor
Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor.cs Outdated
Comment thread src/EventLogExpert.UI/Interfaces/IFileSaveService.cs Outdated
Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor Outdated
Comment thread src/EventLogExpert.UI/Services/DebugLogProjection.cs
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor Outdated
Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor
Comment thread src/EventLogExpert/Services/MauiFileSaveService.cs Outdated
Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor.cs Outdated
Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor.cs Outdated
@jschick04 jschick04 force-pushed the jschick/debug-log-filters branch from fd4f150 to 6a259c9 Compare May 4, 2026 14:10
@jschick04 jschick04 requested a review from Copilot May 4, 2026 14:10
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor.cs Outdated
Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor.cs
Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor.cs Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor.cs
Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor Outdated
Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor.css Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 31 out of 31 changed files in this pull request and generated 7 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/EventLogExpert.UI/Services/DebugLogEntryParser.cs
Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor
Comment thread src/EventLogExpert.UI/Models/DebugLogEntry.cs Outdated
Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor.cs Outdated
Comment thread src/EventLogExpert/Services/MauiFileSaveService.cs Outdated
Comment thread src/EventLogExpert.UI/Services/DebugLogProjection.cs
Comment thread src/EventLogExpert.UI/Models/DebugLogEntry.cs Outdated
@jschick04 jschick04 force-pushed the jschick/debug-log-filters branch from ff5ae03 to 9de514e Compare May 5, 2026 17:36
Copilot AI review requested due to automatic review settings May 5, 2026 22:30
@jschick04 jschick04 force-pushed the jschick/debug-log-filters branch from 9de514e to b4cd4d3 Compare May 5, 2026 22:30
@jschick04 jschick04 force-pushed the jschick/debug-log-filters branch from b4cd4d3 to a23bc88 Compare May 5, 2026 22:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 31 out of 31 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor
Comment thread src/EventLogExpert/Services/MauiFileSaveService.cs Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 31 out of 31 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/EventLogExpert.UI/Interfaces/IFileSaveService.cs Outdated
Comment thread src/EventLogExpert/Services/MauiFileSaveService.cs Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 31 out of 31 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/EventLogExpert.Components/Modals/DebugLogModal.razor
Comment thread src/EventLogExpert/Services/MauiFileSaveService.cs Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 31 out of 31 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/EventLogExpert/Services/TitleProvider.cs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants