asp.net core 集成 log4net 日志框架

时间:2023-03-08 18:50:10

asp.net core 集成 log4net 日志框架

Intro

在 asp.net core 中有些日志我们可能想输出到数据库或文件或elasticsearch等,如果不自己去实现一个 LoggerProvider 的话就需要借助第三方日志框架实现了,而一些第三方框架的实现大多比较完善和成熟,不失为一个好办法。

自己写了一个 log4net 的扩展 WeihanLi.Common.Logging.Log4Net,提供了在 .net core 中使用 log4net 的扩展

安装 nuget 包

通过 nuget 安装 WeihanLi.Common.Logging.Log4Net

使用

基本使用

ILoggerFactory loggerFactory = new LoggerFactory();
loggerFactory.AddLog4Net(); // loggerFactory.AddLog4Net(log4netConfigFilePath);

你可以在 asp.net core 应用里你的 Startup 文件中使用下面代码进行配置

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddLog4Net(); // loggerFactory.AddLog4Net(log4netConfigFilePath); // ...
}

默认使用当前目录下的 log4net.config 文件作为 log4net 的配置文件,如果不是需要自己设置 log4net 配置文件的路径。

log4net 配置参考 示例配置

源码解析

项目源码

Log4NetLoggerProvider

  • 实现记录日志的 ILogger
    internal class Log4NetLogger : ILogger
{
private readonly ILog _logger; public Log4NetLogger(string name) => _logger = LogManager.GetLogger(ApplicationHelper.ApplicationName, name); public IDisposable BeginScope<TState>(TState state) => NullScope.Instance; public bool IsEnabled(LogLevel logLevel)
{
switch (logLevel)
{
case LogLevel.Critical:
return _logger.IsFatalEnabled; case LogLevel.Debug:
case LogLevel.Trace:
return _logger.IsDebugEnabled; case LogLevel.Error:
return _logger.IsErrorEnabled; case LogLevel.Information:
return _logger.IsInfoEnabled; case LogLevel.Warning:
return _logger.IsWarnEnabled; case LogLevel.None:
return false; default:
throw new ArgumentOutOfRangeException(nameof(logLevel));
}
} public void Log<TState>(LogLevel logLevel, EventId eventId, TState state,
Exception exception, Func<TState, Exception, string> formatter)
{
if (!IsEnabled(logLevel))
{
return;
} if (formatter == null)
{
throw new ArgumentNullException(nameof(formatter));
} var message = formatter(state, exception); if (!(string.IsNullOrEmpty(message) && exception == null))
{
switch (logLevel)
{
case LogLevel.Critical:
_logger.Fatal(message, exception);
break; case LogLevel.Debug:
case LogLevel.Trace:
_logger.Debug(message, exception);
break; case LogLevel.Error:
_logger.Error(message, exception);
break; case LogLevel.Information:
_logger.Info(message, exception);
break; case LogLevel.Warning:
_logger.Warn(message, exception);
break; default:
_logger.Warn($"Encountered unknown log level {logLevel}, writing out as Info.");
_logger.Info(message, exception);
break;
}
}
}
}
  • 实现提供 logger 的 ILoggerProvider
    [ProviderAlias("log4net")]
internal class Log4NetLoggerProvider : ILoggerProvider
{
private readonly ConcurrentDictionary<string, Log4NetLogger> _loggers =
new ConcurrentDictionary<string, Log4NetLogger>(StringComparer.Ordinal); public Log4NetLoggerProvider(string confFilePath)
{
if (null == LogManager.GetAllRepositories()?.FirstOrDefault(_ => _.Name == ApplicationHelper.ApplicationName))
{
XmlConfigurator.ConfigureAndWatch(LogManager.CreateRepository(ApplicationHelper.ApplicationName), new FileInfo(confFilePath));
}
} public void Dispose() => _loggers.Clear(); public ILogger CreateLogger(string categoryName) => _loggers.GetOrAdd(categoryName, loggerName => new Log4NetLogger(loggerName));
}
  • 添加 ILoggerFactory 扩展
    public static class Log4NetLoggerFactoryExtensions
{
public static ILoggerFactory AddLog4Net(this ILoggerFactory factory)
{
factory.AddProvider(new Log4NetLoggerProvider(ApplicationHelper.MapPath("log4net.config"))); return factory;
} public static ILoggerFactory AddLog4Net(this ILoggerFactory factory, string configFile)
{
factory.AddProvider(new Log4NetLoggerProvider(configFile)); return factory;
}
}

Memo

如果有什么问题或建议,欢迎指出