.NET Core引入日志(Log4Net篇)


Demo版本信息如下:

VS:2019

框架:.Net Core 3.1

Log4Net:2.0.12

思维导图:

【1】添加依赖项

  通过nuget添加Log4Net

【2】创建公共类

  添加公共类Log4NetLogger,实现ILogger, ILoggerProvider,扩展方法Log4netExtensions

   /// 
    /// ILogger
    /// 
    public class Log4NetLogger : ILogger
    {
        private readonly ILog _log;
        private ILoggerRepository _loggerRepository;
        public Log4NetLogger(string 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 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(LogLevel logLevel, EventId eventId, TState state,
            Exception exception, Funcstring> 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
    /// 
    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"];
        }
    }

    /// 
    /// 扩展方法 Log4netExtensions
    /// 
    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;
        }
    }

【3】Startup

  在Startup中注册log4net

  

【5】配置文件

  添加log4Net.config配置文件,需要注意,log4Net.config文件一定要放在项目的根目录,其次,“属性”—“复制到输出目录”要设置为“始终复制”

<?xml version="1.0" encoding="utf-8" ?>


  "ErrorRollingFileAppender" type="log4net.Appender.RollingFileAppender">
    "D://log//Error//" />
    "true" />
    "Date"/>
    "yyyy-MM-dd'.log'"/>
    "100" />
    "false" />
    "utf-8" />
    "log4net.Layout.PatternLayout">
      "%newline%date [%thread %-5level] %n -- %m%n" />
    
    "log4net.Filter.LevelRangeFilter">
      "ERROR" />
      "FATAL" />
    
  

  "WarnRollingFileAppender" type="log4net.Appender.RollingFileAppender">
    "D://log//Warn//" />
    "true" />
    "Date"/>
    "yyyy-MM-dd'.log'"/>
    "100" />
    "false" />
    "utf-8" />
    "log4net.Layout.PatternLayout">
      "%newline%date [%thread %-5level] %n -- %m%n" />
    
    "log4net.Filter.LevelRangeFilter">
      "WARN" />
      "WARN" />
    
  

  "InfoRollingFileAppender" type="log4net.Appender.RollingFileAppender">
    "D://log//Info//" />
    "true" />
    "Date"/>
    "yyyy-MM-dd'.log'"/>
    "100" />
    "false" />
    "utf-8" />
    "log4net.Layout.PatternLayout">
      "%newline%date [%thread %-5level] %n -- %m%n" />
    
    "log4net.Filter.LevelRangeFilter">
      "TRACE " />
      "INFO" />
    
  

  
    "All" />
    ref ref="ErrorRollingFileAppender" />
    ref ref="WarnRollingFileAppender" />
    ref ref="InfoRollingFileAppender" />
  

【6】测试

  此Demo通过MVC实现测试,所以需要添加控制器与视图。

  1、同时在Startup中注册MVC相关服务,services.AddControllersWithViews();

  

   2、更改Configure中的UseEndpoints请求为MVC路由配置

  

    app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}"
                    );
            });

  3、控制器中获取对象

     private readonly ILogger _logger;

        /// 
        /// **************通过构造方法获取注册的Log4Net服务
        /// 
        /// 
        public HomeController(ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger();
        }

  4、调用

     public IActionResult Index()
        {
            //************** 日志对象的引用
            _logger.LogInformation($"这是一个一般的日志消息");
            _logger.LogWarning($"这是一个警告的日志消息");
            _logger.LogError($"这是一个错误的日志消息");
            return View();
        }