https://dotnetthoughts.net/how-to-use-log4net-with-aspnetcore-for-logging/
这篇文章是关于使用 Log4Net 和 ASP.NET Core 来实现日志记录的。Apache log4net 库是帮助程序员将日志语句输出到各种输出目标的工具。log4net 是优秀的 Apache log4j™ 框架到 Microsoft® .NET 运行时的一个端口。我们在利用 .NET 运行时中的新功能的同时,使框架在精神上与原始 log4j 相似。
首先需要在 project.json 文件中添加 log4net 库的引用。我正在使用”log4net”:”2.0.7”. 现在您可以使用 log4net 编写代码。我正在 Program.cs 文件中编写代码。与 ASP.NET 不同,log4net 不支持加载配置的属性,因此需要手动加载配置。这是我正在使用的示例 log4net 配置文件,它将使用FileAppender. 我正在记录所有信息。您可以在 log4net 文档中找到有关日志记录提供程序和级别的更多信息。
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<appender name="RollingFile" type="log4net.Appender.FileAppender">
<file value="C:\Temp\app.log" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5p %d{hh:mm:ss} %message%newline" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="RollingFile" />
</root>
</log4net>
这是 program.cs 文件,它获取 ILog 对象的实例并手动加载配置。
public class Program
{
private static readonly log4net.ILog log =
log4net.LogManager.GetLogger(typeof(Program));
public static void Main(string[] args)
{
XmlDocument log4netConfig = new XmlDocument();
log4netConfig.Load(File.OpenRead("log4net.config"));
var repo = log4net.LogManager.CreateRepository(
Assembly.GetEntryAssembly(), typeof(log4net.Repository.Hierarchy.Hierarchy));
log4net.Config.XmlConfigurator.Configure(repo, log4netConfig["log4net"]);
log.Info("Application - Main is invoked");
//Lines removed for brevity
}
}
在根文件夹中添加的 log4net.config 文件。现在您可以运行该应用程序,您会看到在 C:\temp 文件夹中创建了一个名为 app.log 的文件。如果您查看它,您只会看到添加了我们记录的信息。但是如果你想要类似于 ASP.NET Core 日志的东西,你需要自己实现提供者和扩展方法。
这是实现,它可以帮助您进行类似于现有 ASP.NET Core 日志记录实现的日志记录。
首先,您需要使用 Log4Net 库实现 ILogger 接口。这是实现。
public class Log4NetLogger : ILogger
{
private readonly string _name;
private readonly XmlElement _xmlElement;
private readonly ILog _log;
private ILoggerRepository _loggerRepository;
public Log4NetLogger(string name, XmlElement xmlElement)
{
_name = name;
_xmlElement = xmlElement;
_loggerRepository = log4net.LogManager.CreateRepository(
Assembly.GetEntryAssembly(), typeof(log4net.Repository.Hierarchy.Hierarchy));
_log = LogManager.GetLogger(_loggerRepository.Name, name);
log4net.Config.XmlConfigurator.Configure(_loggerRepository, xmlElement);
}
public IDisposable BeginScope<TState>(TState state)
{
return null;
}
public bool IsEnabled(LogLevel logLevel)
{
switch (logLevel)
{
case LogLevel.Critical:
return _log.IsFatalEnabled;
case LogLevel.Debug:
case LogLevel.Trace:
return _log.IsDebugEnabled;
case LogLevel.Error:
return _log.IsErrorEnabled;
case LogLevel.Information:
return _log.IsInfoEnabled;
case LogLevel.Warning:
return _log.IsWarnEnabled;
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));
}
string message = null;
if (null != formatter)
{
message = formatter(state, exception);
}
if (!string.IsNullOrEmpty(message) || exception != null)
{
switch (logLevel)
{
case LogLevel.Critical:
_log.Fatal(message);
break;
case LogLevel.Debug:
case LogLevel.Trace:
_log.Debug(message);
break;
case LogLevel.Error:
_log.Error(message);
break;
case LogLevel.Information:
_log.Info(message);
break;
case LogLevel.Warning:
_log.Warn(message);
break;
default:
_log.Warn($"Encountered unknown log level {logLevel}, writing out as Info.");
_log.Info(message, exception);
break;
}
}
}
}
并且需要使用 ILoggerProvider 实现将此记录器提供给记录器工厂扩展。这是 ILoggerProvider 实现。我从 ASP.NET Core 实现的控制台记录器提供程序实现中获取的大部分代码。配置解析在这个类内部实现。
public class Log4NetProvider : ILoggerProvider
{
private readonly string _log4NetConfigFile;
private readonly ConcurrentDictionary<string, Log4NetLogger> _loggers =
new ConcurrentDictionary<string, Log4NetLogger>();
public Log4NetProvider(string log4NetConfigFile)
{
_log4NetConfigFile = log4NetConfigFile;
}
public ILogger CreateLogger(string categoryName)
{
return _loggers.GetOrAdd(categoryName, CreateLoggerImplementation);
}
public void Dispose()
{
_loggers.Clear();
}
private Log4NetLogger CreateLoggerImplementation(string name)
{
return new Log4NetLogger(name, Parselog4NetConfigFile(_log4NetConfigFile));
}
private static XmlElement Parselog4NetConfigFile(string filename)
{
XmlDocument log4netConfig = new XmlDocument();
log4netConfig.Load(File.OpenRead(filename));
return log4netConfig["log4net"];
}
}
最后,您需要 ILoggerFactory 扩展方法,这有助于将 Log4Net 添加到记录器工厂。这是扩展方法的实现。
public static class Log4netExtensions
{
public static ILoggerFactory AddLog4Net(this ILoggerFactory factory, string log4NetConfigFile)
{
factory.AddProvider(new Log4NetProvider(log4NetConfigFile));
return factory;
}
public static ILoggerFactory AddLog4Net(this ILoggerFactory factory)
{
factory.AddProvider(new Log4NetProvider("log4net.config"));
return factory;
}
}
你可以使用这个内部Configure()方法。
public void Configure(IApplicationBuilder app,
IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddLog4Net();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvcWithDefaultRoute();
}
现在您可以再次运行该应用程序,您可以看到充满大量日志记录详细信息的日志文件。
这是 log4net 创建的日志文件的屏幕截图。