EgonsoftHU.Extensions.Logging.Serilog 10.0.1

Prefix Reserved

Requires NuGet 6.1.0 or higher.

dotnet add package EgonsoftHU.Extensions.Logging.Serilog --version 10.0.1
                    
NuGet\Install-Package EgonsoftHU.Extensions.Logging.Serilog -Version 10.0.1
                    
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="EgonsoftHU.Extensions.Logging.Serilog" Version="10.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="EgonsoftHU.Extensions.Logging.Serilog" Version="10.0.1" />
                    
Directory.Packages.props
<PackageReference Include="EgonsoftHU.Extensions.Logging.Serilog" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add EgonsoftHU.Extensions.Logging.Serilog --version 10.0.1
                    
#r "nuget: EgonsoftHU.Extensions.Logging.Serilog, 10.0.1"
                    
#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.
#:package EgonsoftHU.Extensions.Logging.Serilog@10.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=EgonsoftHU.Extensions.Logging.Serilog&version=10.0.1
                    
Install as a Cake Addin
#tool nuget:?package=EgonsoftHU.Extensions.Logging.Serilog&version=10.0.1
                    
Install as a Cake Tool

Egonsoft.HU Serilog Logging Extensions

GitHub Nuget Nuget

PropertyBagEnricher and C# extension methods for Serilog.ILogger.

Introduction

The motivation behind this project is as follows:

  • Enrich log events with the name of the source member (method, property, etc.) in which the log event occurs.
    • ILogger.Here() extension method.
    • PropertyBagEnricher.CreateForSourceMember() static factory method.
    • PropertyBagEnricher.Here() instance method.
  • Enrich log events with multiple properties at once using PropertyBagEnricher.
  • Populate Exception.Data dictionary with the log event properties.
    • Exception.Populate(PropertyBagEnricher) extension method.

Releases

You can download the package from nuget.org: EgonsoftHU.Extensions.Logging.Serilog

You can find the release notes here.

Releases under active support or development:

Version Release Date Latest Patch Version End of Support Targets
10.0 2026-10-20 10.0.1 2028-11-14 net8.0, net9.0, net10.0<br/>net472<br/>netstandard2.0, netstandard2.1

Breaking change

The project namespace has changed to avoid namespace collision with Serilog.
Please note: The package id will remain unchanged.

Version Namespace
>= 1.0.0 && < 2.0.0 EgonsoftHU.Extensions.Logging.Serilog
>= 2.0.0 EgonsoftHU.Extensions.Logging

Summary

SourceMember property

When you create a logger by calling Log.Logger.ForContext<T>() then the log events will contain a SourceContext property with the type name where the log event occurs.

This project helps you add a SourceMember property with the member name of the type where the log event occurs.

The SourceMember property name can be customized. See examples below.

PropertyBagEnricher : Serilog.Core.ILogEventEnricher

Each time you add a log event property (e.g. logger.ForContext("SomeProperty", 42)) a new logger instance will be created.

This enricher helps you reducing creating logger instances by adding multiple log event properties at once.

Exception.Data population

Exception.Data dictionary can contain additional user-defined information about the exception.

The log event properties the enricher contains can be populated into the Exception.Data dictionary using the Exception.Populate(PropertyBagEnricher) extension method. See example below.

Examples

ILogger.Here() - single use per method

using EgonsoftHU.Extensions.Logging;
using Serilog;

namespace SomeCompany.Services;

public class SomeService
{
    private readonly ILogger logger;

    // To inject a contextual logger using Autofac:
    // https://github.com/gcsizmadia/EgonsoftHU.Extensions.Logging.Serilog.Autofac
    public SomeService(ILogger logger)
    {
        this.logger = logger;
        logger.Here().Verbose("SomeService has been created");
    }

    public void DoSomething()
    {
        logger.Here().Information("We are doing something here");
    }
}

The log events and their properties will be:

{"SourceContext":"SomeCompany.Services.SomeService","SourceMember":".ctor","@l":"Verbose","@mt":"SomeService has been created","@t":"2022-05-08T12:34:56.1111111Z"}
{"SourceContext":"SomeCompany.Services.SomeService","SourceMember":"DoSomething","@l":"Information","@mt":"We are doing something here","@t":"2022-05-08T12:34:56.2222222Z"}

ILogger.Here() - multiple use per method

To reduce creating logger instances you can store the logger instance created by calling the Here() method.

using EgonsoftHU.Extensions.Logging;
using Serilog;

private void DoComplexThings()
{
    ILogger logger = this.logger.Here();

    // All the log events below will contain this log event property:
    // "SourceMember": "DoComplexThings"

    logger.Verbose("Preparing to do complex things");
    logger.Warning("Configuration not found, using default settings");
    logger.Verbose("Prepared to do complex things");
    logger.Information("Complex things done");
}

PropertyBagEnricher

To further reduce creating logger instances you can use the PropertyBagEnricher to add multiple log event properties at once.

using EgonsoftHU.Extensions.Logging;
using Serilog;

private void CalculateRectangleArea(int a, int b)
{
    logger
        .Here()
        .ForContext(
            PropertyBagEnricher
                .Create()
                .Add("SideA", a)
                .Add("SideB", b)
        )
        .Information("Rectangle area: {RectangleArea}", a * b);
}

You can also combine Here() with PropertyBagEnricher by using the CreateForSourceMember() factory method:

using EgonsoftHU.Extensions.Logging;
using Serilog;

private void CalculateRectangleArea(int a, int b)
{
    logger
        .ForContext(
            PropertyBagEnricher
                .CreateForSourceMember() // this will add the SourceMember property.
                .Add("SideA", a)
                .Add("SideB", b)
        )
        .Information("Rectangle area: {RectangleArea}", a * b);
}

Of course, you can store the enricher in a variable if you want to add other properties later:

using EgonsoftHU.Extensions.Logging;
using Serilog;

private void CalculateRectangleArea(int a, int b)
{
    var enricher =
        PropertyBagEnricher
            .CreateForSourceMember() // this will add the SourceMember property.
            .Add("SideA", a)
            .Add("SideB", b);

    ILogger logger = this.logger.ForContext(enricher);

    logger.Information("Rectangle area: {RectangleArea}", a * b);
    
    enricher.Add("RectangleArea", a * b);
    
    // this log event will also contain the RectangleArea property.
    logger.Verbose("Rectangle area calculated");
}

You can also add multiple properties at once:

using EgonsoftHU.Extensions.Logging;

var propertiesFromOtherSource = new Dictionary<string, object?>()
{
    ["SideA"] = 5,
    ["SideB"] = 10
};

var enricher =
    PropertyBagEnricher
        .CreateForSourceMember()
        .AddRange(propertiesFromOtherSource);

Please note:

  • AddRange<TValue>() method expects a single parameter.
  • The parameter type is IEnumerable<KeyValuePair<string, TValue>>.
  • TValue generic type parameter has no generic constraint, hence, both nullable and non-nullable types can be used as the type of the values. E.g.:
    • Dictionary<string, object>
    • Dictionary<string, object?>

Exception.Data - populate log event properties

Instead of manually providing the additional information:

var ex = new ArithmeticException("Cannot calculate area.");
ex.Data["SideA"] = a;
ex.Data["SideB"] = b;

throw ex;

you can use your existing PropertyBagEnricher instance:

using EgonsoftHU.Extensions.Logging;

var enricher =
    PropertyBagEnricher
        .Create()
        .Add("SideA", a)
        .Add("SideB", b);

// Exception.Data dictionary will contain all the properties above.
// The extension method returns the exception itself,
// hence you can use it directly in a `throw` statement or expression.
throw new ArithmeticException("Cannot calculate area.").Populate(enricher);

SourceMember property customization

As the contextual logger uses the SourceContext property name for the type, it seems to be logical to use the SourceMember property name for the member in that type.

Should you need to customize the log event property name for whatever reason, use the SourceMemberNamingConfiguration.Initialize() method as below:

using EgonsoftHU.Extensions.Logging;
using Serilog;

namespace ConsoleApp;

class Program
{
    private static ILogger logger;

    public static void Main(string[] args)
    {
        SourceMemberNamingConfiguration.Initialize("CallerMemberName");

        /* Log.Logger configuration omitted for clarity */

        logger = Log.Logger.ForContext<Program>();

        // The log event property will be { "CallerMemberName": "Main" }
        logger.Here().Information("First message");
    }
}

Please note:

  • This setting is global within the application.
  • Unless Initialize() method is called, the default property name (SourceMember) will be used.
  • This method may be called only once, preferably before you log anything. Subsequent calls will throw an InvalidOperationException.
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.  net10.0 is compatible.  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. 
.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 is compatible. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 is compatible.  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
10.0.1 300 10/21/2026
3.0.0 616 10/26/2024
2.0.0 1,836 11/5/2022
1.0.2 604 10/29/2022
1.0.1 3,530 6/25/2022
1.0.0 653 5/8/2022

Please visit https://github.com/gcsizmadia/logging/releases to view the release notes.