You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求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的批处理能力,自定义批处理策略聚合重复消息:

  1. 安装Serilog.Sinks.PeriodicBatching包
  2. 实现自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 13:20:20