17
votes

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.
2
for solution i need to read till the end of your Question. lower case issue.Abin

2 Answers

21
votes

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.

0
votes

This configuration worked for me:

<log4net>
    <root name="EventLog">
        <level value="ALL"/>
        <appender-ref ref="EventLogAppender"/>
    </root>

    <logger name="FileLogger" additivity="false">
        <level value="ALL" />
        <appender-ref ref="RollingFileAppender" />
    
        ...appenders
    </logger>

Good Luck!