You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Replace the hand-rolled Confuser.Core.ILogger interface and its 5 custom implementations with the industry-standard Microsoft.Extensions.Logging abstraction backed by Serilog as the logging provider. The objective is to eliminate custom logging maintenance, gain battle-tested features for free, and align with .NET ecosystem conventions.
Why — The Problem with Custom Logging
We currently maintain a custom ILogger interface (13 methods) with 5 separate implementations:
Implementation
Location
Maintenance concern
ConsoleLogger
CLI/Program.cs
No progress display, no level filtering, no file output
ProtectTabVM
GUI ViewModel
Tightly coupled to WPF FlowDocument rendering
MSBuildLogger
MSBuild.Tasks
Probable bug in Finish() — HasError = false when !successful
PackerLogger
Core/Packer.cs
Decorator wrapping another ILogger
NullLogger
Core/NullLogger.cs
Contains dead code (BeginModule/EndModule)
Every improvement we want (level filtering, timestamps, file output, verbosity flags) requires manual implementation across all 5. This is ongoing maintenance burden for solved problems.
Current limitations (all would need DIY implementation):
No log level filtering — cannot suppress Debug in production
No --verbose / --quiet CLI flags
No timestamps on individual log lines
No file output — users must redirect stdout
No structured logging
5 bare catch blocks swallowing exceptions silently
CLI has no progress display (Progress/EndProgress are no-ops)
No log context/scope — callers manually embed module/phase names
What This Would Improve
Improvement
Current (DIY)
After (built-in)
Log level filtering
Not possible
LogLevel.Debug, LogLevel.Warning, etc. — one-line config
CLI verbosity (-v/-vv/-vvv)
Not implemented
Maps directly to LogEventLevel (Verbose, Debug, Information, Warning)
File output
Not implemented
Serilog.Sinks.File — one line of config
Timestamps
Not implemented
Built into every sink's formatter
Structured logging
Not possible
Native to Serilog — Log.Information("Loading {Module}", name)
Console formatting
Basic color only
Serilog.Sinks.Console with templates, themes
MSBuild integration
Buggy custom impl
Clean adapter to TaskLoggingHelper
GUI integration
Tightly coupled
Custom WPF sink (~30 lines), cleanly decoupled
Net result: delete 5 logger implementations, replace with ~30 lines of Serilog configuration.
Serilog provides the actual output engine with rich formatting and sinks
Any future .NET library we consume or expose will expect M.E.L
Separates the "what to log" (M.E.L interface) from "where to log" (Serilog sinks)
Why not NLog: Less modern API, XML-based config, less ecosystem momentum. Why not Serilog alone: No standard abstraction — locks us into Serilog's API surface. Why not M.E.L alone: Needs separate provider packages for actual output. Serilog is the best provider.
Phase 1: Add packages, create thin adapter (old ILogger → Serilog)
Existing code keeps working, zero breaking changes.
Phase 2: New code uses M.E.L ILogger<T> directly.
Old ILogger calls still work through adapter.
Phase 3: Incrementally replace old ILogger calls across 27 files.
Each file is a small, reviewable PR.
Phase 4: Remove Confuser.Core.ILogger interface and all custom implementations.
Adapter deleted. Migration complete.
Possible Caveats
net461 compatibility: Microsoft.Extensions.Logging.Abstractions supports netstandard2.0, so it works on net461. However, it adds ~3 NuGet packages to what has been a deliberately lean dependency tree. After the .NET 10 retarget (Retarget GUI and CLI to .NET 10 #53), M.E.L ships with the framework and the extra packages go away.
Name collision: Both our custom Confuser.Core.ILogger and M.E.L define ILogger. During migration (Phases 1-3), both will coexist. Callers will need using aliases or fully-qualified names. This is temporary but annoying.
GUI sink: No off-the-shelf Serilog sink writes to a WPF FlowDocument. We'll need a small custom sink (~30 lines) that marshals log events to the UI thread. This replaces the current 80+ line ProtectTabVM logger implementation — net reduction.
Progress reporting: Serilog doesn't have a native "progress" concept. We'd keep the Progress(int, int) / EndProgress() methods as a separate IProgressReporter interface, or use a Serilog enricher. This needs design thought.
Timing: This work overlaps significantly with Retarget GUI and CLI to .NET 10 #53 (Retarget to .NET 10). Doing both together reduces churn — M.E.L becomes a built-in dependency on net10.0. Doing logging first on net461 means carrying extra NuGet packages temporarily.
Recommendation
Implement as part of #53 (.NET 10 retarget) to minimize dependency churn. Phase 1 (adapter) can land earlier if needed for immediate debugging improvements.
Goal
Replace the hand-rolled
Confuser.Core.ILoggerinterface and its 5 custom implementations with the industry-standardMicrosoft.Extensions.Loggingabstraction backed by Serilog as the logging provider. The objective is to eliminate custom logging maintenance, gain battle-tested features for free, and align with .NET ecosystem conventions.Why — The Problem with Custom Logging
We currently maintain a custom
ILoggerinterface (13 methods) with 5 separate implementations:ConsoleLoggerProtectTabVMMSBuildLoggerFinish()—HasError = falsewhen!successfulPackerLoggerNullLoggerBeginModule/EndModule)Every improvement we want (level filtering, timestamps, file output, verbosity flags) requires manual implementation across all 5. This is ongoing maintenance burden for solved problems.
Current limitations (all would need DIY implementation):
--verbose/--quietCLI flagscatchblocks swallowing exceptions silentlyWhat This Would Improve
LogLevel.Debug,LogLevel.Warning, etc. — one-line config-v/-vv/-vvv)LogEventLevel(Verbose, Debug, Information, Warning)Serilog.Sinks.File— one line of configLog.Information("Loading {Module}", name)Serilog.Sinks.Consolewith templates, themesTaskLoggingHelperNet result: delete 5 logger implementations, replace with ~30 lines of Serilog configuration.
Proposed Approach
Library Choice: M.E.L abstraction + Serilog provider
Why M.E.L + Serilog (not just Serilog alone):
Why not NLog: Less modern API, XML-based config, less ecosystem momentum.
Why not Serilog alone: No standard abstraction — locks us into Serilog's API surface.
Why not M.E.L alone: Needs separate provider packages for actual output. Serilog is the best provider.
CLI Verbosity Design
Migration Path
Possible Caveats
net461 compatibility:
Microsoft.Extensions.Logging.Abstractionssupports netstandard2.0, so it works on net461. However, it adds ~3 NuGet packages to what has been a deliberately lean dependency tree. After the .NET 10 retarget (Retarget GUI and CLI to .NET 10 #53), M.E.L ships with the framework and the extra packages go away.Name collision: Both our custom
Confuser.Core.ILoggerand M.E.L defineILogger. During migration (Phases 1-3), both will coexist. Callers will needusingaliases or fully-qualified names. This is temporary but annoying.GUI sink: No off-the-shelf Serilog sink writes to a WPF FlowDocument. We'll need a small custom sink (~30 lines) that marshals log events to the UI thread. This replaces the current 80+ line
ProtectTabVMlogger implementation — net reduction.Progress reporting: Serilog doesn't have a native "progress" concept. We'd keep the
Progress(int, int)/EndProgress()methods as a separateIProgressReporterinterface, or use a Serilog enricher. This needs design thought.Timing: This work overlaps significantly with Retarget GUI and CLI to .NET 10 #53 (Retarget to .NET 10). Doing both together reduces churn — M.E.L becomes a built-in dependency on net10.0. Doing logging first on net461 means carrying extra NuGet packages temporarily.
Recommendation
Implement as part of #53 (.NET 10 retarget) to minimize dependency churn. Phase 1 (adapter) can land earlier if needed for immediate debugging improvements.
Related Issues