RandomSkunk.EasyLogger 1.0.0-rc1

This is a prerelease version of RandomSkunk.EasyLogger.
There is a newer version of this package available.
See the version list below for details.
dotnet add package RandomSkunk.EasyLogger --version 1.0.0-rc1                
NuGet\Install-Package RandomSkunk.EasyLogger -Version 1.0.0-rc1                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="RandomSkunk.EasyLogger" Version="1.0.0-rc1" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add RandomSkunk.EasyLogger --version 1.0.0-rc1                
#r "nuget: RandomSkunk.EasyLogger, 1.0.0-rc1"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install RandomSkunk.EasyLogger as a Cake Addin
#addin nuget:?package=RandomSkunk.EasyLogger&version=1.0.0-rc1&prerelease

// Install RandomSkunk.EasyLogger as a Cake Tool
#tool nuget:?package=RandomSkunk.EasyLogger&version=1.0.0-rc1&prerelease                

RandomSkunk.EasyLogging

This library provides two simple logger base classes, EasyLogger and EasyLogger<TCategoryName>, which implement ILogger and ILogger<TCategoryName> respectively.

What makes it an "easy" logger?

  • Correctly implementing the ILogger.BeginScope method is difficult.
    • EasyLogger takes care of it for you.
  • Implementing ILogger.IsEnabled isn't terribly difficult, but if you're not careful, you could end up writing logs at the None log level.
    • EasyLogger implements this method and doesn't accidentally write None logs.
  • Mocking the ILogger.Log in order to verify that a logging operation took place is difficult.
    • First, you need to deal with the generic type argument and the state parameter. It could be literally any type and any value. Where do you even begin?
    • What is the formatter parameter all about?
    • What about the logger's scope? What if you wanted to verify that the logger had a certain scope at the time of the log event? How would you mock that?
    • Mocking the EasyLogger.Write method to verify that a logging operation took place is easy.
  • The ease of mocking is tested and verified with Moq, FakeItEasy, and NSubstitute.

Mock Logger Setup and Verification

EasyLogger is easy to mock regardless of the mocking library - just specify that its abstract Write method should be the target for setup or verification.

Note that the LogEntry struct contains numerous methods for querying whether it is a match for a setup or verification. Methods used below in the examples are IsInformation, HasMessage, and HasAttribute.

Moq

Mock<EasyLogger> mockLogger = new Mock<EasyLogger>();
EasyLogger logger = mockLogger.Object;

LogEntry? capturedLogEntry = null;

// Setup
mockLogger.Setup(m => m.Write(It.IsAny<LogEntry>()))
    .Callback<LogEntry>(logEntry => capturedLogEntry = logEntry);

logger.LogInformation("Hello, {Who}!", "world");

// Verification
mockLogger.Verify(m => m.Write(It.Is<LogEntry>(log =>
    log.IsInformation() && log.HasMessage("Hello, world!") && log.HasAttribute("Who", "world"))));

FakeItEasy

EasyLogger logger = A.Fake<EasyLogger>();

LogEntry? capturedLogEntry = null;

// Setup
A.CallTo(() => logger.Write(A<LogEntry>.Ignored))
    .Invokes((LogEntry logEntry) => capturedLogEntry = logEntry);

logger.LogInformation("Hello, {Who}!", "world");

// Verification
A.CallTo(() => logger.Write(A<LogEntry>.That.Matches(log =>
    log.IsInformation() && log.HasMessage("Hello, world!") && log.HasAttribute("Who", "world"))))
    .MustHaveHappened();

NSubstitute

EasyLogger logger = Substitute.For<EasyLogger>();

LogEntry? capturedLogEntry = null;

// Setup
logger.When(m => m.Write(Arg.Any<LogEntry>()))
    .Do(x => capturedLogEntry = x.Arg<LogEntry>());

logger.LogInformation("Hello, {Who}!", "world");

// Verification
logger.Received().Write(Arg.Is<LogEntry>(log =>
    log.IsInformation() && log.HasMessage("Hello, world!") && log.HasAttribute("Who", "world")));
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 is compatible.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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.0 79 1/31/2025
1.0.0-rc1 61 1/30/2025