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

Мое веб-приложение ASP.NET Core 2.x идиоматически использует Microsoft.Extensions.Logging для ведения журнала в стиле «трассировки», когда я хочу сохранить короткую (<200 символов) параметризованную строку.Эти виды регистрируемых событий хорошо работают с инструментарием и экосистемой, построенной вокруг структурированных систем журналирования, таких как Serilog. </p>

например

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

Однако моему приложению также необходимо регистрировать несколько большие текстовыеBLOB-объекты (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> - но с этим есть несколько проблемподход:

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

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

1 Ответ

0 голосов
/ 02 февраля 2019

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

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

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

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

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

...