3

Basically, I need to generate multiple log files. In my example, i have 2 loggers {logger-A, logger-B}. I find it tedious to create another fileappender for each logger. How can I re-use 1 appender for multiple loggers?

In Config

<log4net>

    <root>
      <level value="ALL" />
      <appender-ref ref="LogFileAppender" />
    </root>

    <logger additivity="false" name="logger-A">
      <level value="All"/>
      <appender-ref ref="FileAppender" />
    </logger>

    <logger additivity="false" name="logger-B">
      <level value="All"/>
      <appender-ref ref="FileAppender" />
    </logger>

    <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender" >
      <param name="File" type="log4net.Util.PatternString" value="log\all.txt" />
      <param name="AppendToFile" value="true" />

      <rollingStyle value="Size" />
      <maxSizeRollBackups value="10" />
      <maximumFileSize value="2MB" />
      <staticLogFileName value="true" />

      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%-5p%d{yyyy-MM-dd hh:mm:ss} – %m%n" />
      </layout>

      <filter type="log4net.Filter.PropertyFilter">
        <Key value="Version" />
        <StringToMatch value="1" />
      </filter>
    </appender>

    <appender name="FileAppender" type="log4net.Appender.RollingFileAppender" >
      <param name="File" type="log4net.Util.PatternString" value="log\%property{LogName}.txt" />
      <param name="AppendToFile" value="true" />

      <rollingStyle value="Size" />
      <maxSizeRollBackups value="10" />
      <maximumFileSize value="2MB" />
      <staticLogFileName value="true" />

      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%-5p%d{yyyy-MM-dd hh:mm:ss} – %m%n" />
      </layout>
    </appender>

  </log4net>

in C#

GlobalContext.Properties["LogName"] = string.Format("{0}", loggerName);
var logger = LogManager.GetLogger(loggerName);
h3n
  • 5,142
  • 9
  • 46
  • 76
  • link might be helpful, https://stackoverflow.com/questions/23015507/log4net-multiple-loggers – Praveen Kumar Apr 25 '18 at 08:22
  • You didn't really mention what exactly the problem is. Based on your posted code I would assume you're getting a `(null).txt` output log file. If that's the case, then you'll need to call `XmlConfigurator.Configure();` **after** you set your `LogName` in the `GlobalContext`. And then, call it again every time you want to switch log files using the same appender. Ugly... I would much rather have multiple appenders. – jsanalytics Apr 25 '18 at 09:51
  • The LogName property would be dynamic. For example, I add new logger-C from the config, I would just use the existing FileAppender and it should create a new log file. – h3n Apr 30 '18 at 07:02
  • We get it that `LogName` is dynamic, but you're still not telling us what exactly happens when you run your code. – jsanalytics Apr 30 '18 at 20:27
  • Each Logger should have separate log file. If I have 3 loggers, Id like to have 3 log files. – h3n May 01 '18 at 09:18
  • When you run your code, how many log files you get? What is the log file name? What is the content? – jsanalytics May 01 '18 at 11:15

2 Answers2

3

You can use good old composition to do this and add more properties if you want to the configuration. As shown below.

public class FileAppenderX2 : AppenderSkeleton
{
    private FileAppender _output1;
    private FileAppender _output2;

    public string Output1 { get; set; }

    public string Output2 { get; set; }

    public override void ActivateOptions()
    {
        base.ActivateOptions();
        _output1 = new FileAppender() { Layout = this.Layout, File = Output1 };
        _output2 = new FileAppender() { Layout = this.Layout, File = Output2 };
        _output1.ActivateOptions();
        _output2.ActivateOptions();
    }

    public FileAppenderX2()
    {
    }

    protected override void Append(LoggingEvent loggingEvent)
    {
        _output1.DoAppend(loggingEvent);
        _output2.DoAppend(loggingEvent);
    }
}

Configuration file edits here...

  <appender name="FileX2Appender" type="{Fully Qualified Namespace}.FileAppenderX2, {Assembly Name}">
    <Output1 value="C:\output1.log"/>
    <Output2 value="C:\output2.log"/>
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="[%date]-[%thread]-[%level]-[%logger] - %message%newline" />
    </layout>
  </appender>
fanuc_bob
  • 857
  • 1
  • 7
  • 20
  • I'd like the log file to be dynamic. So when I add new Logger, It will use the logger name as the LogName of the FileAppender – h3n Apr 30 '18 at 07:06
  • Odd request for a referenced logger name as you are asking for a file appender with two different output files. Maybe I don't understand fully. Good luck! – fanuc_bob Apr 30 '18 at 15:06
0

I'm not fully understood your requirement, any how as per my understanding I'm trying to answer you.

So you have Multiple logger specified in your config like

    <logger additivity="false" name="logger-A">
      <level value="All"/>
      <appender-ref ref="FileAppender" />
    </logger>

    <logger additivity="false" name="logger-B">
      <level value="All"/>
      <appender-ref ref="FileAppender" />
    </logger>

then you have a appender with param as below

<param name="File" type="log4net.Util.PatternString" value="log\%property{LogName}.txt" />

which is seeking a string to replace {LogName}.

And you were able to get the logger name using your c# code below,

GlobalContext.Properties["LogName"] = string.Format("{0}", loggerName);
var logger = LogManager.GetLogger(loggerName);

If my above understanding is correct then you can refer link. I don't how far this is practical, but at least it would provide you a information I believe.

andrew subash
  • 51
  • 1
  • 8