求Serilog聚合连续重复日志消息的插件、过滤器或代码
Serilog聚合连续重复日志的解决方案
一、自定义Logger装饰器实现
这是最灵活的方案,通过包装ILogger实例跟踪连续重复的日志消息并计数,当出现新的不同消息时输出之前的聚合内容。
示例代码:
public class DuplicateAggregationLogger : ILogger, IDisposable { private readonly ILogger _innerLogger; private string _lastMessage; private int _duplicateCount; public DuplicateAggregationLogger(ILogger innerLogger) { _innerLogger = innerLogger ?? throw new ArgumentNullException(nameof(innerLogger)); } public void Write(LogEvent logEvent) { var message = logEvent.MessageTemplate.Render(logEvent.Properties); if (message == _lastMessage) { _duplicateCount++; return; } // 输出之前的重复聚合 if (_duplicateCount > 0) { _innerLogger.Information("Plus {Count} more", _duplicateCount); _duplicateCount = 0; } // 输出当前新消息 _innerLogger.Write(logEvent); _lastMessage = message; } // 委托ILogger的其他接口方法给内部实例 public IDisposable BeginScope<TState>(TState state) => _innerLogger.BeginScope(state); public bool IsEnabled(LogEventLevel level) => _innerLogger.IsEnabled(level); // 程序退出时输出剩余的重复计数 public void Dispose() { if (_duplicateCount > 0) { _innerLogger.Information("Plus {Count} more", _duplicateCount); } (_innerLogger as IDisposable)?.Dispose(); } }
使用方式:
var baseLogger = new LoggerConfiguration() .WriteTo.Console() .CreateLogger(); var aggregatedLogger = new DuplicateAggregationLogger(baseLogger); // 后续使用aggregatedLogger替代原Logger
二、基于批处理Sink的扩展实现
借助Serilog.Sinks.PeriodicBatching的批处理能力,自定义批处理策略聚合重复消息:
- 安装
Serilog.Sinks.PeriodicBatching包 - 实现自定义
IBatchFormatter:
public class DuplicateAggregationBatchFormatter : IBatchFormatter { public void FormatBatch(IEnumerable<LogEvent> events, TextWriter output) { LogEvent lastEvent = null; int duplicateCount = 0; foreach (var evt in events) { var currentMsg = evt.MessageTemplate.Render(evt.Properties); if (lastEvent != null && currentMsg == lastEvent.MessageTemplate.Render(lastEvent.Properties)) { duplicateCount++; continue; } if (duplicateCount > 0) { output.WriteLine($"Plus {duplicateCount} more"); duplicateCount = 0; } lastEvent = evt; evt.Render(output); output.WriteLine(); } // 处理最后一批重复消息 if (duplicateCount > 0) { output.WriteLine($"Plus {duplicateCount} more"); } } }
配置使用:
var logger = new LoggerConfiguration() .WriteTo.PeriodicBatching(options => { options.BatchSizeLimit = 1000; options.Period = TimeSpan.FromSeconds(1); options.BatchFormatter = new DuplicateAggregationBatchFormatter(); options.Sink = new ConsoleSink(new ConsoleSinkOptions()); }) .CreateLogger();
三、业务代码层面的轻量化优化
如果是明确的批量处理场景,也可以在业务逻辑中先聚合异常,再统一输出日志,避免产生大量重复日志:
var errorCount = 0; foreach(var item in myLargeList){ try{ // 处理item的逻辑 }catch(Exception e){ errorCount++; } } if (errorCount > 0) { logger.LogDebug("This is a message"); if (errorCount > 1) { logger.LogDebug("Plus {Count} more", errorCount - 1); } }
内容的提问来源于stack exchange,提问作者Emilio Petrangeli
相关产品推荐
相关产品推荐

