Мое веб-приложение 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обрабатывать текстовые капли специально?Например, вывести их в свой файл?