真正运行时修改log4net多个Appender的存储路径

问题说明

配置文件示例

在Net程序中,经常使用log4net存储日志文件,下面是一个log4net配置文件的示例,文件名为log.config。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<log4net>
  <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender" >
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
    <file value="Logs/App_" />
    <datePattern value="yyyyMMdd.'txt'"/>
    <appendToFile value="true" />
    <!--<rollingStyle value="Date" />-->
    <staticLogFileName value="false"/>
    <rollingStyle value="Date" />
    <maxSizeRollBackups value="10"/>
    <maximumFileSize value="1MB"/>
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%-5level - %date - [%-5.5thread] - %logger - [%class.%method] - %f - %l %message%newline" />
    </layout>
  </appender>

  <appender name="PlcAppender" type="log4net.Appender.RollingFileAppender" >
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
    <file value="Logs/Plc_" />
    <datePattern value="yyyyMMdd HH.'txt'"/>
    <appendToFile value="true" />
    <rollingStyle value="Composite" />
    <staticLogFileName value="false"/>
    <maxSizeRollBackups value="10"/>
    <maximumFileSize value="1MB"/>
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%-5level - %date - [%-5.5thread] - %logger - [%class.%method] - %f - %l %message%newline" />
    </layout>
  </appender>

  <appender name="DebugAppender" type="log4net.Appender.RollingFileAppender" >
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
    <file value="Logs/Debug_" />
    <datePattern value="yyyyMMdd.'txt'"/>
    <appendToFile value="true" />
    <!--<rollingStyle value="Date" />-->
    <staticLogFileName value="false"/>
    <rollingStyle value="Composite" />
    <maxSizeRollBackups value="10"/>
    <maximumFileSize value="1MB"/>
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%-5level - %date - [%-5.5thread] - %logger - [%class.%method] - %f - %l %message%newline" />
    </layout>
  </appender>
    
  <appender name="DbAppender" type="log4net.Appender.RollingFileAppender" >
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
    <file value="Logs/Db_" />
    <datePattern value="yyyyMMdd.'txt'"/>
    <appendToFile value="true" />
    <staticLogFileName value="false"/>
    <rollingStyle value="Composite" />
    <maxSizeRollBackups value="10"/>
    <maximumFileSize value="1MB"/>
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%-5level - %date - [%-5.5thread] - %logger - [%class.%method] - %f - %l %message%newline" />
    </layout>
  </appender>  
  
  <!--<root>
    <appender-ref ref="RollingFileAppender" />
    <level value="DEBUG" />
  </root>-->
  <logger name="AppLogger" additivity="false">
    <level value="ALL" />
    <appender-ref ref="RollingFileAppender" />
  </logger>
  <!--PLC日志-->
  <logger name="PlcLogger" additivity="false">
    <level value="ALL" />
    <!--<appender-ref ref="RollingFileAppender" />-->
    <appender-ref ref ="PlcAppender"/>
  </logger>
  <!-- 调试日志-->
  <logger name="DebugLogger" additivity="false">
    <level value="ALL" />
    <appender-ref ref ="DebugAppender"/>
  </logger>
  
  <!-- 数据库日志-->
  <logger name="DbLogger" additivity="false">
    <level value="ALL" />
    <appender-ref ref ="DbAppender"/>
  </logger>  
    
</log4net>
</configuration>

从配置文件可以看出来,有4个Appender,软件会建立4个日志文件,路径都在Logs/文件夹下,通常这个Logs文件夹在主程序所在路径下。要注意的是每个日志文件的文件名不同,例如DbAppender的日志文件名为Db_xxxx.txt,而DebugAppender的日志文件名为Debug_xxxx.txt。

修改存储路径

如果用户想改变这个路径到其它位置该怎么办呢?
方法1:修改这个配置文件log.config里边的每个Appender的配置;
方法2:在软件运行时动态修改Appender的参数。
网上最典型的修改文件名的办法,非常好,缺点是不够彻底。
下面的例子引用自https://blog.csdn.net/yw1688/article/details/52590072

/// <summary>
        /// 改变默认的日志位置
        /// </summary>
        /// <param name="folder"></param>
        public static void UpdateFolder(string folder)
        {
            var storedPath = LogManager.GetRepository();
            var appenders = storedPath.GetAppenders();
            //一般多种日志目录是写在一起
            if (appenders == null) return;
            foreach (var app in appenders)
            {
                if (app.Name.Equals("ErrorAppender") || app.Name.Equals("InfoAppender"))
                {
                    var ra = app as RollingFileAppender;
                    ra.File = folder;
                    ra.ActivateOptions();
                }
            }
        }

这个例子的结果是,所有Appender的存储文件名变成同一个,因此不是修改存储路径,而是修改存储文件名。

修改多个Appender的存储路径

没有datePattern设置的情况

下面是本篇在上述原理基础上的改进。

        public static void ChangeDir(string configFile,string newDir)
        {
            XmlConfigurator.Configure(new FileInfo(configFile));
            var curPath = LogManager.GetRepository();
            var appenders = curPath.GetAppenders();
            if (appenders == null)
                return;
            foreach (var appender in appenders)
            {
                var rollingFileAppender = appender as RollingFileAppender;
                if(rollingFileAppender == null)
                    continue;
                var oldPath = rollingFileAppender.File;
                var oldFile = Path.GetFileName(oldPath);
                if(oldFile == null)
                    continue;
                var newFile = Path.Combine(newDir, oldFile);
                rollingFileAppender.File = newFile;
                rollingFileAppender.ActivateOptions();
            }
        }

调用方法如下。

LogHelper.ChangeDir("Log.config",newDir);

有datePattern设置的情况

本篇的log4net的配置文件中由于有datePattern配置,修改日志路径要用如下方法。

 public static void ChangeDir(string configFile,string newDir)
        {
            XmlConfigurator.Configure(new FileInfo(configFile));
            var curPath = LogManager.GetRepository();
            var appenders = curPath.GetAppenders();
            if (appenders == null)
                return;
            foreach (var appender in appenders)
            {
                var rollingFileAppender = appender as RollingFileAppender;
                if(rollingFileAppender == null)
                    continue;
                var oldPath = rollingFileAppender.File;
                var oldFile = Path.GetFileName(oldPath);
                if(oldFile == null)
                    continue;
                var newFile = Path.Combine(newDir, oldFile);

                rollingFileAppender.Writer = new StreamWriter(newFile, rollingFileAppender.AppendToFile,rollingFileAppender.Encoding);
            }
        }

即不能用修改appender的File属性,而是,直接指定Writer属性的内容。

修改配置文件方法

有些复杂datepattern,修改后,log4net会在file属性的值变了后,又恢复的配置文件的file的设置模式,因此最彻底的方法还是修改xml文件。
代码如下。

        public static void ChangeDirXml(string configFile, string newDir)
        {

            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(configFile);
            XmlNode nodes= xmlDoc.SelectSingleNode("configuration");
            var appenderNodes = nodes.ChildNodes[0];
            foreach (XmlNode xn in appenderNodes)
            {
                if (xn.Name == "appender")
                {
                    foreach (XmlNode ele in xn)
                    {
                        if (ele.Name == "#comment")
                            continue;
                        
                        XmlElement xe = (XmlElement)ele;
                        if (xe.Name != "file")
                        {
                            continue;
                            
                        }
                        var oldFileValue = xe.GetAttribute("value");
                        var oldFile = Path.GetFileName(oldFileValue);
                        if (oldFile == null)
                            continue;
                        var newFile = Path.Combine(newDir, oldFile);

                        xe.SetAttribute("value", newFile);                       
                    }
                }
                
            }
            xmlDoc.Save(configFile);

            XmlConfigurator.Configure(new FileInfo(configFile));

        }

本人亲自测试没毛病。欢迎各位批评指正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章