Release: log-view robustness (network-share tailing, bulk row-cap trim, selection contrast) #10

Merged
hannah-vernon merged 4 commits from dev into main 2026-07-03 15:33:50 -05:00

What does this PR do?

Release: merges the log-view robustness fixes from #9 into main. The Version Bump workflow will tag the next v1.2.{PR number}.

Included changes:

  • Network-share tailing - detect appended data by reading through to the real end of stream instead of trusting SMB's cached FileStream.Length; richer status bar (matched-file count, follow state, "last new HH:mm:ss", persistent notice); FileSystemWatcher.Error handling with a poll fallback.
  • Bulk row-cap trim - BoundedLogCollection.TrimHead drops the oldest rows in one notification instead of one event per row, so the display no longer stalls at the 50,000-row cap under a fast log rate.
  • Selection contrast - selected rows are painted white-on-blue (focused or not) so a clicked line stays readable.

How was this tested?

  • dotnet build Tayler.slnx -c Debug - 0 errors, 0 warnings
  • Each fix smoke-tested against the running app (see #9 for details).

Checklist

  • I have read the Contributing Guide
  • Changes are focused - one logical change per PR
  • Documentation updated (if user-visible behavior changed)
  • New dependencies are MIT/Apache-2.0 and security-vetted
  • No commented-out code or debug leftovers
## What does this PR do? Release: merges the log-view robustness fixes from #9 into `main`. The Version Bump workflow will tag the next `v1.2.{PR number}`. Included changes: - **Network-share tailing** - detect appended data by reading through to the real end of stream instead of trusting SMB's cached `FileStream.Length`; richer status bar (matched-file count, follow state, "last new HH:mm:ss", persistent notice); `FileSystemWatcher.Error` handling with a poll fallback. - **Bulk row-cap trim** - `BoundedLogCollection.TrimHead` drops the oldest rows in one notification instead of one event per row, so the display no longer stalls at the 50,000-row cap under a fast log rate. - **Selection contrast** - selected rows are painted white-on-blue (focused or not) so a clicked line stays readable. ## How was this tested? - [x] `dotnet build Tayler.slnx -c Debug` - 0 errors, 0 warnings - [x] Each fix smoke-tested against the running app (see #9 for details). ## Checklist - [x] I have read the [Contributing Guide](../CONTRIBUTING.md) - [x] Changes are focused - one logical change per PR - [x] Documentation updated (if user-visible behavior changed) - [x] New dependencies are MIT/Apache-2.0 and security-vetted - [x] No commented-out code or debug leftovers
Tailing could stop showing new lines on UNC / SMB shares because new-content
detection relied on FileStream.Length, which the SMB redirector can cache as a
stale (smaller) value, so the tailer concluded there was nothing new even while
the file kept growing. A restart did not recover it because the stale length
lives in the OS redirector, not in the app.

- FileTailer.ReadNew: seek to the last offset and read through to the real end of
  stream (read until a zero-byte read) instead of bounding reads by the cached
  fs.Length. fs.Length is now used only for truncation / rotation detection. A
  read at the offset goes to the server and returns genuinely appended bytes.
- FolderTailer: raise a DiscoveryCompleted event after discovery so the UI can
  show "Following" and the matched-file count even before the first new line;
  handle FileSystemWatcher.Error (internal-buffer overflow / dropped watch) by
  forcing a rescan and notice while the periodic poll carries on; bump the
  watcher InternalBufferSize to 64 KB.
- FolderWindow: status bar now shows matched-file count, the follow state as soon
  as tailing starts (no longer stuck on "Starting..."), the "last new HH:mm:ss"
  time so a stalled source is visible, and the most recent notice persistently
  instead of a one-shot message.
- README: document the network-share behaviour and the richer status bar.

Verified with a local harness: existing lines plus all after-start appends are
displayed, and the status bar reports "Following", file count, and last-new time.
Build is 0 warnings / 0 errors.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Once the combined view reached its row cap (MaxRows, 50,000 by default), each
poll trimmed the overflow with a per-row ObservableCollection.RemoveAt(0) loop.
Every removal shifted the whole backing array and, more importantly, raised its
own collection-changed event, each of which drove a layout pass in the bound
DataGrid. At the cap under a fast log rate that is thousands of events per 250 ms
poll, which saturated the UI thread and made the display appear to stop showing
new lines.

- Add BoundedLogCollection (ObservableCollection<LogRow>) with TrimHead(max),
  which drops the oldest rows directly on the backing list (a single
  List.RemoveRange) and raises one Reset notification instead of one event per
  row.
- FolderWindow.AppendRows now lets the buffer grow a small amount past the cap
  and then bulk-trims, so a trim (and any scroll reposition when auto-scroll is
  off) happens rarely rather than on every batch. Additions stay incremental so
  appending does not disturb the scroll position.
- README: document the bounded-view / bulk-trim behaviour.

Verified by running the app with MaxRows=20 and appending 200 lines quickly: the
view stayed responsive, trimmed to the newest 20 rows, and the status bar showed
"20 rows - Following". Build is 0 warnings / 0 errors.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Clicking a row in the combined view was hard to read: with full-row selection
the default WPF theme leaves the log text dark and paints a pale highlight behind
it (and an even fainter brush when the grid is not focused), so the selected line
lost contrast. Because the cells are transparent for the compact look, that
washed-out selection showed through.

Add an IsSelected trigger to the DataGridCell style that paints selected cells
with white text on a solid blue background, applied whether or not the grid has
focus, so a selected row stays legible.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Reviewed-on: #9
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
hannah-vernon/tayler-log-tailer!10
No description provided.