问题说明
配置文件示例
在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));
}
本人亲自测试没毛病。欢迎各位批评指正。