0
votes

I have been trying to understand the config of the log4net library and I think I have it except for some unexpected behavior.

I have a root logger that has a level set to INFO and another logger for a specific class that has level set to ERROR.

What I expected from this was that the class logger would only log at error and ignore the roots level since I had additivity set to false for the class logger. Here is the log4net.config I have at the moment:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <log4net>

    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
      </layout>
    </appender>

    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="log.txt" />
      <appendToFile value="true" />
      <rollingStyle value="Size" />
      <maxSizeRollBackups value="10" />
      <maximumFileSize value="100KB" />
      <staticLogFileName value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
      </layout>
    </appender>

    <logger name="EveStatic.Config.ViewModel" additivity="false">
      <level value="error"/>
      <appender-ref ref="ConsoleAppender"/>
      <appender-ref ref="RollingFileAppender"/>
    </logger>

    <root>
      <level value="debug" />
      <appender-ref ref="ConsoleAppender" />
      <appender-ref ref="RollingFileAppender" />
    </root>

  </log4net>
</configuration>

In my AssemblyInfo.cs:

[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]

And in the class that loads the configuration:

log4net.Config.XmlConfigurator.Configure(new FileInfo("log4net.config"));

These two seem redundant but the configuration wont load unless I have the code part. Everything here is in a class library being used by another project.

Is this behavior expected and I don't understand the configuration and level overrides or am I forgetting something?

EDIT: Here is how I instantiate and call the ILog. The the full class name is the name of the logger in the config plus the ConfiInfoViewModel:

private static readonly ILog LOG = LogManager.GetLogger(typeof(ConfigInfoViewModel));
...
LOG.Debug("Something buggy");

Also note that when testing the logging levels I had a log statement for each level in a series.

1
Can u please provide some additional code. Where you call GetLogger and where your logging exactly happens.nosale
@nosale view the EDIT portionDallas Phillips

1 Answers

4
votes

Your problem lays here

LogManager.GetLogger(typeof(ConfigInfoViewModel));

Internally this get resolved to

LogManager.GetLogger(typeof(ConfigInfoViewModel).FullName);

Now log4net is looking for a Logger named "EveStatic.Config.ConfigInfoViewModel" (result of typeof(ConfigInfoViewModel).FullName)

Because no Logger with that name is specified a new one with your default settings is used.

Also note that level specify a threshold, not a single level.
Example: level=warn means log warn an all levels above (error and fatal)