A Serilog and ILogger source generator that supports enriching logs with which method called them.
Install the Serilog.Enrichers.GeneratedContext package from NuGet:
Using Package Manager In Visual Studio, open NuGet Package Manager Console by clicking Tools → NuGet Package Manager → Package Manager Console
In the console run the following command:
Install-Package Serilog.Enrichers.GeneratedContextOptionally using Dotnet CLI
dotnet add package Serilog.Enrichers.GeneratedContextCreate a class or extend your current class
Note: your logger must be a ** static partial ** for the generator to work correctly
public static partial class Logger
{
}Then append the attribute to generate the new log methods. You can customize what the context name will be and how many parameters you will use for strucutred logging. See attribute parameters
[LoggerGenerate(
genericOverrideCount: 3
)]
public static partial class Logger
{
}This will source generate some methods that you can use to log with, these methods take generic parameters to allow for strucutred logging. While still being able to take the CallerMembers. This works by generating a bunch of overloads.
// <auto-generated/>
public static partial class Logger
{
[MessageTemplateFormatMethod("messageTemplate")]
public static void Verbose<T0, T1, T2, T3>(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2, T3 propertyValue3, Serilog.Enrichers.GeneratedContext.LogWithOptionalParameterList _ = default(Serilog.Enrichers.GeneratedContext.LogWithOptionalParameterList), [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int _sourceLineNumber = 0)
=> Serilog.Log.ForContext("MethodName", $"{Path.GetFileNameWithoutExtension(sourceFilePath)}.{memberName} - ").Write(LogEventLevel.Verbose, messageTemplate, propertyValue0, propertyValue1, propertyValue2, propertyValue3);
}Create a class or extend a new static extension class
Note: your static logger extenions class must be a ** static partial ** for the generator to work correctly
public static partial class Logger
{
}Then append the attribute to generate the new log methods. You can customize what the context name will be and how many parameters you will use for strucutred logging. See attribute parameters
[MicrosoftLoggerGenerate(
genericOverrideCount: 3
)]
public static partial class Logger
{
}This will source generate some methods that you can use to log with, these methods take generic parameters to allow for strucutred logging. While still being able to take the CallerMembers. This works by generating a bunch of overloads.
// <auto-generated/>
public static partial class Logger
{
// <auto-generated/>
[MessageTemplateFormatMethod("messageTemplate")]
public static void Trace<T0, T1, T2, T3, T4>(this Microsoft.Extensions.Logging.ILogger msLogger, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2, T3 propertyValue3, T4 propertyValue4, Serilog.Enrichers.GeneratedContext.LogWithOptionalParameterList _ = default(Serilog.Enrichers.GeneratedContext.LogWithOptionalParameterList), [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int _sourceLineNumber = 0)
{
using (msLogger.BeginScope(new Dictionary<string, object>(){ { "MethodContext", $"{Path.GetFileNameWithoutExtension(sourceFilePath)}.{memberName}" } }))
{
msLogger.LogTrace(messageTemplate, propertyValue0, propertyValue1, propertyValue2, propertyValue3, propertyValue4);
}
}
}