代码之家  ›  专栏  ›  技术社区  ›  Dai

在MEL和Serilog这样的结构化日志系统中,记录长消息的惯用方法是什么?

  •  1
  • Dai  · 技术社区  · 6 年前

    Microsoft.Extensions.Logging 当我想存储一个短的(<200个字符)参数化字符串时,用于执行“跟踪”式日志记录。这些类型的日志事件与围绕Serilog这样的结构化日志系统构建的工具和生态系统配合得很好。

    例如

    public IActionResult DisplayCustomers(String customerName, String country)
    {
        this.logger.LogInformation( "Search performed for customers named {name} in {country}.", customerName, country );
    }
    

    然而,我的应用程序还需要记录一些较大的文本块(2-3KB),这些文本块是由应用程序使用 StringBuilder IProgress<String> 以类似于临时使用 Console.WriteLine .

    例如

    // Backend method (no structured logging available):
    public void ProcessData(LotsOfData data, IProgress<String> report)
    {
        Stopwatch sw = Stopwatch.StartNew();
        for( Int32 i = 0; i < data.Records.Count; i++ )
        {
            if( i % 500 == 0 ) report.Report( String.Format( "{0}ms - Processed {1} records.", sw.ElapsedMilliseconds, i ) );
    
            if( data.Records[i].Foo )
            {
                // (send job off to SQL Server and get back SPROC output via PRINT and RAISERROR)
                String sprocRaiseErrorOutput = ...
                report.Report( "Sproc output: " +  sprocRaiseErrorOutput );
            }
    
            if( data.Records[i].Bar ) report.Report( "Contents of bar: " +  data.Records[i].Bar.Text );
        }
        report.Report( "{0}ms - Completed.", sw.ElapsedMilliseconds );
    }
    
    class StringBuilderProgress : IProgress<String>
    {
        private StringBuilder sb;
        public StringBuilderProgress(StringBuilder sb) { this.sb = sb; }
    
        public void Report(String value) { this.sb.AppendLine( value ); }
    }
    
    // Frontend method:
    public IActionResult ProcessData(LotsOfData data)
    {
        StringBuilder sb = new StringBuilder();
        StringBuilderProgress sbp = new StringBuilderProgress( sb );
    
        backendService.ProcessData( data, sbp );
    
        this.logger.LogInformation( "Process data ran: {report}", sb.ToString() );
    }
    

    ...这会产生一个大的、非结构化的文本块,其中包含有用的信息,需要单独查看,但不适合现有的结构化日志记录工具。

    我知道一个通用的解决方案是为 ILogger 实现 IProgress<字符串> -但这种方法存在一些问题:

    • 原始文本blob中的每一行输出都成为一个结构化对象,并被其自身的附加属性所困扰,这些属性会显著增加日志的大小。
    • 这将导致重复数据,例如,结构化日志系统将添加时间戳,但文本也已包含秒表时间值。
    • 通常,文本块包含诸如ACII art for Box和指示处理区域之类的内容,每一行都缩进以表示更深层次的处理——如果每一行单独存储且独立于其文本上下文,则这些信息将丢失。
      • 只包含ASCII艺术矩形框第一行的日志条目有什么用?

    Serilog或MEL中是否有专门处理文本斑点的方法?比如将它们输出到自己的文件中?

    1 回复  |  直到 6 年前
        1
  •  0
  •   Ruben Bartelink    6 年前

    你可以很容易地实现一个接收器来解析输出( sorry, don't have this in C# deeper example ].

    • Serilog.Events.LogEvent 它以基本不变的形式保存结构,但允许添加/删除属性。

      因此,您应该能够提取嵌入的属性,并将它们向前写入一个单独的日志(并在允许继续之前从LogEvent中删除它们)。如果你在一个 Async

    • 另一个选项是呈现为json using the variety of renditions possible

    • 最后,如果你给物品贴好标签,或者有相关的识别标记,比如 Seq 是为了高效地解析这样的内容而构建的(尽管我不知道有什么方法可以将内容呈现为固定宽度格式)(存储中的内容也会被压缩,整个事件总是被保留)