使用Log4Net根据log level的不同将log输出到不同的文件中

2,038 阅读3分钟

在我们的日常开发过程中log的输出是必不可少且至关重要的工作,能够将log明确的输出有助于我们快速定位并解决相关问题,该篇文章主要介绍一下如何使用Log4Net根据log level的不同将log输出到不同的文件中,主要是将error级别的log和其他级别的log进行分离输出,这样我们可以在特定的文件中看到全部的error信息。

第一步:首先通过log4net.config文件来定义log4net配置信息:

<?xml version="1.0" encoding="UTF-8"?>
<log4net>
  <root>
    <level value="DEBUG" />
    <!--<level value="INFO" />-->
    <!-- 预先定义两种appender类型,LogFileAppender类型用来定义普通log的输出,
HighLevelFileLogAppender类型用来定义Error级别的log的输出-->
    <appender-ref ref="LogFileAppender" />
    <appender-ref ref="HighLevelFileLogAppender" />
  </root>
  <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
    <param name="File" value="Logs\CommonSolution_.log" />
    <param name="AppendToFile" value="true" />
    <rollingStyle value="Composite" />
    <maximumFileSize value="5MB" />
    <!--<param name="DatePattern" value="yyyy-MM-dd&quot;.log&quot;"/>-->
    <param name="DatePattern" value="yyyy-MM-dd" />
    <param name="StaticLogFileName" value="false" />
    <maxSizeRollBackups value="5" />
    <preserveLogFileNameExtension value="true" />
    <encoding value="UTF-8" />
    <layout type="log4net.Layout.PatternLayout">
      <header value="Level DateTime Version Thread Class EventID- Message &#xD;&#xA;" />
      <param name="ConversionPattern" value="%-5level %date{MM-dd HH:mm:ss,fff} %property{Version} %thread %logger %property{EventID}- %message  %newline" />
    </layout>
    <!--添加log输出的过滤规则,输出的最小log级别为DEBUG,最大log级别为WARN-->
    <filter type="log4net.Filter.LevelRangeFilter">
      <levelMin value="DEBUG" />
      <levelMax value="WARN" />
    </filter>
  </appender>
  <appender name="HighLevelFileLogAppender" type="log4net.Appender.RollingFileAppender">
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
    <param name="File" value="Logs\CommonSolution_" />
    <param name="AppendToFile" value="true" />
    <param name="DatePattern" value="yyyy-MM-dd&quot;-High.log&quot;" />
    <param name="StaticLogFileName" value="false" />
    <rollingStyle value="Composite" />
    <maximumFileSize value="5MB" />
    <maxSizeRollBackups value="5" />
    <encoding value="UTF-8" />
    <layout type="log4net.Layout.PatternLayout">
      <header value="Level DateTime Version Thread Class EventID- Message &#xD;&#xA;" />
      <param name="ConversionPattern" value="%-5level %date{MM-dd HH:mm:ss,fff} %property{Version} %thread %logger %property{EventID}- %message  %newline" />
    </layout>
    <filter type="log4net.Filter.LevelRangeFilter">
      <!--添加log输出的过滤规则,输出的最小log级别为ERROR,最大log级别为ERROR-->
      <levelMin value="ERROR"/>
      <levelMax value="ERROR"/>
    </filter>
  </appender>
</log4net>

第二步:封装一个简单的LogHelper类,用来管理Log对象的创建:

using log4net;
using log4net.Config;
using log4net.Repository;
using System;
using System.Collections.Concurrent;
using System.IO;

namespace CommonSolution.Util.Log
{
    public class LogHelper
    {
        public static ILoggerRepository logRepository { get; set; }
        private const string RepositoryName = "NetCoreRepository";
        private static readonly ConcurrentDictionary<Type, ILog> Loggers = new ConcurrentDictionary<Type, ILog>();
        public static void InitLogger(string filePath)
        {
            logRepository = LogManager.CreateRepository(RepositoryName);
            XmlConfigurator.Configure(logRepository, new FileInfo(filePath));
        }

        /// <summary>
        /// 动态修改log文件的存储地址
        /// </summary>
        /// <param name="folder">要存储log文件的保存地址</param>
        /// <param name="fileName">要存储的log文件的name</param>
        public static void UpdateLogStoreFolder(string folder, string fileName)
        {
            var storedPath = LogManager.GetRepository(RepositoryName);
            var appenders = storedPath.GetAppenders();
            if (appenders == null) return;
            foreach (var app in appenders)
            {
                if (app.Name.Equals("LogFileAppender") || app.Name.Equals("HighLevelFileLogAppender"))
                {
                    var ra = app as RollingFileAppender;
                    ra.File = Path.Combine(folder, fileName + "-");
                    ra.ActivateOptions();
                }
            }
        }

        public static ILog GetLogger(Type source)
        {
            ILog log;
            if (!Loggers.TryGetValue(source, out log))
            {
                log = LogManager.GetLogger(RepositoryName, source);
                Loggers.TryAdd(source, log);
            }
            return log;
        }
    }
}

第三步:在工程中使用LogHelper来完成log的输出,以.Net Core工程为例子,我们首先需要在工程的Startup.cs中调用LogHelper中的InitLogger方法初始化log4net,方法参数为log4net.config配置文件路径:

 public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
            var logFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Configuration.GetValue<string>("Log4NetFile"));
            LogHelper.InitLogger(logFilePath);
        }

第四步:在程序中输出log:

 public class HomeController : Controller { 
       private readonly ILog _log = LogHelper.GetLogger(typeof(HomeController));

        public IActionResult Index()
        {
            _log.Warn("This is Warn Message");
            _log.Debug("This is Debug Message");
            _log.Info("This is Info Message");
            _log.Error("This is Error Message");
            return View();
        }
}

输出结果如图所示:




这样我们就完成了根据log level的不同将log输出到不同的文件中的全部工作,希望能为大家的实际开发带来帮助。