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

如何在运行时从Serilog日志配置中移除Enricher?

解决Serilog Enricher异常时避免循环日志并禁用自身的方案

Serilog的Logger实例是不可变的,一旦创建就无法直接从配置中移除已添加的Enricher,所以我们可以通过包装Enricher+开关禁用的方式实现需求,同时用独立Logger避免循环日志问题。

实现步骤

  1. 编写一个通用的安全包装Enricher,内置禁用开关和独立错误日志实例:
public class SafeEnricher<T> : ILogEventEnricher where T : ILogEventEnricher
{
    private readonly T _enricher;
    private bool _isEnabled = true;
    // 创建一个不带任何Enricher的独立Logger,用于记录自身错误
    private static readonly Logger _errorLogger = new LoggerConfiguration()
        .WriteTo.Console() // 根据实际需求修改输出目标(如文件、ELK等)
        .CreateLogger();

    public SafeEnricher(T enricher)
    {
        _enricher = enricher ?? throw new ArgumentNullException(nameof(enricher));
    }

    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
    {
        // 如果已禁用,直接跳过
        if (!_isEnabled)
            return;

        try
        {
            // 调用原Enricher的逻辑
            _enricher.Enrich(logEvent, propertyFactory);
        }
        catch (Exception ex)
        {
            // 标记为禁用,后续日志不再执行该Enricher
            _isEnabled = false;
            // 用独立Logger记录错误,不会触发原Enricher链,避免循环
            _errorLogger.Error(ex, "Enricher {EnricherTypeName}执行失败,已自动禁用", typeof(T).FullName);
        }
    }
}
  1. 保留你原有的PotentiallyCrashingEnricher不变:
public class PotentiallyCrashingEnricher : ILogEventEnricher
{
    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
    {
        var myString = "Something i want to log";
        var property = propertyFactory.CreateProperty("MyProperty", myString);
        logEvent.AddPropertyIfAbsent(property);
        throw new Exception("Oh no..."); // 模拟可能抛出的异常
    }
}
  1. 配置Serilog时,用SafeEnricher包裹你的目标Enricher:
Log.Logger = new LoggerConfiguration()
    .Enrich.With(new SafeEnricher<PotentiallyCrashingEnricher>(new PotentiallyCrashingEnricher()))
    .WriteTo.Console()
    .CreateLogger();

方案优势

  • 避免循环日志:独立的_errorLogger没有配置任何Enricher,记录错误时不会触发原Enricher链,彻底解决无限循环问题。
  • 自动禁用:异常触发后,开关_isEnabled会被置为false,后续所有日志都不会再执行该Enricher,达到“移除”的效果。
  • 通用性强:SafeEnricher<T>是通用类,可以包装任何实现了ILogEventEnricher的类,无需修改原有Enricher代码。

内容的提问来源于stack exchange,提问作者user3012708

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 00:26:27