FastLogr 1.0.0

dotnet add package FastLogr --version 1.0.0                
NuGet\Install-Package FastLogr -Version 1.0.0                
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="FastLogr" Version="1.0.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add FastLogr --version 1.0.0                
#r "nuget: FastLogr, 1.0.0"                
#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 FastLogr as a Cake Addin
#addin nuget:?package=FastLogr&version=1.0.0

// Install FastLogr as a Cake Tool
#tool nuget:?package=FastLogr&version=1.0.0                

Pipeline GitHub issues

FastLogr <img src="https://github.com/MichaelHochriegl/FastLogr/blob/main/FastLogr_noBorder_64x64.png?raw=true" height="30" width="30" >

A less convoluted approach to the newly introduced high-performance logging Microsoft recently introduced.

Purpose

Microsoft introduced a new warning CA1848: Use the LoggerMessage delegates that links to the page describing high-performance logging by either writing an Action for your log message or, by using their source generated approach.

As I'm not really a fan of either of those proposed ways I created this package. FastLogr tries to combine both approaches that MS suggests and do it in a more elegant way. It also uses source generators to limit what you have to code, but instead of the MS approach with way less hassle.

The following sections compare the MS approach and the FastLogr approach.

MS Approach

To get the MS source gen going you need to make your class partial and also provide a static, partial method.

namespace FastLogr.Example.WorkerService;

public partial class MsApproach
{
    [LoggerMessage(
        EventId = 0,
        Level = LogLevel.Critical,
        Message = "Could not open socket to `{hostName}`")]
    public static partial void CouldNotOpenSocket(
        ILogger logger, string hostName);
}

The code generated by this looks like this:

// <auto-generated/>
#nullable enable

namespace FastLogr.Example.WorkerService
{
    partial class MsApproach
    {
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "7.0.8.27404")]
        private static readonly global::System.Action<global::Microsoft.Extensions.Logging.ILogger, global::System.String, global::System.Exception?> __CouldNotOpenSocketCallback =
            global::Microsoft.Extensions.Logging.LoggerMessage.Define<global::System.String>(global::Microsoft.Extensions.Logging.LogLevel.Critical, new global::Microsoft.Extensions.Logging.EventId(0, nameof(CouldNotOpenSocket)), "Could not open socket to `{hostName}`", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true }); 

        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "7.0.8.27404")]
        public static partial void CouldNotOpenSocket(global::Microsoft.Extensions.Logging.ILogger logger, global::System.String hostName)
        {
            if (logger.IsEnabled(global::Microsoft.Extensions.Logging.LogLevel.Critical))
            {
                __CouldNotOpenSocketCallback(logger, hostName, null);
            }
        }
    }
}

This is just one example of how you can get the MS way going, more can be found in the documentation.

FastLogr Approach

To get the FastLogr source gen going you simply need to provide an Action with the parameters you want to log.

using FastLogr.Attributes;

namespace FastLogr.Example.WorkerService;

public class FastLogrApproach
{
    [LogMessage(MessageTemplate = "Writing log with FastLogr, my message was '{message}'", LogLevel = LogLevel.Critical, EventId = 0)]
    private static Action<string> LogFastLogrMessage = default!;
}

No need to mark your class as partial just for the sake of logging. The generated code will look like this:

using System;
using Microsoft.Extensions.Logging;
using FastLogr.Attributes;

namespace SourceGenPlayground.Example.Worker;
public static class LogFastLogrMessageExtensions
{
    private static readonly Action<ILogger, string, Exception> s_logFastLogrMessage = LoggerMessage.Define<string>(LogLevel.Critical, new EventId(0, ""), "Writing log with FastLogr, my message was '{message}'");
    public static void LogFastLogrMessage(this ILogger logger, string arg1) => s_logFastLogrMessage(logger, arg1, default !);
}

The usage of the FastLogr approach is simple, as it provides you with an extension method on your ILogger instance:

using FastLogr.Attributes;
using SourceGenPlayground.Example.Worker;

namespace FastLogr.Example.WorkerService;

public class FastLogrApproach
{
    private readonly ILogger<FastLogrApproach> _logger;

    [LogMessage(MessageTemplate = "Writing log with FastLogr, my message was '{message}'", LogLevel = LogLevel.Critical, EventId = 0)]
    private static Action<string> LogFastLogrMessage = default!;

    public FastLogrApproach(ILogger<FastLogrApproach> logger)
    {
        _logger = logger;
        _logger.LogFastLogrMessage("MyCustomMessage");
    }
}

Installation

FastLogr is published as a nuget package, so installation is simple:

dotnet add package FastLogr

There are also YOLO packages pushed here on this Github repository.

Usage

You define your log message as a combination of the LogMessage attribute and an Action with the parameter types you want to pass to your log message.

using FastLogr.Attributes;
using SourceGenPlayground.Example.Worker;

namespace FastLogr.Example.WorkerService;

public class FastLogrApproach
{
    private readonly ILogger<FastLogrApproach> _logger;

    [LogMessage(MessageTemplate = "Writing log with FastLogr, my message was '{message}'", LogLevel = LogLevel.Critical, EventId = 0)]
    private static Action<string> LogFastLogrMessage = default!;

    public FastLogrApproach(ILogger<FastLogrApproach> logger)
    {
        _logger = logger;
        _logger.LogFastLogrMessage("MyCustomMessage");
    }
}

As shown above FastLogr will generate an extension method for ILogger and you can use it right away.

The types you want to log can be pretty much anything, e.g.:

using FastLogr.Attributes;

namespace FastLogr.Example.WorkerService;

public class FastLogrApproach
{
    private readonly ILogger<FastLogrApproach> _logger;

    [LogMessage(MessageTemplate = "Writing log with FastLogr, my message was '{message}'", LogLevel = LogLevel.Critical, EventId = 0)]
    private static Action<string, FancyType> LogFastLogrMessage = default!;

    public FastLogrApproach(ILogger<FastLogrApproach> logger)
    {
        _logger = logger;
        _logger.LogFastLogrMessage("MyCustomMessage", new FancyType("fany message", 420, true));
    }
}

public record FancyType(string FancyTypeString, int FancyTypeInt, bool FancyTypeBool);

Any usings that your class has will also be available to the ILogger extension built by FastLogr.

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 was computed.  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. 
.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 was computed.  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.
  • .NETStandard 2.0

    • No dependencies.

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 324 8/9/2023