我有一段代码,用于基于一些自定义配置与托管环境相结合来设置serilog。 例如,应用程序写入开发中的一个接收器和生产环境中的另一个接收器。
我正在尝试弄清楚如何为这段代码编写测试。基本上,我想编写一个测试,检查是否仅在环境名称设置为给定值时才添加接收器,以及接收器配置(如日志文件路径(是否遵循我提供的自定义配置。
但是我没有运气找到任何从LoggingConfiguration
中获得价值的方法......
有人知道这是否可能吗?
不幸的是,Serilog 不会公开已配置的接收器列表,因此您目前唯一的选择就是使用反射。
如果您浏览 Serilog 的源代码,您会发现它将所有已配置的接收器分组到内部类SafeAggregateSink
的实例中,该类负责将日志发送到不同的接收器设置,并在一个名为_sinks
的私有字段中保存一个包含所有已配置接收器的数组。
下面是一个简单的示例:
var log = new LoggerConfiguration()
.WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Verbose)
.WriteTo.File(path: "log.txt", restrictedToMinimumLevel: LogEventLevel.Verbose)
.CreateLogger();
var aggregateSinkFieldInfo = log.GetType()
.GetField("_sink", BindingFlags.Instance | BindingFlags.NonPublic);
var aggregateSink = (ILogEventSink)aggregateSinkFieldInfo?.GetValue(log);
var sinkEnumerableFieldInfo = aggregateSink?.GetType()
.GetField("_sinks", BindingFlags.Instance | BindingFlags.NonPublic);
var sinks = (ILogEventSink[])sinkEnumerableFieldInfo?
.GetValue(aggregateSink);
if (sinks != null)
{
foreach (var sink in sinks)
{
Console.WriteLine(sink.GetType().FullName);
}
}
这应该输出:
Serilog.Sinks.SystemConsole.ConsoleSink
Serilog.Sinks.File.FileSink
注意:请记住,Serilog 在某些情况下会包裹水槽,因此您可能需要先处理这个问题,然后才能找到所需的水槽。例如,如果您限制水槽的最低水平,则您的水槽将被包裹到RestrictedSink
中,因此您必须掌握其_sink
字段才能获得您正在寻找的"真实"水槽。