1
votes

My app logs to console and file (log4net 1.2.11):

<root>
  <level value="DEBUG" />
  <appender-ref ref="ConsoleAppender" />
  <appender-ref ref="RollingLogFileAppender" />
</root>

I'd like to change configuration for one class so that it logs all messages to file, and all but Debug messages to console. Can I do that without adding dedicated appender for my class, and without changing root configuration, e.g. on logger's appender-ref level?

Inspired by this answer, I've tried the code below but without success (all messages, including Debug, are logged to both appenders):

<logger name="MyClass" additivity="false">
  <appender-ref ref="ConsoleAppender">
    <threshold value="INFO" />
  </appender-ref>
  <appender-ref ref="RollingLogFileAppender" />
</logger>

This also fails (it excludes Debug from all appenders, and I want Debug messages in file):

<logger name="MyClass">
  <level value="INFO" />
</logger>
1

1 Answers

1
votes

You are out of luck, when log4net parses the appender-ref tag it doesn't pass any information to the appender that is referenced by name (code from 1.2.10):

// log4net.Repository.Hierarchy.XmlHierarchyConfigurator
if (xmlElement.LocalName == "appender-ref")
{
    IAppender appender = this.FindAppenderByReference(xmlElement);
    string attribute = xmlElement.GetAttribute("ref");
    if (appender != null)
    {
        LogLog.Debug(string.Concat(new string[]
        {
            "XmlHierarchyConfigurator: Adding appender named [",
            attribute,
            "] to logger [",
            log.Name,
            "]."
        }));
        log.AddAppender(appender);
    }
    else
    {
        LogLog.Error("XmlHierarchyConfigurator: Appender named [" + attribute + "] not found.");
    }
}

I'm pretty sure that the answer you are linking to doesn't really work; the Treshold property exists on the appender, but it is not parsed in a ref node.

Which is for the best really - can you imagine the configuration nightmares if a logger could change some appender property from its reference? Last logger being parsed would win the configuration and good luck tracking why your debug appender is now keeping silent when it's because some other logger swapped the treshold value :)

So you have to add another appender; if you don't want to copy-paste the RollingLogFileAppender configuration, you can use a forwarding appender which can be used as a filter before passing messages on to its own referenced appender. You would end up with

  • Root log -> ConsoleAppender
  • Root log -> RollingFileAppender
  • MyClass -> ForwardingAppender with filter -> ConsoleAppender
  • MyClass -> RollingFileAppender