Log4Net Logging of Two Different Levels to Two Different Appenders for the Same Logger

Log4Net Logging of two different levels to two different appenders for the same logger

You should be able to set the threshold property of each appender separately and include them in the same root.

<appender name="filelogAppender" type="log4net.Appender.RollingFileAppender">
<threshold value="Error" />
</appender>
<appender name="dblogAppender" type="log4net.Appender.AdoNetAppender">
<threshold value="Info" />
</appender>
<root>
<appender-ref ref="filelogAppender" />
<appender-ref ref="dblogAppender" />
</root>

reference

How to define different logger levels per appenders

You're problem is, that the definition you make in Logger outweights all following levels. So here comes my solution:

<log4net>
<appender name="DebugAppender" type="log4net.Appender.RollingFileAppender">
<file value="plastic.debug.log.txt" />
<!--...-->
</appender>

<appender name="Security_RelevantAppender" type="log4net.Appender.RollingFileAppender">
<threshold value="ERROR" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<file value="plastic.relevant.log.txt" />
<!--...-->
</appender>

<appender name="Serverstat_RelevantAppender" type="log4net.Appender.RollingFileAppender">
<threshold value="INFO" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<!--...-->
</appender>

<logger name="Security">
<appender-ref ref="Security_RelevantAppender" />
</logger>

<logger name="ServerStats">
<appender-ref ref="Serverstat_RelevantAppender" />
</logger>

<root>
<level value="DEBUG" />
<appender-ref ref="DebugAppender" />
</root>
</log4net>

Define 3 different appenders. The DebugAppender's level is defined by <root>. The two relevant appenders write both to the same file with different log-levels (thresholds). It is important, that you include the locking model <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />. Utherwise the first appender you call will lock the file and the second one can not write in it (Can Log4net have multiple appenders write to the same file?). In the <logger> you just define the two different appenders and no loglevel. This way it will take the level from the appender settings.

When you do it like this all events of the type debug+ from any logger will be written to plastic.debug.log.txt. To plastic.relevant.log.txt only events error+ from security-logger and info+ from serverstat-logger are written.

Hope this helps

log4net logging to multiple defined appenders using class name loggers

If you want to have multiple loggers with the same name but using different appenders, then you must set up multiple repositories to contain them.

As it says in the (somewhat scanty) documentation on repositories:

Named logging repositories can be created using the LogManager.CreateRepository method. The repository for can be retrieved using the LogManager.GetRepository method. A repository created in this way will need to be configured programmatically.

However, this does not mean the actual config must be in code, but that you should do something like this:

// or wherever
string configPath = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;

var repository = log4net.LogManager.CreateRepository("file1repo");
log4net.XmlConfigurator.ConfigureAndWatch(repository, new FileInfo(configPath));

repository = log4net.LogManager.CreateRepository("file2repo");
log4net.XmlConfigurator.ConfigureAndWatch(repository, new FileInfo(configPath));

Then you would write code to amend the 'file2' appender to write to file2:

var appender = LogManager.GetRepository("file2repo").GetAppenders()
.OfType<RollingFileAppender>().Single();

appender.File = "file2.log";
appender.ActivateOptions();

Your code then looks like this:

public static ILog GetLogger(Type classType, bool shouldLogToFile2)
{
return LogManager.GetLogger(shouldLogToFile2 ? "file2repo" : "file1repo", classType);
}

Log4net - multiple appenders

I suspect your are on the right track, looks like both appenders needs to be specified in the same root see example and link below:

<root>
<level value="ERROR" />
<level value="WARN" />
<appender-ref ref="AdoNetAppender" />
<level value="DEBUG" />
<appender-ref ref="RollingFileAppender" />
</root>

File and Database multiple configuration for log4net

log4net - One logger, multiple appenders

RESOLVED

The config above is indeed correct. Good to note for future use :)

It turns out that the reason for the failing logging was the appender I was using (the log4net.SignalR appender by Chris Fulstow and/or Matthew Steeples, there are two the same, even in Nuget!) - it had a number of tweaks required before it would work correctly and very little documentation.

If anyone needs help with this I'd be glad to assist.

Log4net and multiple loggers to different files

In this answer I told the OP that log4net was usually greedy regarding its log files' creation:

the file is created as soon as the appender is initialized in the ActivateOptions() method. From what I see you need a custom FileAppender that will handle all your business rules. It would need to

- override the default ActivateOptions method to prevent file creation
- override the Append method to create a new timestamped file when a message is logged
- use data passed in the LoggingEvent class (you have some properties available on the class) to retrieve the filename; you have to determine the filename before logging.

Unless you want to benefit from behavior it already implements(impersonation for example), I'd recommend skipping inheritance from the FileAppender class and inherit directly from the TextWriterAppender class.

So I think that - unless you want to customize the behavior of the appenders - the fallback proposed by peer may be the most efficient option since it will avoid the exclusive locks on log files. You will still have logfiles that are created as soon as the configuration is parsed.

Log4net - modify logging levels for individual logger and appender combinations

The configuration mechanism of log4net is quite lenient but doesn't tell you when some parameters are not taken into account. For example in your configuration the following references the appender InfoAppender but the threshold property doesn't do anything

 <appender-ref ref="InfoAppender">
<threshold value="WARN" />
</appender-ref>

No parsing of xml element below the appender-ref node occur, you could put anything it won't be taken into account:

protected void ParseChildrenOfLoggerElement(XmlElement catElement, Logger log, bool isRoot)
// some code ommited
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.");
}
}

What you need to do is add a filter between your logger and your final appender. To do this I recommend using the ForwardingAppender which lets you pass log events between appenders while adding some behavior: change the NHibernate section of your config file to this:

<appender name="NHibernateDebugFilterAppender" type="log4net.Appender.ForwardingAppender">
<appender-ref ref="DebugAppender"/>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="INFO" />
</filter>
</appender>

<appender name="NHibernateInfoFilterAppender" type="log4net.Appender.ForwardingAppender">
<appender-ref ref="InfoAppender"/>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="WARN" />
</filter>
</appender>

<logger name="NHibernate" additivity="false">
<appender-ref ref="NHibernateInfoFilterAppender" />
<appender-ref ref="NHibernateDebugFilterAppender"/>
</logger>

How to log different log level to different log appender in log4net

You should be able to add a filter to both of your appenders.

<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="INFO" />
<levelMax value="FATAL" />
</filter>

This way one appender will only log to a certain level while the other to a different level even though they are defined by the same logger.



Related Topics



Leave a reply



Submit