.NET 8 Worker Service中Serilog LogEvent的MessageTemplateToken创建问题
关于Serilog DuplicateFilterSink重复计数消息空白的问题
我在C# .NET 8 Worker Service项目中基于Serilog实现了DuplicateFilterSink,用来过滤连续重复的日志:连续出现相同LogEvent时只计数不输出,当新的LogEvent到来且重复计数大于0时,先输出“前一条消息重复X次”的日志,再输出新消息,避免循环日志占满文件。目前功能基本正常,但输出的重复计数消息内容是空的。我推测原因是创建MessageTemplate时用了空的MessageTemplateToken数组,由于MessageTemplateToken是抽象类无法直接实例化,且现有LogEvent的MessageTemplateToken文本不可修改,因此有两个疑问:
- 是否是空MessageTemplateToken数组导致输出空白行?
- 如何创建包含有效MessageTemplateToken数组的合法MessageTemplate?
问题解答
1. 空MessageTemplateToken数组是否导致空白行?
是的,这就是导致空白行的直接原因。Serilog的MessageTemplate完全依赖内部的MessageTemplateToken数组来渲染最终的日志文本,当数组为空时,没有任何可解析输出的内容,自然会输出空白行。
2. 如何创建合法的MessageTemplate?
不需要手动实例化MessageTemplateToken的子类,Serilog内置了MessageTemplateParser工具类,通过它的静态Parse方法可以直接将字符串解析为合法的MessageTemplate,该方法会自动生成对应的MessageTemplateToken数组。
示例代码如下:
using Serilog.Events; using Serilog.Parsing; using System.Linq; // 假设重复计数为count int count = 3; // 定义重复提示消息 var repeatMessage = $"前一条消息重复{count}次"; // 解析生成合法的MessageTemplate var template = MessageTemplateParser.Parse(repeatMessage); // 创建对应的LogEvent var repeatLogEvent = new LogEvent( timestamp: DateTimeOffset.Now, level: LogEventLevel.Information, exception: null, messageTemplate: template, properties: Enumerable.Empty<LogEventProperty>() ); // 将该LogEvent输出到目标Sink(比如你原本的输出Sink) yourTargetSink.Emit(repeatLogEvent);
如果需要保留原日志的上下文属性,也可以将原LogEvent的Properties传递给新创建的repeatLogEvent,保证日志上下文的一致性。
内容的提问来源于stack exchange,提问作者Dogulas
相关产品推荐
相关产品推荐

