首页 > 解决方案 > 如何将磁盘上的 Serilog 文件接收器写入的数据推送到另一个 Serilog 接收器?

问题描述

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

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

我想一次读取json 文件一行,然后在Logger. 但是我不确定如何从 json 中获取属性数组。此外,很高兴听到 Serilog 世界中是否有更好的选择来满足我的需求。

示例解析

            var events=  File.ReadAllLines(@"C:\20210520.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. 它无法处理 Context 属性(虽然使用 ForContext 有一个变通方法),
  2. 它还强制所有属性为字符串类型,并且
  3. 更不用说解构(@property)没有正确处理

标签: serilog

解决方案


如果您可以将 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);

推荐阅读