An implementation of ILogger and ILogger<T> from Microsoft.Extensions.Logging that writes log entries to an in-memory collection. Designed for unit and integration tests where you need to assert against logged messages.
dotnet add package Wolfgang.Extensions.Logging.InMemoryLoggerNuGet Package: Wolfgang.Extensions.Logging.InMemoryLogger
This project is licensed under the MIT License. See the LICENSE file for details.
- GitHub Repository: https://github.com/Chris-Wolfgang/In-memory-Logger
- API Documentation: https://Chris-Wolfgang.github.io/In-memory-Logger/
- CHANGELOG: CHANGELOG.md
- Contributing Guide: CONTRIBUTING.md
- DocFX Version Picker Troubleshooting: docs/DOCFX-VERSION-PICKER.md
- Thread-safe in-memory log entry storage.
- Configurable minimum log level (passed to the constructor; defaults to
LogLevel.Trace). - Configurable initial capacity (defaults to
16). - Supports all .NET log levels (
TracethroughCritical). - Captures scope state via
BeginScopefor assertion in tests. - Returns log entries as
IReadOnlyList<LogEntry<object>>for easy LINQ + assertion patterns. - Ships both a non-generic
InMemoryLogger(constructed with a category string) and a genericInMemoryLogger<T>(category derived fromtypeof(T)), matching the standardILogger/ILogger<T>shape.
using Microsoft.Extensions.Logging;
using Wolfgang.Extensions.Logging.InMemoryLogger;
// Generic form — category is "MyApp.MyService"
var logger = new InMemoryLogger<MyService>(LogLevel.Information);
// Use the logger in code under test
var service = new MyService(logger);
service.DoWork();
// Assert against captured log entries
Assert.Single(logger.LogEntries);
Assert.Equal(LogLevel.Information, logger.LogEntries[0].LogLevel);The non-generic form takes a category string directly:
var logger = new InMemoryLogger("MyCategory", LogLevel.Warning, capacity: 32);This library targets:
- .NET Framework: 4.6.2
- .NET Standard: 2.0, 2.1
- .NET: 8.0, 10.0
See the NuGet package page for the authoritative per-TFM compatibility matrix.
This project is held to the canonical analyzer set used across all Chris-Wolfgang .NET libraries. Analyzers run on every build and are treated as errors in Release.
- Microsoft.CodeAnalysis.NetAnalyzers — built-in .NET analyzers (correctness and performance)
- Roslynator.Analyzers — refactoring and code quality
- AsyncFixer — async/await best practices
- Microsoft.VisualStudio.Threading.Analyzers — thread safety
- Microsoft.CodeAnalysis.BannedApiAnalyzers — enforces the
BannedSymbols.txtpolicy - Meziantou.Analyzer — broad code-quality rules
- SonarAnalyzer.CSharp — industry-standard analysis
- Microsoft.CodeAnalysis.PublicApiAnalyzers — public-API surface tracking via
PublicAPI.Shipped.txt/PublicAPI.Unshipped.txt
BannedSymbols.txt is the canonical fleet baseline. Banned categories include blocking sync-over-async (Task.Result, Task.Wait()), Thread.Sleep, synchronous file I/O, and several legacy / deprecated APIs.
Contributions are welcome! Please see CONTRIBUTING.md for:
- Code quality standards
- Build and test instructions
- Pull request guidelines
- Analyzer configuration details