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 文档中找到有关日志记录提供程序和级别的更多信息。

    1. <?xml version="1.0" encoding="utf-8" ?>
    2. <log4net>
    3. <appender name="RollingFile" type="log4net.Appender.FileAppender">
    4. <file value="C:\Temp\app.log" />
    5. <layout type="log4net.Layout.PatternLayout">
    6. <conversionPattern value="%-5p %d{hh:mm:ss} %message%newline" />
    7. </layout>
    8. </appender>
    9. <root>
    10. <level value="ALL" />
    11. <appender-ref ref="RollingFile" />
    12. </root>
    13. </log4net>

    这是 program.cs 文件,它获取 ILog 对象的实例并手动加载配置。

    1. public class Program
    2. {
    3. private static readonly log4net.ILog log =
    4. log4net.LogManager.GetLogger(typeof(Program));
    5. public static void Main(string[] args)
    6. {
    7. XmlDocument log4netConfig = new XmlDocument();
    8. log4netConfig.Load(File.OpenRead("log4net.config"));
    9. var repo = log4net.LogManager.CreateRepository(
    10. Assembly.GetEntryAssembly(), typeof(log4net.Repository.Hierarchy.Hierarchy));
    11. log4net.Config.XmlConfigurator.Configure(repo, log4netConfig["log4net"]);
    12. log.Info("Application - Main is invoked");
    13. //Lines removed for brevity
    14. }
    15. }

    在根文件夹中添加的 log4net.config 文件。现在您可以运行该应用程序,您会看到在 C:\temp 文件夹中创建了一个名为 app.log 的文件。如果您查看它,您只会看到添加了我们记录的信息。但是如果你想要类似于 ASP.NET Core 日志的东西,你需要自己实现提供者和扩展方法。
    这是实现,它可以帮助您进行类似于现有 ASP.NET Core 日志记录实现的日志记录。
    首先,您需要使用 Log4Net 库实现 ILogger 接口。这是实现。

    1. public class Log4NetLogger : ILogger
    2. {
    3. private readonly string _name;
    4. private readonly XmlElement _xmlElement;
    5. private readonly ILog _log;
    6. private ILoggerRepository _loggerRepository;
    7. public Log4NetLogger(string name, XmlElement xmlElement)
    8. {
    9. _name = name;
    10. _xmlElement = xmlElement;
    11. _loggerRepository = log4net.LogManager.CreateRepository(
    12. Assembly.GetEntryAssembly(), typeof(log4net.Repository.Hierarchy.Hierarchy));
    13. _log = LogManager.GetLogger(_loggerRepository.Name, name);
    14. log4net.Config.XmlConfigurator.Configure(_loggerRepository, xmlElement);
    15. }
    16. public IDisposable BeginScope<TState>(TState state)
    17. {
    18. return null;
    19. }
    20. public bool IsEnabled(LogLevel logLevel)
    21. {
    22. switch (logLevel)
    23. {
    24. case LogLevel.Critical:
    25. return _log.IsFatalEnabled;
    26. case LogLevel.Debug:
    27. case LogLevel.Trace:
    28. return _log.IsDebugEnabled;
    29. case LogLevel.Error:
    30. return _log.IsErrorEnabled;
    31. case LogLevel.Information:
    32. return _log.IsInfoEnabled;
    33. case LogLevel.Warning:
    34. return _log.IsWarnEnabled;
    35. default:
    36. throw new ArgumentOutOfRangeException(nameof(logLevel));
    37. }
    38. }
    39. public void Log<TState>(LogLevel logLevel, EventId eventId, TState state,
    40. Exception exception, Func<TState, Exception, string> formatter)
    41. {
    42. if (!IsEnabled(logLevel))
    43. {
    44. return;
    45. }
    46. if (formatter == null)
    47. {
    48. throw new ArgumentNullException(nameof(formatter));
    49. }
    50. string message = null;
    51. if (null != formatter)
    52. {
    53. message = formatter(state, exception);
    54. }
    55. if (!string.IsNullOrEmpty(message) || exception != null)
    56. {
    57. switch (logLevel)
    58. {
    59. case LogLevel.Critical:
    60. _log.Fatal(message);
    61. break;
    62. case LogLevel.Debug:
    63. case LogLevel.Trace:
    64. _log.Debug(message);
    65. break;
    66. case LogLevel.Error:
    67. _log.Error(message);
    68. break;
    69. case LogLevel.Information:
    70. _log.Info(message);
    71. break;
    72. case LogLevel.Warning:
    73. _log.Warn(message);
    74. break;
    75. default:
    76. _log.Warn($"Encountered unknown log level {logLevel}, writing out as Info.");
    77. _log.Info(message, exception);
    78. break;
    79. }
    80. }
    81. }
    82. }

    并且需要使用 ILoggerProvider 实现将此记录器提供给记录器工厂扩展。这是 ILoggerProvider 实现。我从 ASP.NET Core 实现的控制台记录器提供程序实现中获取的大部分代码。配置解析在这个类内部实现。

    1. public class Log4NetProvider : ILoggerProvider
    2. {
    3. private readonly string _log4NetConfigFile;
    4. private readonly ConcurrentDictionary<string, Log4NetLogger> _loggers =
    5. new ConcurrentDictionary<string, Log4NetLogger>();
    6. public Log4NetProvider(string log4NetConfigFile)
    7. {
    8. _log4NetConfigFile = log4NetConfigFile;
    9. }
    10. public ILogger CreateLogger(string categoryName)
    11. {
    12. return _loggers.GetOrAdd(categoryName, CreateLoggerImplementation);
    13. }
    14. public void Dispose()
    15. {
    16. _loggers.Clear();
    17. }
    18. private Log4NetLogger CreateLoggerImplementation(string name)
    19. {
    20. return new Log4NetLogger(name, Parselog4NetConfigFile(_log4NetConfigFile));
    21. }
    22. private static XmlElement Parselog4NetConfigFile(string filename)
    23. {
    24. XmlDocument log4netConfig = new XmlDocument();
    25. log4netConfig.Load(File.OpenRead(filename));
    26. return log4netConfig["log4net"];
    27. }
    28. }

    最后,您需要 ILoggerFactory 扩展方法,这有助于将 Log4Net 添加到记录器工厂。这是扩展方法的实现。

    1. public static class Log4netExtensions
    2. {
    3. public static ILoggerFactory AddLog4Net(this ILoggerFactory factory, string log4NetConfigFile)
    4. {
    5. factory.AddProvider(new Log4NetProvider(log4NetConfigFile));
    6. return factory;
    7. }
    8. public static ILoggerFactory AddLog4Net(this ILoggerFactory factory)
    9. {
    10. factory.AddProvider(new Log4NetProvider("log4net.config"));
    11. return factory;
    12. }
    13. }

    你可以使用这个内部Configure()方法。

    1. public void Configure(IApplicationBuilder app,
    2. IHostingEnvironment env, ILoggerFactory loggerFactory)
    3. {
    4. loggerFactory.AddLog4Net();
    5. if (env.IsDevelopment())
    6. {
    7. app.UseDeveloperExceptionPage();
    8. }
    9. app.UseMvcWithDefaultRoute();
    10. }

    现在您可以再次运行该应用程序,您可以看到充满大量日志记录详细信息的日志文件。
    这是 log4net 创建的日志文件的屏幕截图。
    image.png