Запись в несколько файлов журналов с помощью Microsoft.Extensions.Logging.Abstractions

Я хотел бы войти в разные файлы журнала в зависимости от информации.

Файл журнала приложения должен содержать общую информацию о поведении и исключениях приложения или службы.

Внутри службы я хотел бы войти в файл журнала приложения и для вещей, которые не подходят для общего файла журнала, в файл журнала службы. Примером файла журнала службы может быть связь через последовательный порт.

У меня есть основное приложение .net, в котором я инициализирую Log4Net Logger:

public void Configure(..., ILoggerFactory loggerFactory, ...)
{
    ...
    loggerFactory.AddLog4Net();
    ...
}

Мой log4net.config для журнала приложений выглядит так:

 <log4net>
  <root>
    <level value="ALL" />
    <appender-ref ref="console" />
    <appender-ref ref="file" />
  </root>
  <appender name="console" type="log4net.Appender.ConsoleAppender">
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date %level %logger - %message%newline" />
    </layout>
  </appender>
  <appender name="file" type="log4net.Appender.RollingFileAppender">
    <file value="logs/application.log" />
    <appendToFile value="true" />
    <rollingStyle value="Date" />
  <datePattern value="-yyyyMMdd" />
    <maxSizeRollBackups value="5" />
    <maximumFileSize value="5MB" />
  <preserveLogFileNameExtension value="true" />
    <staticLogFileName value="false" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date [%thread] %level %logger - %message%newline" />
    </layout>
  </appender>
 </log4net>

Я использую внедрение зависимостей, чтобы использовать регистратор в службах, которые реализованы в проектах .net Standard 2.0. Эти проекты имеют ссылку на пакет nuget Microsoft.Extensions.Logging.Abstractions. https://github.com/aspnet/Extensions/tree/master/src/Logging/Logging.Abstractions/src

Пример службы

public void MyService(ILogger<MyService> logger)
{
   logger.Log(LogLevel.Information, $"application log info");
   // How to log to the service log file?
   // logger.LogServiceLog(LogLevel.Information, $"service log info")
}

Я знаю, что могу настроить log4net для регистрации в разных файлах журналов в зависимости от пространства имен. Однако я хочу иметь возможность использовать оба файла журнала.

Есть ли способ добиться этого с помощью Microsoft.Extensions.Logging.Abstractions?

Могу ли я записать область действия в другой файл журнала?

using (_logger.BeginScope("Service Scope"))
{
    _logger.LogInformation("Service info");
}

person eugstman    schedule 19.06.2019    source источник


Ответы (2)


Наконец я нашел решение, которое удовлетворяет мои потребности. Я поделюсь им, если кто-то еще захочет сделать то же самое.

Как я уже предполагал, есть возможность добиться этого с помощью ведения журнала в области видимости. Свойства области должны быть установлены таким образом, чтобы их можно было использовать для записи в другой файл.

Для удобства я написал метод расширения:

private const string PropertyKey = "ServiceLogger";
private const string ValueSuffix = "ServiceLogger";

public static void ServiceLog<TCategoryName>(this ILogger<TCategoryName> logger, LogLevel level, string message)
{
    using (logger.BeginScope(new[] { new KeyValuePair<string, object>(PropertyKey, $"{typeof(TCategoryName).Name}{ValueSuffix}") }))
    {
        logger.Log(level, message);
    }
}

И теперь в сервисе я могу использовать:

public void MyService(ILogger<MyService> logger)
{
   // application log file
   logger.Log(LogLevel.Information, $"application log info");
   // service log file
   logger.ServiceLog(LogLevel.Information, $"service log info");
}

Чтобы это работало, конфигурация log4net должна быть скорректирована, так как я хочу войти в другой файл, если ключ установлен. Поэтому я добавил новое приложение с фильтром для Property Key=ServiceLogger и value=MyServiceServiceLogger.

Обратите внимание, что если эти журналы должны быть только в одном файле журнала, мы должны установить фильтр игнорирования в общем приложении для свойства Key=ServiceLogger и значения, содержащего ServiceLogger.

Пример конфига:

<log4net>
  <root>
    <level value="ALL" />
    <appender-ref ref="console" />
    <appender-ref ref="app_logger" />
    <appender-ref ref="service_myservice_logger" />
  </root>
  <appender name="console" type="log4net.Appender.ConsoleAppender">
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date [%2thread] %-5level %.50logger - %message%newline" />
    </layout>
  </appender>
  <appender name="app_logger" type="log4net.Appender.RollingFileAppender">
    <file value="logs/application.log" />
    <appendToFile value="true" />
    <rollingStyle value="Date" />
    <datePattern value="-yyyyMMdd" />
    <maxSizeRollBackups value="5" />
    <maximumFileSize value="5MB" />
    <preserveLogFileNameExtension value="true" />
    <staticLogFileName value="false" />
    <filter type="log4net.Filter.PropertyFilter">
      <key value="ServiceLogger" />
      <regexToMatch value="ServiceLogger" />
      <acceptOnMatch value="false" />
    </filter>
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date [%2thread] %-5level %.50logger - %message%newline" />
    </layout>
  </appender>
  <appender name="service_myservice_logger" type="log4net.Appender.RollingFileAppender">
    <file value="logs/my_service.log" />
    <appendToFile value="true" />
    <rollingStyle value="Date" />
    <datePattern value="-yyyyMMdd" />
    <maxSizeRollBackups value="5" />
    <maximumFileSize value="5MB" />
    <preserveLogFileNameExtension value="true" />
    <staticLogFileName value="false" />
    <filter type="log4net.Filter.PropertyFilter">
      <Key value="ServiceLogger" />
      <StringToMatch value="MyServiceServiceLogger" />
    </filter>
    <filter type="log4net.Filter.DenyAllFilter" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date [%2thread] %-5level %.50logger - %message%newline" />
    </layout>
  </appender>
</log4net>
person eugstman    schedule 21.06.2019

Встроенный регистратор не поддерживает ведение журнала файлов (хотя я думаю, что кто-то сделал расширение на основе поставщика Azure?). Мое предложение состоит в том, что если вам требуется такой уровень ведения журнала, придерживайтесь Log4Net.

person Robert Perry    schedule 19.06.2019
comment
Что вы имеете в виду под встроенным регистратором? Я уже использую log4Net для входа в файл. Однако я не хочу напрямую ссылаться на log4net в своих сервисных проектах, так как это ограничивает использование моих сервисов с разными поставщиками журналов. - person eugstman; 20.06.2019