Skip to content

Add a rolling file logger, an in-memory file system, XDG state/cache homes and JSON options - #105

Merged
matt-edmondson merged 2 commits into
mainfrom
claude/project-thread-hoe8hl
Oct 11, 2026
Merged

matt-edmondson merged 2 commits into
mainfrom
claude/project-thread-hoe8hl

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Requested by Matt · project thread

Before: the only logger wrote to the console, so an app's warnings vanished on Windows; tests that needed a file system had to touch the disk; JsonSerializationProvider always used its own fixed options; and UserDirectories stopped at the data and config homes.

After: a rolling file logger, an in-memory IFileSystemProvider for tests, a JsonSerializationProvider(JsonSerializerOptions) constructor, and XDG state and cache homes beside the existing data and config helpers. This is the upstream half of ImageGui's "one app data root, with a log file" task.

How

  • ktsu.Essentials.LoggingProviders.File (new package): FileLoggingProvider + FileLoggingOptions (directory, file name, size limit, file count, minimum level). One line per entry, 2026-10-11T15:02:37.123Z WARN message, with line breaks and other terminators in messages and exceptions escaped. It writes through IFileSystemProvider, opening and closing the file per entry so no handle is held. It rolls log.txt → log.1.txt … before an entry would pass the size limit, and deletes the oldest past the count. Entries are serialized with a lock. I/O failures are dropped and counted in DroppedEntryCount rather than thrown. AddFileLoggingProvider(options) registers it beside other loggers. It isn't in AddEssentials(), since it needs a directory.
  • ktsu.Essentials.FileSystemProviders.InMemory (new package): InMemoryFileSystemProvider over Testably.Abstractions.Testing's MockFileSystem (7.1.1, which pins Testably.Abstractions 10.4). The mock is exposed for its helpers. It isn't in AddEssentials(), because resolving one IFileSystemProvider returns the last registered, and silently writing to memory would lose data.
  • UserDirectories: GetStateHome/GetCacheHome ($XDG_STATE_HOME or ~/.local/state, $XDG_CACHE_HOME or ~/.cache) plus GetApplicationStateDirectory/GetApplicationCacheDirectory. The data and config helpers were already public.
  • JSON: the new constructor copies the options. The parameterless one keeps indented output. There's also an AddJsonSerializationProvider(JsonSerializerOptions) overload, and the DI registration now shares one instance between the concrete type and the interface.
  • Both new projects set DisablePackageBaselineValidation, since no 2.5.2 baseline exists for them (NU1101). CLAUDE.md records this.
  • ktsu.Essentials.All references both new packages but doesn't register them.
  • Tests: FileLoggingProviderTests, InMemoryFileSystemProviderTests, JsonSerializationOptionsTests and UserDirectoriesTests. The shared file system contract now runs over the in-memory provider too. All 1015 tests pass locally on net10.0, three runs in a row. README and CLAUDE.md are updated.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QYkc2PGkdnFxuFB2jSeAyB


Generated by Claude Code

…e/cache homes and JSON options

- Essentials.LoggingProviders.File: FileLoggingProvider writes one line per entry through
  IFileSystemProvider, rolls past a size limit, keeps a bounded number of files, is thread-safe,
  and drops (and counts) entries it cannot write rather than throwing.
- Essentials.FileSystemProviders.InMemory: InMemoryFileSystemProvider over Testably's MockFileSystem,
  for tests. Not part of AddEssentials().
- UserDirectories: GetStateHome/GetCacheHome and their application-directory variants, beside the
  data and config helpers that were already public.
- JsonSerializationProvider(JsonSerializerOptions) and an AddJsonSerializationProvider overload.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYkc2PGkdnFxuFB2jSeAyB
@matt-edmondson matt-edmondson self-assigned this Oct 11, 2026
Comment thread Essentials/UserDirectories.cs Fixed
Comment thread Essentials.Tests/FileLoggingProviderTests.cs Fixed
Comment thread Essentials.Tests/InMemoryFileSystemProviderTests.cs Fixed
Comment thread Essentials.Tests/UserDirectoriesTests.cs Fixed
Comment thread Essentials.Tests/UserDirectoriesTests.cs Fixed
Comment thread Essentials.Tests/UserDirectoriesTests.cs Fixed
Comment thread Essentials.Tests/UserDirectoriesTests.cs Fixed
Comment thread Essentials.Tests/UserDirectoriesTests.cs Fixed
Comment thread Essentials.Tests/UserDirectoriesTests.cs Fixed
Comment thread Essentials.Tests/UserDirectoriesTests.cs Fixed
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYkc2PGkdnFxuFB2jSeAyB
@sonarqubecloud

Copy link
Copy Markdown

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