logginglog4net-configurationrollingfileappender

Log4Net Multiple loggers


First of all, I have seen a lot of answers and tips in others topics (most similar: Log4Net: Multiple loggers), but there is no applicable answer.

I want to have 2 loggers with different file appenders and restrict each to write into root logger. It is Console app. Whole code below:

using System;
using System.Diagnostics;
using System.Linq;
using log4net;

namespace Test_log4net
{
class Program
{
    static void Main(string[] args)
    {
        log4net.Config.XmlConfigurator.Configure();
            ILog logger = LogManager.GetLogger("Async");
        logger.Info("started async");
        Console.WriteLine("Logger: {0}", (logger as log4net.Core.LogImpl).Logger.Name);
        Console.WriteLine("Appenders: {0}", string.Join(", ", (logger as log4net.Core.LogImpl).Logger.Repository.GetAppenders().ToList().Select(appendr => appendr.Name)));

        ILog logger2 = LogManager.GetLogger("Sync");
        logger2.Info("started sync"); //changed: from logger -> to logger2 on 10/21/2014
        Console.WriteLine("Logger: {0}", (logger2 as log4net.Core.LogImpl).Logger.Name);
        Console.WriteLine("Appenders: {0}", string.Join(", ", (logger2 as log4net.Core.LogImpl).Logger.Repository.GetAppenders().ToList().Select(appendr => appendr.Name)));

        Console.ReadKey();
    }       
}
}

And App.config file:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
   <configSections>
      <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
   </configSections>
   <startup>
      <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
   </startup>
   <log4net>
      <root>
         <level value="All"/>
      </root>

      <appender name="FileInfoAppenderA" type="log4net.Appender.RollingFileAppender">
         <file value="D:\\temp\\AsyncTest.log"/>
         <filter type="log4net.Filter.LevelRangeFilter">
            <levelMin value="DEBUG"/>
            <levelMax value="FATAL"/>
         </filter>
         <appendToFile value="true"/>
         <rollingStyle value="Size"/>
         <maxSizeRollBackups value="10"/>
         <maximumFileSize value="100MB"/>
         <staticLogFileName value="true"/>
         <datePattern value="yyyyMMdd"/>
         <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%d - %m%n"/>
         </layout>
      </appender>

      <appender name="FileInfoAppenderS" type="log4net.Appender.RollingFileAppender">
         <file value="D:\\temp\\SyncTest.log"/>
         <filter type="log4net.Filter.LevelRangeFilter">
            <levelMin value="DEBUG"/>
            <levelMax value="FATAL"/>
         </filter>
         <appendToFile value="true"/>
         <rollingStyle value="Size"/>
         <maxSizeRollBackups value="10"/>
         <maximumFileSize value="100MB"/>
         <staticLogFileName value="true"/>
         <datePattern value="yyyyMMdd"/>
         <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%d - %m%n"/>
         </layout>
      </appender>

      <logger Name="Sync" additivity="false">
         <level value="INFO"/>
         <appender-ref ref="FileInfoAppenderS"/>
      </logger>

      <logger Name="Async" additivity="false">
         <level value="INFO"/>
         <appender-ref ref="FileInfoAppenderA"/>
      </logger>
        
   </log4net>
</configuration>

And console output:

    Logger: Async
    Appenders: FileInfoAppenderA
    Logger: Sync
    Appenders: FileInfoAppenderA

Files have been created, but both of them are empty. When I specify appenders in root, like:

<root>
    <level value="All"/>
    <appender-ref ref="FileInfoAppenderA"/>
    <appender-ref ref="FileInfoAppenderS"/>
</root>

then, console:

log4net:ERROR [RollingFileAppender] Attempted to append to closed appender named [FileInfoAppenderS]
Logger: Async
Appenders: FileInfoAppenderA, FileInfoAppenderS
Logger: Sync
Appenders: FileInfoAppenderA, FileInfoAppenderS

And only in AsyncTest.log:

2014-04-11 17:26:58,142 - started async
2014-04-11 17:26:58,151 - started sync

What I am doing wrong?

UPD (10/21/2014): With latest log4net available via Nuget I have following console output:

Logger: Async
Appenders: FileInfoAppenderA
Logger: Sync
Appenders: FileInfoAppenderA

And both of files (AsyncTest.log, SyncTest.log) are empty.

UPD (08/4/2015): Solution is to use lower case when setting the attributes for everything in log4net section. So, I just should have changed following lines in app.config:

......
<logger name="Sync" additivity="false">
......
<logger name="Async" additivity="false">
......

Note the difference: attribute 'name' is in lower case.


Solution

  • You have several typos on your example. First is you don't close the configuration tag, and why you're getting only in one file, is because you call:

    logger.Info("started async");
    

    and after that you surprisingly do:

    logger.Info("started sync");
    

    You will not get writing in the second file because you actually don't log to it.

    And in console I get from your code:

    Logger: Async
    Appenders: FileInfoAppenderS, FileInfoAppenderA
    Logger: Sync
    Appenders: FileInfoAppenderS, FileInfoAppenderA
    

    For future information, you did correctly by putting additivity to false, because this means that the loggers will not inherit from root logger. As about the statement:

    I want to have 2 loggers with different file appenders and restrict each to write into root logger

    I do not understand it. If you want that your loggers write to these files while root logger having a console appender for example, just remove additivity and they will write to console and their own files. Also tested and it works very well.

    I have read your comment. Now I add the code that I'm using and getting what you need:

    class Program
    {
        static void Main(string[] args)
        {
            log4net.Config.XmlConfigurator.Configure();
    
            ILog logger = LogManager.GetLogger("Async");
            logger.Info("started async");
            Console.WriteLine("Logger: {0}", (logger as log4net.Core.LogImpl).Logger.Name);
            Console.WriteLine("Appenders: {0}", string.Join(", ", (logger as log4net.Core.LogImpl).Logger.Repository.GetAppenders().ToList().Select(appendr => appendr.Name)));
    
    
            ILog logger2 = LogManager.GetLogger("Sync");
            logger2.Info("started sync");
            Console.WriteLine("Logger: {0}", (logger2 as log4net.Core.LogImpl).Logger.Name);
            Console.WriteLine("Appenders: {0}", string.Join(", ", (logger2 as log4net.Core.LogImpl).Logger.Repository.GetAppenders().ToList().Select(appendr => appendr.Name)));
    
            Console.ReadKey();
        }
    }
    

    And the app.config:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <configSections>
            <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
        </configSections>
        <startup>
            <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
        </startup>
        <log4net>
            <appender name="FileInfoAppenderA" type="log4net.Appender.RollingFileAppender">
              <file value="C:\\temp\\AsyncTest.log"/>
              <filter type="log4net.Filter.LevelRangeFilter">
                <levelMin value="DEBUG"/>
                <levelMax value="FATAL"/>
              </filter>
              <appendToFile value="true"/>
              <rollingStyle value="Size"/>
              <maxSizeRollBackups value="10"/>
              <maximumFileSize value="100MB"/>
              <staticLogFileName value="true"/>
              <datePattern value="yyyyMMdd"/>
              <layout type="log4net.Layout.PatternLayout">
                <conversionPattern value="%d - %m%n"/>
              </layout>
            </appender>
        
            <appender name="FileInfoAppenderS" type="log4net.Appender.RollingFileAppender">
                <file value="C:\\temp\\SyncTest.log"/>
                <filter type="log4net.Filter.LevelRangeFilter">
                    <levelMin value="DEBUG"/>
                    <levelMax value="FATAL"/>
                </filter>
                <appendToFile value="true"/>
                <rollingStyle value="Size"/>
                <maxSizeRollBackups value="10"/>
                <maximumFileSize value="100MB"/>
                <staticLogFileName value="true"/>
                <datePattern value="yyyyMMdd"/>
                <layout type="log4net.Layout.PatternLayout">
                    <conversionPattern value="%d - %m%n"/>
                </layout>
            </appender>
        
            <root>
                <level value="INFO"/>
            </root>
            
            <logger name="Sync" additivity="false">
                <level value="INFO"/>
                <appender-ref ref="FileInfoAppenderS"/>
            </logger>
        
            <logger name="Async" additivity="false">
                <level value="INFO"/>
                <appender-ref ref="FileInfoAppenderA"/>
            </logger>
        </log4net>
    </configuration>
    

    Log4net version: 1.2.13.0 with .NET 4.0 Tell me please if you get what you want.