如何将磁盘上的 Serilog 文件接收器写入的数据推送到另一个 Serilog 接收器?

How can I push data written by a Serilog File Sink on the disk to another Serilog sink?

我们正在尝试对 logstash/elastic 的基础架构进行负载测试。由于实际日志是由使用硬件的软件生成的,我们无法大规模模拟它。

我想知道我们是否可以使用文件接收器存储日志,然后编写一个程序来读取日志文件并通过实际接收器发送数据。因为,我们正在尝试不同的设置,所以如果我们可以交换不同的接收器进行测试,那就太好了。说一下http sink和elastic sink。

我想一次读取 json 文件一行,然后在 Logger 上调用 Write 方法。但是我不确定如何从 json 获取属性数组。另外,很高兴听到 Serilog 世界中是否有更好的替代品来满足我的需求。

示例解析

            var events=  File.ReadAllLines(@"C:210520.json")
                .Select(line => JsonConvert.DeserializeObject<dynamic>(line));

            foreach (var o in objects)
            {
                DateTime timeStamp = o.Timestamp;
                LogEventLevel level = o.Level;
                string messageTemplate = o.MessageTemplate;
                string exception = o.Exception;
                var properties = (o.Properties as JObject);

                List<object> parameters = new List<object>();
                foreach (var property in properties)
                {
                    if(messageTemplate.Contains(property.Key))
                        parameters.Add(property.Value.ToString());
                }

                logInstance.Write(level, messageTemplate, parameters.ToArray());
                count++;
            }

示例Json 事件写入文件

{"Timestamp":"2021-05-20T13:15:49.5565372+10:00","Level":"Information","MessageTemplate":"Text dialog with {Title} and {Message} displayed, user selected {Selected}","Properties":{"Title":"Unload Device from Test","Message":"Please unload the tested device from test jig","Selected":"Methods.Option","SinkRepository":null,"SourceRepository":null,"TX":"TX2937-002 ","Host":"Host1","Session":"Host1-2021.05.20 13.12.44","Seq":87321,"ThreadId":3}}

更新 虽然这适用于简单的事件,

  1. 它无法处理上下文属性(虽然使用 ForContext 可以解决),
  2. 它还强制所有属性为字符串类型并且
  3. 更不用说解构 (@属性) 处理不当

如果你能把JSON格式改成Serilog.Formatting.Compact的CLEF格式,那么你就可以用Serilog.Formatting.Compact.Reader为此.

在源应用中:

// dotnet add package Serilog.Formatting.Compact
Log.Logger = new LoggerConfiguration()
  .WriteTo.File(new CompactJsonFormatter(), "./logs/myapp.clef")
  .CreateLogger();

在负载测试器中:

// dotnet add package Serilog.Formatting.Compact.Reader
using (var target = new LoggerConfiguration()
    .MinimumLevel.Verbose()
    .WriteTo.Console()
    .CreateLogger())
{
    using (var file = File.OpenText("./logs/myapp.clef"))
    {
        var reader = new LogEventReader(file);
        while (reader.TryRead(out var evt))
            target.Write(evt);
    }
}

请注意,如果您使用重复的时间戳,负载测试结果对于许多接收器来说将不准确。您应该考虑重新映射您读入的事件以使用当前时间戳。

例如一旦你加载 evt:

var current = new LogEvent(DateTimeOffset.Now,
                           evt.Level,
                           evt.Exception,
                           evt.MessageTemplate,
                           evt.Properties);
target.Write(current);