Каков идиоматический подход для регистрации длинных сообщений в структурированной системе регистрации, такой как 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, созданы для эффективного анализа подобных вещей (хотя я не знаю, как можно представить что-то в этом формате с фиксированной шириной) (вещи также сжимается в магазинах и т. д., и событие всегда сохраняется)