Регистрировать тип, используемый с универсальным ILogger , через Serilog

#c# #.net #serilog

#c# #.net #serilog

Вопрос:

В настоящее время я использую этот шаблон вывода с Serilog:

 "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] [{MachineName}] {Message:lj}{NewLine}{Exception}"
  

Я хотел бы добавить класс, который я указываю при объявлении Microsoft.Extensions.Logging.ILogger регистратора, который я внедряю, т. Е. Если я объявляю, ILogger<MyType> то я хотел бы выводить MyType через шаблон.

Я знаю, что могу добавить весь контекст, но я читал, что это приводит к снижению производительности, поэтому в настоящее время я добавляю класс, добавляя nameof(MyType) к каждому сообщению, что является беспорядком.

Есть ли обогащающее средство или что-то подобное, которое сделает тип доступным в шаблоне (или просто добавит к каждому сообщению журнала тип)?

Редактировать:

На самом деле кода не так много, вот как я настраиваю Serilog с помощью dotnet-core WebAPI:

 public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.UseStartup<Startup>();
    })
    .UseWindowsService()
    .UseSerilog();
  

И это пример того, как я использую регистратор через IOC:

 private readonly ILogger<MyType> _logger;

public MyType(ILogger<MyType> logger)
{
    _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}

public void HelloLog()
{
   _logger.LogInformation("hello");
}

// expected log output: "[MyType] hello"
  

Я понимаю из комментария Энди, что я мог бы написать LoggingProvider и передать его в перегрузке UseSerilog, которая требует набора поставщиков. Это то, что я рассмотрю, если ничего проще не появится.

Комментарии:

1. Предоставьте свой код. чтобы мы могли предоставить лучшие предложения

2. Уверен, вам придется создать свой собственный ILoggerProvider и добавить его в ILoggerFactory .

3. @VimalCK в этом вопросе нет необходимости в дополнительном коде. OP спрашивает, как избежать вызова Enrich.FromLogContext() и при этом получить имя регистратора

4. Не пытайтесь оптимизировать то, что может никогда не стать проблемой, только потому, что кто-то сказал, что это может повлиять на производительность. Ведение журнала влияет на производительность, и все же мы используем его, потому что нам это нужно.

5. Согласен, но если я правильно помню, контекст также возвращает полное имя метода, а не более краткое имя типа, предоставленное регистратором. Мне нужно только имя типа (я использую несколько адаптеров с аналогичной функциональностью и хочу знать, где произошло событие). Таким образом, отражение контекста плюс использование некоторой строки.разделить все, что угодно, чтобы добраться до типа, выглядит слишком обременительным для времени выполнения, когда имя фактически доступно как параметр универсального типа.

Ответ №1:

Имя типа должно быть добавлено в SourceContext свойство любых событий журнала, генерируемых ILogger<T> , точно так же, как если бы вы использовали методы ForContext<T>() или ForContext(type) для Serilog.ILogger . Использование {SourceContext} где-нибудь в вашем шаблоне сообщения должно позволить вам добавить только имя источника, например

 "[{Timestamp:HH:mm:ss} {Level:u3}] [{MachineName}] [{SourceContext}] {Message:lj}{NewLine}{Exception}"
  

Обратите внимание, что это выведет полное имя типа, поэтому будет включать пространство имен.

Комментарии:

1. Я не хочу выводить полное имя типа, а только имя типа или класса, как указано в параметре шаблона ILogger. В текстовых журналах SourceContext работает нормально, но не в каком-либо другом средстве ведения журнала (Greylog) и консоли.

2. Я возился со списком ILoggingProvider, но вскоре заблудился, поэтому я думаю, что ответ Robs настолько хорош, насколько это возможно.