当前位置: 动力学知识库 > 问答 > 编程问答 >

log4net - set up XML config to use runtime-specified path for FileAppender

问题描述:

We are building a Unity game client that will be run on (at least) Windows, OS X, and iOS. I'm using log4net to handle logging, and I want to log errors to a file using a FileAppender to assist with bug reports. I want to place this file in whichever directory UnityEngine.Application.persistentDataPath points to, so that the file will appear somewhere sensible regardless of OS, and I'm struggling to find a way of plugging this into the XML config I'm passing to log4net's XMLConfigurator.

I can set a dummy path and change it at runtime, but (aside from being clunky) this has the drawback that by the time I can alter the setup of the FileAppender, it's already created an empty logfile at whatever location I put into the XML config, which means I then need to clean up the empty file afterwards.

So, is there a way to point a FileAppender at UnityEngine.Application.persistentDataPath in an XML config file?

网友答案:

You can create a custom PatternConverter to allow you to do this

The XMLConfigurator resolves %someString variables at runtime, so you can set up a custom PatternConverter to return the value of UnityEngine.Application.persistentDataPath, and set up the XML so that the configurator will use it to resolve one of your variables.

So, you'll need a class like this:

public class PersistentDataStoreConverter : PatternConverter {
    protected override void Convert(TextWriter writer, object state) {
        writer.Write(UnityEngine.Application.persistentDataPath);
    }
}

You can then use that converter in the XML config like so:

<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>
网友答案:

A common way to do this is to set a property which is evaluated during configuration: note that the file attribute must be set to type PatternString in order to evaluate the variable:

[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>";

As this is using the overload of Configure that takes a Stream, it would be just as easy to load the XML into a variable, change the file location from placeholder to actual, and pass that as a stream to be configured.

分享给朋友:
您可能感兴趣的文章:
随机阅读: