使用 Microsoft.Extensions.Logging.Abstractions 记录到多个日志文件

Log to multiple Logfiles with Microsoft.Extensions.Logging.Abstractions

我想根据信息记录到不同的日志文件。

应用程序日志文件应包含有关应用程序或服务行为和异常的一般信息。

在服务中,我想记录到应用程序日志文件,对于不适合一般日志文件的内容,我想记录到服务日志文件。服务日志文件的一个示例可以是串行端口的通信。

我有一个 .net 核心应用程序,我在其中初始化 Log4Net 记录器:

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 标准 2.0 项目中实现的服务中使用记录器。这些项目引用了 Microsoft.Extensions.Logging.Abstractions nuget 包。 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");
}

内置记录器不支持文件记录(尽管我认为有人已经基于 Azure 提供程序进行了扩展?)我的建议是,如果您需要那种级别的记录 - 坚持使用 Log4Net

终于找到了满足我需求的解决方案。 我会分享它以防其他人也想这样做。

正如我已经假设的那样,有可能通过在一个范围内登录来实现这一点。 必须设置范围属性,以便它们可用于记录到不同的文件。

为了方便我写了一个扩展方法:

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 配置,因为如果设置了密钥,我想登录到不同的文件。因此,我为 属性 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>