.NET 6 中的 Logging Source Generator

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了.NET 6 中的 Logging Source Generator相关的知识,希望对你有一定的参考价值。

.NET 6 中的 Logging Source Generator

Intro

Logging source generator 是 .NET 6 引入的一个新功能,借助 Source Generator 来实现,因为要用到 C# 9 中的分部方法(partial method),C# 语言需要使用 9 及以上版本,具有更好的性能以及灵活性,在注重性能的项目中值得一试。

Static usage sample

类库里的日志通常会使用静态方法,将日志统一组织在一个静态类中,类似于下面这样

public static void RequestLog(this ILogger logger, string requestLog) => logger.Log(
    LogLevel.Information,
    new EventId(1, "RequestLog"),
    requestLog);

这样以后就可以比较方便地进行 EventId 的管理,避免 EventId 重复导致冲突

使用 Logging Source Generator 之后可以变成下面这样:

[LoggerMessage(LogLevel = LogLevel.Information, EventId=1, EventName= "RequestLog", Message = "requestLog")]
public static void RequestLog(this ILogger logger, string requestLog);

更多使用示例:

[LoggerMessage(Level = LogLevel.Information, EventId = 0, Message = "Logging generator sample begin")]
public static partial void TestBegin(this ILogger logger);

[LoggerMessage(Level = LogLevel.Information, EventId = 1, Message = "Logging generator sample end", SkipEnabledCheck = true)]
public static partial void TestEnd(this ILogger logger);

[LoggerMessage(EventId = 2, Message = "Logging generator sample user userName")]
public static partial void TestWithArgument(this ILogger logger, LogLevel logLevel, string userName);

// warning SYSLIB1015: Argument 'host' is not referenced from the logging message
[LoggerMessage(EventId = 3)]
public static partial void TestWithEmptyMessage(this ILogger logger, LogLevel logLevel, string host);

[LoggerMessage(
    EventId = 9,
    Level = LogLevel.Trace,
    Message = "Fixed message",
    EventName = "CustomEventName")]
public static partial void LogWithCustomEventName(this ILogger logger);

这里的静态方法作为了扩展方法使用,也可以不作为扩展方法来使用,可以根据自己需要和习惯来选择

使用示例:

var loggerFactory = LoggerFactory.Create(builder => builder.AddJsonConsole(options =>
        
            options.JsonWriterOptions = new JsonWriterOptions()
            
                Indented = true,
                Encoder = javascriptEncoder.UnsafeRelaxedJsonEscaping
            ;
        ));

var logger = loggerFactory.CreateLogger<LoggingGeneratorSample>();
logger.TestBegin();
logger.TestWithArgument(LogLevel.Warning, Environment.UserName);
logger.TestWithEmptyMessage(LogLevel.Information, Environment.MachineName);
logger.TestEnd();

这里的示例为了方便展示,配置输出格式为带缩进的 JSON 格式,输出结果如下:

Instance usage sample

除了作为静态方法使用,我们也可以作为实例方法去使用,不需要关注 EventId 的日志记录可能会使用的比较多,下面是一个示例:

// instance logging test
new InstanceLoggingGenerator(logger).LoggingTest();

internal partial class InstanceLoggingGenerator

    private readonly ILogger _logger;

    public InstanceLoggingGenerator(ILogger logger)
    
        _logger = logger;
    

    [LoggerMessage(EventId = 0, EventName = "Test", Level = LogLevel.Information, Message = "Instance logging generator test")]
    public partial void LoggingTest();

输出结果如下:

实例方法中使用可以不传 ILogger 实例,会自动从类型中寻找 ILogger 类型的字段,可以想一下如果类型中有多个 ILogger 字段会怎么样?如果没有的话又会怎么样呢?可以自己实践一下

More

现在 ASP.NET Core 里有很多地方都已经在用了新的 Source Generator 的方式来记录日志,不妨也在自己的系统中试一下吧

目前我们日志里的 Message 中的参数还是要写模板传参数,以后可能就可以直接写一个插值字符串,由编译器去提取消息模板和参数,目前还不支持,可以参考设计文档:https://github.com/dotnet/designs/blob/main/accepted/2021/logging-generator.md

References

  • https://github.com/WeihanLi/SamplesInPractice/blob/master/net6sample/GeneratorSample/LoggingGeneratorSample.cs

  • https://docs.microsoft.com/en-us/dotnet/core/extensions/logger-message-generator

  • https://github.com/dotnet/designs/blob/main/accepted/2021/logging-generator.md

以上是关于.NET 6 中的 Logging Source Generator的主要内容,如果未能解决你的问题,请参考以下文章

使用.NET 6开发TodoList应用(12.1)——加餐 .NET 6中的HttpLogging简介

将 .NetStandard 2.0 Nuget 包安装到 VS2015 Net 4.6.1 项目中

net core体系-web应用程序7asp.net core日志组件

logback.xml读取application.properties自定义日志路径

如何使用 commons-logging 库解决 jasperreports 中的依赖收敛错误?

tomcat中的logging.properties有人可以具体分析一下里面的配置吗