8
votes

I am trying to write a C# code, which retrieves in runtime the name pattern of a log4net log file via the log4net API.

That is, if in log4net.config the following appender is defined:

<appender name="MyAppender" type="log4net.Appender.RollingFileAppender">
  <file type="log4net.Util.PatternString" value="%date{yyyy}\%date{MM}\%date{dd}\%property{Id}.log" />
  <appendToFile value="true" />
  <rollingStyle value="Size" />
  <maxSizeRollBackups value="16" />
  <maximumFileSize value="1MB" />
  <staticLogFileName value="true" />
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%message%newline" />
  </layout>
</appender>

I would like to get %date{yyyy}\%date{MM}\%date{dd}\%property{Id}.log in a string variable in code (without parsing log4net.config as a plain XML).

Does anybody has an idea ho to pull this trick?

Thank you in advance.

4

4 Answers

2
votes

The value for this pattern will be in the File property of a FileAppender instance that's part of your logging repository.

Getting at the appender can be done in a couple of different ways.

  1. If you already have an ILogger instance (e.g. what you get from LogManager.GetLogger()) then there's an Appenders property on it. This will give you any appenders associated with that specific level of the logging heirarchy.
  2. You can also call LogManager.GetRepository() to get a Heirarchy object that contains the entire logger and appender heirarchy. The method expects an assembly, so pass GetCallingAssembly() to get the default one. This class has a GetAppenders() method that returns all configured appenders, though it won't tell you which ones are associated with which loggers.

From there, just look through looking for an appender of the correct type (e.g. FileAppender or RollingFileAppender), then read it's File property.

1
votes

Explanation of Michael Edenfield is good. Here's realization.

private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

string fileName = ((RollingFileAppender)log.Logger.Repository.GetCurrentLoggers()
    .Where(e => e.Name == "Your namespace.class").ToList()[0]
    .Repository.GetAppenders()
    .Where(e => e.Name == "MyAppender").ToList()[0]).File.ToString();
0
votes

I think that you want to subclass RollingFileAppender, and use your subclass in the config file, instead of the base class. Make sure to prefix the classname with full namespace so log4net can find it.

I have only a UDPAppender subclassed in my code. I added an override like this:

    public override void ActivateOptions()
    {
        base.ActivateOptions();
    }

When I broke before the base class call, I examined 'this' in the locals window and saw the values for the UDPAppender 'members'.

0
votes

I can obtain the value of the <file value> with the following code:

((log4net.Appender.FileAppender) ((log4net.Appender.IAppender[])
            ( (log4net.Repository.Hierarchy.Logger)
                log.Logger).Appenders.SyncRoot)[0]).File