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 theLogManager.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
How to Redirect to Index from Another Controller
How to Make Form1 Label.Text Change When Checkbox on Form2 Is Checked
Removing the Delay After Keydown Event
How to Find Certificate by Its Thumbprint in C#
Newtonsoft Inline Formatting for Subelement While Serializing
The Difference Between Virtual, Override, New and Sealed Override
Overriding Fields or Properties in Subclasses
Is Idisposable.Dispose() Called Automatically
Copying Free Hand Drawing from Panel in Visual Studio 2013
Open a Folder Using Process.Start
Can Connect to Ftp Using Filezilla or Winscp, But Not with Ftpwebrequest or Fluentftp
Make a Specific Column Only Accept Numeric Value in Datagridview in Keypress Event
Run a Background Task from a Controller Action in ASP.NET Core
Binding Combobox Selecteditem Using Mvvm