log4net - 设置 XML 配置以使用运行时指定的 FileAppender 路径
log4net - set up XML config to use runtime-specified path for FileAppender
我们正在构建一个 Unity 游戏客户端,它将在(至少)Windows、OS X 和 iOS 上 运行。我正在使用 log4net 来处理日志记录,我想使用 FileAppender
将错误记录到一个文件中以协助错误报告。我想将此文件放在 UnityEngine.Application.persistentDataPath
指向的任何目录中,这样无论 OS 如何,文件都会出现在合理的地方,我正在努力寻找一种将其插入 [=29] 的方法=] 配置我传递给 log4net 的 XMLConfigurator
.
我可以设置一个虚拟路径并在 运行 时更改它,但是(除了笨拙之外)这有一个缺点,即到我可以更改 FileAppender
的设置时,它已经在我放入 XML 配置的任何位置创建了一个空日志文件,这意味着我之后需要清理空文件。
那么,有没有办法在 XML 配置文件中将 FileAppender
指向 UnityEngine.Application.persistentDataPath
?
您可以创建自定义 PatternConverter
以允许您执行此操作
XMLConfigurator
在运行时解析 %someString
变量,所以你可以设置自定义 PatternConverter
到 return UnityEngine.Application.persistentDataPath
的值,并设置向上 XML 以便配置器将使用它来解析您的变量之一。
所以,您需要这样的 class:
public class PersistentDataStoreConverter : PatternConverter {
protected override void Convert(TextWriter writer, object state) {
writer.Write(UnityEngine.Application.persistentDataPath);
}
}
然后您可以在 XML 配置中使用该转换器,如下所示:
<appender name="Logfile" type="log4net.Appender.FileAppender">
<file type="log4net.Util.PatternString">
<converter>
<!-- Tell the configurator that this is the converter for "%persistentDataStore" below -->
<name value="persistentDataStore" />
<!-- Tell the converter what to call to do the conversion -->
<type value="Namespace.PersistentDataStoreConverter, AssemblyName" />
</converter>
<conversionPattern value="%persistentDataStore/logfile-%date{yyyy-MM-dd-HH-mm-ss}.log" />
</file>
<!-- Also specify layout etc... -->
</appender>
一个常见的方法是设置一个 属性 ,它在配置期间被评估:注意 file
属性必须设置为类型 PatternString
才能评估变量:
[TestMethod]
public void Set_Log_Path_At_Runtime()
{
log4net.GlobalContext.Properties["logpath"] =
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Test.log");
// Use stream as is convenient for a unit test, in normal usage
// would probably want to use the overload that takes a fileinfo.
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(config)))
XmlConfigurator.Configure(ms);
var appender = log4net.LogManager.GetRepository()
.GetAppenders()
.OfType<RollingFileAppender>()
.First();
Console.WriteLine(appender.File);
}
private const string config = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
<log4net debug=""false"">
<appender name=""RollingFileAppender"" type=""log4net.Appender.RollingFileAppender"">
<file type=""log4net.Util.PatternString"" value=""%property{logpath}"" />
<lockingModel type=""log4net.Appender.FileAppender+MinimalLock"" />
<layout type=""log4net.Layout.PatternLayout"">
<conversionPattern value=""%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"" />
</layout>
</appender>
<root>
<level value=""ALL"" />
<appender-ref ref=""RollingFileAppender"" />
</root>
</log4net>";
因为这是使用 the overload of Configure that takes a Stream,将 XML 加载到变量中,将文件位置从占位符更改为实际位置,并将其作为流传递到已配置。
我们正在构建一个 Unity 游戏客户端,它将在(至少)Windows、OS X 和 iOS 上 运行。我正在使用 log4net 来处理日志记录,我想使用 FileAppender
将错误记录到一个文件中以协助错误报告。我想将此文件放在 UnityEngine.Application.persistentDataPath
指向的任何目录中,这样无论 OS 如何,文件都会出现在合理的地方,我正在努力寻找一种将其插入 [=29] 的方法=] 配置我传递给 log4net 的 XMLConfigurator
.
我可以设置一个虚拟路径并在 运行 时更改它,但是(除了笨拙之外)这有一个缺点,即到我可以更改 FileAppender
的设置时,它已经在我放入 XML 配置的任何位置创建了一个空日志文件,这意味着我之后需要清理空文件。
那么,有没有办法在 XML 配置文件中将 FileAppender
指向 UnityEngine.Application.persistentDataPath
?
您可以创建自定义 PatternConverter
以允许您执行此操作
XMLConfigurator
在运行时解析 %someString
变量,所以你可以设置自定义 PatternConverter
到 return UnityEngine.Application.persistentDataPath
的值,并设置向上 XML 以便配置器将使用它来解析您的变量之一。
所以,您需要这样的 class:
public class PersistentDataStoreConverter : PatternConverter {
protected override void Convert(TextWriter writer, object state) {
writer.Write(UnityEngine.Application.persistentDataPath);
}
}
然后您可以在 XML 配置中使用该转换器,如下所示:
<appender name="Logfile" type="log4net.Appender.FileAppender">
<file type="log4net.Util.PatternString">
<converter>
<!-- Tell the configurator that this is the converter for "%persistentDataStore" below -->
<name value="persistentDataStore" />
<!-- Tell the converter what to call to do the conversion -->
<type value="Namespace.PersistentDataStoreConverter, AssemblyName" />
</converter>
<conversionPattern value="%persistentDataStore/logfile-%date{yyyy-MM-dd-HH-mm-ss}.log" />
</file>
<!-- Also specify layout etc... -->
</appender>
一个常见的方法是设置一个 属性 ,它在配置期间被评估:注意 file
属性必须设置为类型 PatternString
才能评估变量:
[TestMethod]
public void Set_Log_Path_At_Runtime()
{
log4net.GlobalContext.Properties["logpath"] =
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Test.log");
// Use stream as is convenient for a unit test, in normal usage
// would probably want to use the overload that takes a fileinfo.
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(config)))
XmlConfigurator.Configure(ms);
var appender = log4net.LogManager.GetRepository()
.GetAppenders()
.OfType<RollingFileAppender>()
.First();
Console.WriteLine(appender.File);
}
private const string config = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
<log4net debug=""false"">
<appender name=""RollingFileAppender"" type=""log4net.Appender.RollingFileAppender"">
<file type=""log4net.Util.PatternString"" value=""%property{logpath}"" />
<lockingModel type=""log4net.Appender.FileAppender+MinimalLock"" />
<layout type=""log4net.Layout.PatternLayout"">
<conversionPattern value=""%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"" />
</layout>
</appender>
<root>
<level value=""ALL"" />
<appender-ref ref=""RollingFileAppender"" />
</root>
</log4net>";
因为这是使用 the overload of Configure that takes a Stream,将 XML 加载到变量中,将文件位置从占位符更改为实际位置,并将其作为流传递到已配置。