运行时切换 Serilog 接收器

问题描述 投票:0回答:1

我正在使用基于代码的 Serilog 配置(不是应用程序设置)。我想在运行时切换接收器;特别是 Seq,还有其他的。

我知道

WriteTo.Conditional
功能:

var isFooEnabled = true;
var isSeqEnabled = true;

services.AddSerilog((services, config) => config
  // ...
  .WriteTo.Console()
  .WriteTo.Conditional(x => isFooEnabled, x => x.Foo())
  .WriteTo.Conditional(x => isSeqEnabled, x => x.Seq(SEQ_URL))
);

但是该代码位于组合根中(即它在应用程序启动期间运行)。我需要稍后切换水槽。

我可能需要解决一些可以做出切换决定的服务。但是我如何在运行时将其连接到上面的配置代码?我找不到此类功能的挂钩。

(请注意,切换到应用程序设置方法是不可行的。)

asp.net-core serilog serilog-aspnetcore serilog-sinks-seq
1个回答
0
投票

我找到了一个解决方案解决方法,基于这个

添加一个封装类型

LoggingLevelSwitch
:

public class SinkSwitch
{

  private readonly LoggingLevelSwitch _switch;
  private readonly LogEventLevel _levelOff = (LogEventLevel)int.MaxValue;
  private LogEventLevel _level;

  public SinkSwitch(LogEventLevel level)
  {
    if (!Enum.IsDefined(level)) throw new ArgumentOutOfRangeException(nameof(level));
    _level = level;
    _switch = new LoggingLevelSwitch(level);
  }

  public LoggingLevelSwitch Switch => _switch;

  public void Toggle()
  {
    _switch.MinimumLevel = _switch.MinimumLevel == _levelOff
      ? _level
      : _levelOff;
  }

  public void Change(LogEventLevel level)
  {
    if (!Enum.IsDefined(level)) throw new ArgumentOutOfRangeException(nameof(level));
    _level = level;
    _switch.MinimumLevel = level;
  }

}

在启动过程中,在配置 Serilog 之前,创建开关并将其存储为单例:

var sinkSwitch = new SinkSwitch(LogEventLevel.Information);
services.AddSingleton(sinkSwitch);

然后配置Serilog:

services.AddSerilog((services, config) => config
  // ...
  .WriteTo.Console(levelSwitch:sinkSwitch.Switch)
  .WriteTo.Seq(SEQ_URL, controlLevelSwitch:sinkSwitch.Switch)
);

备注:

  • 可以为不同的水槽使用不同的开关
  • 技巧是使用无效的枚举值 (
    _levelOff
    )

这感觉就像一个黑客,因为如果库发生变化(以验证枚举值,就像我上面所做的那样),那么这种方法将会失败。 如果您有更好的解决方案,请发布,我会接受。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.