Adopt injectable Microsoft.Extensions.Logging logging model#381
Merged
Conversation
Replace the Serilog-typed LogOptions.Logger with a backend-agnostic, injectable ILoggerFactory (LogOptions.SetFactory / TrySetFactory), so consumers can plug in any logging backend. This mirrors the LanguageTags project and removes the library's Serilog dependency; the library now depends only on Microsoft.Extensions.Logging.Abstractions. - FileEx and Download resolve per-class cached loggers via LogOptions.CreateLogger and emit source-generated [LoggerMessage] messages, keeping the build clean under AnalysisMode=All. - Move LogAndHandle / LogAndPropagate onto ILogger as internal helpers. - Rename the public Extensions class to CompressExtensions to resolve the clash with the Microsoft.Extensions namespace. - Wire a Serilog console logger into the Sandbox via SerilogLoggerFactory. - Migrate the test suite from xUnit asserts to AwesomeAssertions. Removing LogOptions.Logger and renaming Extensions are breaking API changes, shipped as the next minor version (3.7).
Contributor
There was a problem hiding this comment.
Pull request overview
This pull request migrates the library’s logging from a Serilog-coupled global logger to an injectable Microsoft.Extensions.Logging model, making the core library backend-agnostic while keeping the Sandbox as a Serilog-based wiring example.
Changes:
- Replaced
LogOptions.Loggerwith a thread-safe, injectableILoggerFactorymodel and updatedFileEx/Downloadto log through cachedILoggerinstances with[LoggerMessage]source-generated calls. - Renamed the public compression extensions type to
CompressExtensionsand moved logger helpers ontoMicrosoft.Extensions.Logging.ILoggeras internal extensions (exposed to tests viaInternalsVisibleTo). - Migrated tests to AwesomeAssertions and added coverage for
LogOptions.
Reviewed changes
Copilot reviewed 26 out of 26 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| version.json | Bumps the minor version for the logging model change. |
| Directory.Packages.props | Adds central versions for AwesomeAssertions and logging abstractions, plus sandbox logging bridge. |
| Utilities/Utilities.csproj | Drops Serilog dependency, adds Microsoft.Extensions.Logging.Abstractions, and exposes internals to tests. |
| Utilities/LogOptions.cs | Implements global ILoggerFactory configuration and logger creation logic. |
| Utilities/FileEx.cs | Switches retry/error logging to Microsoft.Extensions.Logging via cached ILogger. |
| Utilities/Download.cs | Switches exception logging to Microsoft.Extensions.Logging via cached ILogger. |
| Utilities/Extensions.cs | Renames compression extensions type and introduces internal logger helper extensions + [LoggerMessage] methods. |
| Sandbox/Sandbox.csproj | Sets RootNamespace and adds Serilog.Extensions.Logging for factory injection. |
| Sandbox/Program.cs | Configures Serilog and injects an ILoggerFactory into LogOptions for the sample app. |
| Sandbox/LoggerFactory.cs | Provides a Serilog-backed Microsoft.Extensions.Logging.ILoggerFactory for the sandbox. |
| UtilitiesTests/UtilitiesTests.csproj | Adds AwesomeAssertions + logging abstractions, removes Serilog package reference. |
| UtilitiesTests/GlobalUsings.cs | Adds global using for AwesomeAssertions. |
| UtilitiesTests/LogOptionsTests.cs | Adds tests validating LogOptions factory behavior and logger creation. |
| UtilitiesTests/StringHistoryTests.cs | Converts assertions to AwesomeAssertions. |
| UtilitiesTests/StringCompressionTests.cs | Converts assertions to AwesomeAssertions. |
| UtilitiesTests/StringCompressionAsyncTests.cs | Converts assertions to AwesomeAssertions (including async exception assertions). |
| UtilitiesTests/ExtensionsTests.cs | Updates logger helper tests to use Microsoft.Extensions.Logging and converts assertions. |
| UtilitiesTests/FormatTests.cs | Converts assertions to AwesomeAssertions. |
| UtilitiesTests/FileTests.cs | Converts assertions to AwesomeAssertions. |
| UtilitiesTests/FileExAsyncTests.cs | Converts assertions to AwesomeAssertions. |
| UtilitiesTests/DownloadTests.cs | Converts assertions to AwesomeAssertions. |
| UtilitiesTests/DownloadAsyncTests.cs | Converts assertions to AwesomeAssertions. |
| UtilitiesTests/ConsoleTests.cs | Converts assertions to AwesomeAssertions. |
| UtilitiesTests/CommandLineTests.cs | Converts assertions to AwesomeAssertions. |
| README.md | Updates release note summary for v3.7 to describe the logging model change. |
| HISTORY.md | Adds detailed v3.7 release notes for the logging refactor and breaking changes. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #381 +/- ##
===========================================
+ Coverage 36.55% 42.77% +6.21%
===========================================
Files 10 10
Lines 1045 1010 -35
Branches 93 100 +7
===========================================
+ Hits 382 432 +50
+ Misses 639 532 -107
- Partials 24 46 +22 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
- Read LoggerFactory once in CreateLogger so a concurrent swap cannot split the reference check and logger creation across two instances. - Correct the AwesomeAssertions subject/expected order in FormatTests and FileTests so failure messages report actual vs expected correctly. - Add a CreateLogger<T> test covering the generic category overload. - Add codecov.yml: ignore the Sandbox example app and make the coverage statuses report-only, matching the report-only upload configuration.
This was referenced Jul 9, 2026
ptr727
added a commit
that referenced
this pull request
Jul 10, 2026
Promotes the 3.7 release from develop to main. **Contents** - #381 - Adopt an injectable `Microsoft.Extensions.Logging` logging model: `LogOptions.SetFactory(ILoggerFactory)` replaces the removed Serilog-typed `LogOptions.Logger`; source-generated `[LoggerMessage]` logging in `FileEx`/`Download`; `Extensions` renamed to `CompressExtensions`; Serilog-wired `Sandbox`; test suite migrated to AwesomeAssertions. - #382 - Gitignore test coverage output and drop an accidentally-committed report. **Release impact:** merging publishes the stable **3.7** package to NuGet (breaking API changes: `LogOptions.Logger` removed, `Extensions` renamed). No issues to close. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This was referenced Jul 10, 2026
LogOptions.CreateLogger reads LoggerFactory twice — check/create TOCTOU race
ptr727/LanguageTags#252
Closed
ptr727
added a commit
to ptr727/LanguageTags
that referenced
this pull request
Jul 10, 2026
Fixes #252. ## Problem `LogOptions.CreateLogger(string)` read the `LoggerFactory` property twice — once for the `ReferenceEquals` guard and once for the actual `CreateLogger` call. Since the backing field is swapped with `Interlocked.Exchange`, a concurrent `SetFactory` could make the guard and the create observe different factory instances, defeating the thread-safe intent of the `Volatile`/`Interlocked` design. ## Fix Read the factory once into a local and use it for both the check and the create. Also splits the `<remarks>` em-dash into two ASCII sentences, matching the sibling `ptr727.Utilities` fix (ptr727/Utilities#381). ## Verification `dotnet test` — build clean, 296/296 pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
This was referenced Jul 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adopts the backend-agnostic logging model used by the LanguageTags project, replacing the Serilog-typed
LogOptions.Loggerwith an injectableMicrosoft.Extensions.Loggingfactory.Library
LogOptionsnow exposes a thread-safe, injectableILoggerFactoryviaSetFactory/TrySetFactory, falling back toNullLogger. The library depends only onMicrosoft.Extensions.Logging.Abstractions; the Serilog dependency and itsIL3058AOT suppression are gone.FileExandDownloadresolve per-class cached loggers throughLogOptions.CreateLoggerand emit source-generated[LoggerMessage]messages (keeps the build clean underAnalysisMode=All+TreatWarningsAsErrors).LogAndHandle/LogAndPropagatemoved ontoMicrosoft.Extensions.Logging.ILoggeras internal helpers (exposed to tests viaInternalsVisibleTo).Extensionsclass is renamed toCompressExtensions, resolving the naming clash with theMicrosoft.Extensionsnamespace.Sandbox
SerilogLoggerFactory, borrowing the pattern fromLanguageTagsCreate.Tests
LogOptionsTests.Breaking changes
LogOptions.Loggeris removed — configure logging withLogOptions.SetFactory(ILoggerFactory).Extensionsclass is renamed toCompressExtensions(instance-style extension calls such asvalue.Compress()are unaffected).Shipped as the next minor version (3.7); README and HISTORY updated.
Verification
dotnet format stylepass.FormatTests.BytestoKilo/BytestoKibinumber-formatting failures (present on the clean tree, unrelated to this change).Sandboxprints the themed console line end-to-end, confirming the factory wiring.🤖 Generated with Claude Code