Каков идиоматический подход для регистрации длинных сообщений в структурированной системе регистрации, такой как MEL и Serilog?

Мое веб-приложение ASP.NET Core 2.x идиоматично использует 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-3 КБ), которые создаются приложением с помощью 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<String> - но есть несколько проблем с этим подходом:

  • Каждая выходная строка в исходном текстовом блоке становится структурированным объектом, обремененным своими собственными дополнительными свойствами, которые значительно увеличивают размер журнала.
  • Это приведет к дублированию данных, например, структурированная система регистрации добавит метки времени, но текст уже содержит значения времени секундомера.
  • Часто текстовый BLOB-объект содержит такие вещи, как ACII-art для блоков и указание областей обработки, и каждая строка имеет отступ, чтобы представить более глубокий уровень обработки - эта информация будет потеряна, если каждая строка хранится индивидуально и независимо от ее текстового контекста.
    • И какая польза от записи в журнале, которая просто содержит первую строку прямоугольника ASCII?

Есть ли способ в Serilog или MEL специально обрабатывать текстовые объекты? Например вывод их в свой файл?

1 ответ

Вы можете довольно легко реализовать приемник для синтаксического анализа выходных данных ( извините, в C# этого нет), как вы считаете нужным и правильно отображать, либо в файл своей формы, либо в журнал. В качестве альтернативы вы можете изолировать вещи как свойства в записях журнала, а затем обработать их в приемнике и / или цепочке журналов в целом, используя предоставленные там механизмы фильтрации ( более глубокий пример].

  • В пользовательской раковине вы получаете доступ к Serilog.Events.LogEvent который содержит структуру в основном неизменяемом виде, но допускает возможность добавлять / удалять свойства.

    Таким образом, вы должны иметь возможность извлекать встроенные свойства и записывать их в отдельный журнал (и удалять их из LogEvent, прежде чем разрешить его продолжить). Если вы делаете это внутри Async Раковина, это также не будет влиять на творчество писателей.

  • другой вариант - сделать рендеринг в формате json, используя различные возможные варианты воспроизведения, а затем постобработать себя вне диапазона

  • Наконец, если вы хорошо помечаете вещи и / или имеете соответствующие опознавательные метки, соотносящие предметы, такие вещи, как Seq, созданы для эффективного анализа подобных вещей (хотя я не знаю, как можно представить что-то в этом формате с фиксированной шириной) (вещи также сжимается в магазинах и т. д., и событие всегда сохраняется)

Другие вопросы по тегам