Add a diagnostic error log, a Log button, and a version display #13

Merged
hannah-vernon merged 1 commit from feature/diagnostic-log into dev 2026-07-07 13:17:05 -05:00

What does this PR do?

Adds a persistent diagnostic error log and makes it (and the running version) reachable from the UI, so intermittent problems - especially on network shares - can be investigated after the fact.

Motivation: a watcher interruption on a share (File watcher interrupted; relying on periodic polling (Incorrect function)) was only shown transiently in the status bar and then lost, with no record of the underlying error. "Incorrect function" is ERROR_INVALID_FUNCTION (Win32 1), which FileSystemWatcher commonly raises on shares that don't support change notifications; the poll fallback covers it, but there was no durable record to confirm what else was happening.

  • DiagnosticLog (new) - thread-safe append-only log at %APPDATA%\TaylerLogTailer\logs\diagnostic.log. Each session starts with a header recording the app version, OS, .NET runtime, process bitness, settings path, and the set of watched windows. Entries are ISO-8601 timestamped and include the exception type, message, and HResult / Win32 code. Rolls to diagnostic.log.1 past 1 MB. Logging never throws.
  • AppInfo (new) - exposes the app version (from MinVer's informational version, build metadata trimmed) and product name.
  • FolderTailer / FileTailer - log watcher creation failures, watcher interruptions (with the full exception), poll errors, the file-limit notice, and per-file read failures. File read errors are de-duplicated per distinct message, and a resume is logged when reading recovers, so a persistently failing file does not flood the log.
  • FolderWindow - a Log toolbar button opens a transient window that live-tails the diagnostic log folder (marked Ephemeral via a new JsonIgnore flag on FolderConfig, so it is not remembered across runs). The status bar now shows the running version at its right-hand end, with the log path in its tooltip.
  • README documents the diagnostic log, the Log button, and the version display.

How was this tested?

  • dotnet build Tayler.slnx -c Release - 0 errors, 0 warnings (via build.ps1)
  • Launched the app and confirmed the session header (version 1.3.12, OS, .NET, settings path, watched windows) is written to diagnostic.log.
  • Invoked the Log button via UI Automation and confirmed it opens a window live-tailing the log folder, with the version shown in its status bar.

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? Adds a persistent diagnostic error log and makes it (and the running version) reachable from the UI, so intermittent problems - especially on network shares - can be investigated after the fact. Motivation: a watcher interruption on a share (`File watcher interrupted; relying on periodic polling (Incorrect function)`) was only shown transiently in the status bar and then lost, with no record of the underlying error. "Incorrect function" is `ERROR_INVALID_FUNCTION` (Win32 1), which `FileSystemWatcher` commonly raises on shares that don't support change notifications; the poll fallback covers it, but there was no durable record to confirm what else was happening. - **`DiagnosticLog`** (new) - thread-safe append-only log at `%APPDATA%\TaylerLogTailer\logs\diagnostic.log`. Each session starts with a header recording the app version, OS, .NET runtime, process bitness, settings path, and the set of watched windows. Entries are ISO-8601 timestamped and include the exception type, message, and HResult / Win32 code. Rolls to `diagnostic.log.1` past 1 MB. Logging never throws. - **`AppInfo`** (new) - exposes the app version (from MinVer's informational version, build metadata trimmed) and product name. - **`FolderTailer` / `FileTailer`** - log watcher creation failures, watcher interruptions (with the full exception), poll errors, the file-limit notice, and per-file read failures. File read errors are de-duplicated per distinct message, and a resume is logged when reading recovers, so a persistently failing file does not flood the log. - **`FolderWindow`** - a **Log** toolbar button opens a transient window that live-tails the diagnostic log folder (marked `Ephemeral` via a new `JsonIgnore` flag on `FolderConfig`, so it is not remembered across runs). The status bar now shows the running version at its right-hand end, with the log path in its tooltip. - **README** documents the diagnostic log, the Log button, and the version display. ## How was this tested? - [x] `dotnet build Tayler.slnx -c Release` - 0 errors, 0 warnings (via `build.ps1`) - [x] Launched the app and confirmed the session header (version 1.3.12, OS, .NET, settings path, watched windows) is written to `diagnostic.log`. - [x] Invoked the **Log** button via UI Automation and confirmed it opens a window live-tailing the log folder, with the version shown in its status bar. ## 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
Non-fatal problems (watcher errors, file read / access failures) were only shown
transiently in the status bar and then lost, which made intermittent network-
share issues hard to investigate. Add a persistent diagnostic log and make it
and the running version easy to reach from the UI.

- DiagnosticLog (new) - thread-safe append-only log at
  %APPDATA%\TaylerLogTailer\logs\diagnostic.log. Each session starts with a
  header recording the app version, OS, .NET runtime, process bitness, settings
  path, and the set of watched windows. Entries are ISO-8601 timestamped and
  include the exception type, message, and HResult / Win32 code. Rolls to
  diagnostic.log.1 past 1 MB. Logging never throws.
- AppInfo (new) - exposes the app version (from MinVer's informational version,
  build metadata trimmed) and product name.
- FolderTailer / FileTailer - log watcher creation failures, watcher
  interruptions (with the full exception, e.g. the "Incorrect function" /
  ERROR_INVALID_FUNCTION seen on some shares), poll errors, the file-limit
  notice, and per-file read failures. File read errors are de-duplicated per
  distinct message and a resume is logged when reading recovers, so a
  persistently failing file does not flood the log.
- FolderWindow - a "Log" toolbar button opens a transient window that live-tails
  the diagnostic log folder (marked Ephemeral via a new JsonIgnore flag on
  FolderConfig, so it is not remembered across runs). The status bar now shows
  the running version at its right-hand end, with the log path in its tooltip.
- App writes the session header at startup.
- README documents the diagnostic log, the Log button, and the version display.

Verified: build 0/0; launched the app, confirmed the session header (version
1.3.12, OS, .NET, settings, windows) is written, invoked the Log button via UI
Automation and confirmed it opens a window tailing the log with the version in
its status bar.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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!13
No description provided.