KhaosKode.Logging
1.0.7
This was a bit of an experiment to see how to use nuget. I understand a tiny bit more now than before. Please feel free to look at the KhaosKoder.* series of packages. They replace this package - with absolutely minimal code changes required. I will try to keep the packages stable under those names from here on.
dotnet add package KhaosKode.Logging --version 1.0.7
NuGet\Install-Package KhaosKode.Logging -Version 1.0.7
<PackageReference Include="KhaosKode.Logging" Version="1.0.7" />
<PackageVersion Include="KhaosKode.Logging" Version="1.0.7" />
<PackageReference Include="KhaosKode.Logging" />
paket add KhaosKode.Logging --version 1.0.7
#r "nuget: KhaosKode.Logging, 1.0.7"
#:package KhaosKode.Logging@1.0.7
#addin nuget:?package=KhaosKode.Logging&version=1.0.7
#tool nuget:?package=KhaosKode.Logging&version=1.0.7
Khaos.Logging
Typed, discoverable logging built on top of Microsoft.Extensions.Logging. Khaos.Logging lets you describe every loggable event once—as an enum—and generates a fully navigable logger surface so you can write _log.DB.Connection.Open.LogInformation("Opening connection") without manually wiring scopes, event IDs, or categories.
Why Another Logging Layer?
ILogger is flexible, but large applications end up with stringly-typed event IDs, ad-hoc scopes, and no shared vocabulary. We wanted:
- A single source of truth for events (enums) that doubles as documentation.
- Automatic, hierarchical loggers that mirror your domain while preserving
ILogger<T>categories. - Guardrails: analyzers that catch duplicate IDs, naming mistakes, or invalid values.
- Zero runtime reflection and no magic DI setup—everything compiles ahead of time.
Khaos.Logging keeps ILogger in the picture; it simply builds strongly-typed façades over it so your team can reason about events the same way they reason about APIs.
How It Works
- Annotate an enum with
[LogEventSource]and follow theAREA_Group_Actionnaming convention. - The incremental source generator emits:
- A root logger (customizable name) and nested loggers for each area/group token.
IEventLoggerproperties per enum member, prewired withEventIdand anEventPathscope.- A DI extension
AddGeneratedLogging()registering everything as scoped generics.
- The runtime provides the lightweight
EventLoggerimplementation and attribute definitions. - The analyzer project enforces duplicate-ID detection, naming guidance, and other correctness checks.
Quick Start
Install the package
dotnet add package KhaosCode.LoggingDeclare your log events
using Khaos.Logging; namespace MyApp.Logging; [LogEventSource(LoggerRootTypeName = "MyLogger", BasePath = "MyApp")] public enum LogEventIds { APP_Startup = 1000, APP_ReadConfiguration = 1001, DB_Connection_Open = 2000, DB_Connection_Close = 2001 }Register generated loggers
builder.Services.AddLogging(); builder.Services.AddGeneratedLogging();Or use Serilog with LogStash:
builder.Services.AddKhaosSerilogLogging(options => { options.WriteToConsole = true; options.LogStash = new LogStashOptions { Host = "elk.example.com", Port = 5044, ApplicationName = "MyApp" }; }); builder.Services.AddGeneratedLogging();Inject and use
public sealed class StartupService { private readonly MyLogger<StartupService> _log; public StartupService(MyLogger<StartupService> log) => _log = log; public void Start() { _log.App.Startup.LogInformation("StartupService online"); _log.DB.Connection.Open.LogDebug("Opening DB for {Tenant}", "Contoso"); } }
Generated loggers always respect ILogger<T> categories, emit scopes with EventPath = "MyApp.DB.Connection.Open", and keep the enum value wired to EventId.Id. You can still inject a plain ILogger<T> anywhere—it remains the same DI container and the two coexist without adapters.
FAQ: Why Not Just Use ILogger?
You absolutely can (and still do). Khaos.Logging is a layer on top of ILogger that eliminates repetitive plumbing:
- Discoverability: Instead of searching for numeric IDs or message templates, IDE completion guides you through areas/groups/actions.
- Consistency: Event IDs, names, and scopes are generated from the enum, so they cannot drift.
- Safety nets: The analyzers fail the build if you accidentally duplicate IDs or misapply attributes.
When a dependency expects ILogger you keep supplying ILogger; generated loggers internally use the same ILogger<T> instances, so you can mix and match without wrappers. Think of the generated APIs as purpose-built entry points into the existing logging infrastructure, not a replacement.
Serilog Integration
For production scenarios requiring structured logging to ELK/LogStash, install the Serilog package:
dotnet add package KhaosCode.Logging.Serilog
See the User Guide for full configuration options.
Design Principles
- Enums as contracts: Everything—EventId, scope metadata, documentation—derives from the annotated enum.
- Hierarchical surface: Area/group/action tokens become nested types, mirroring the shape of your domain.
- No runtime surprises: All code is generated at build time; DI registration is explicit and scoped.
- Pluggable backends: Use Microsoft.Extensions.Logging (default) or Serilog with LogStash.
- Documentation included: The NuGet ships the
docs/folder plus build-transitive targets that copy it into consuming solutions for easy reference.
Documentation
- Specification – end-to-end, low-level requirements.
- User Guide – installation, configuration, and day-to-day usage tips.
- Developer Guide – repo layout, build/test workflow, release checklist.
- Versioning Guide – explains MinVer tagging conventions and release numbering.
- Scripts Reference – details each helper script, parameters, and expected output.
Explore the guides, run scripts/test-with-coverage.ps1, and open TestResults/.../coverage-html/index.html to see test coverage while you iterate. When you're ready to publish, scripts/publish.ps1 -ApiKey <token> handles packing and pushing both the runtime and symbol packages.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated | |
|---|---|---|---|
| 1.0.7 | 100 | 3/12/2026 |