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.
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.