.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的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 老黄的2021
- 下一篇: 一条nginx命令引发的对于容器的思考