How to define different logger levels per appenders - log4net

I'm trying to define 2 independent appenders to log into to 2 files. I define
DEBUG level for the "DebugAppender" and then for the "RelevantAppender" I define different levels for the "Security" and "ServerStats" loggers.
The thing is that these loggers definitions are overwriting my "DebugAppender" levels and now it's not in DEBUG mode (all the loggers).
How can make it work as expected?
<log4net>
<appender name="DebugAppender" type="log4net.Appender.RollingFileAppender">
<file value="plastic.debug.log.txt" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value=".yyyyMMdd" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %thread %property{TransactionID} %property{ClientMachine} %-5level %logger - %message%newline" />
</layout>
</appender>
<appender name="RelevantAppender" type="log4net.Appender.RollingFileAppender">
<file value="plastic.relevant.log.txt" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value=".yyyyMMdd" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %property{ClientMachine} %-5level %logger - %message%newline" />
</layout>`enter code here`
</appender>
<logger name="Security">
<level value="ERROR" />
<appender-ref ref="RelevantAppender" />
</logger>
<logger name="ServerStats">
<level value="INFO" />
<appender-ref ref="RelevantAppender" />
</logger>
<root>
<level value="DEBUG" />
<appender-ref ref="DebugAppender" />
</root>

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

Related

ASP.NET Boilerplate adding an additional log file with Log4Net and Castle Logging

I've been trying to find documentation and guidance on how to use a separate log file in ASP.NET Boilerplate MVC.
It's straight forward to inject ILogger and push messages into the default Log.txt file, however I need a separate log file to record a lot of batch job messages and keep things tidy.
I can't find any methods to use another log from the Log4Net.config file. Can anyone advise on the correct code / configuration?
So I found the answer by chance in looking at the Hangfire documentation, where it was shown you can configure Hangfire messages to be sent to another log file by getting Log4Net to listen for the Hangfire name and route based on that.
With the following additional configuration in Log4Net.config I now have Log messages created normally within MyClass sent to the MyClass.txt log file:
<appender name="RollingFileAppender_MyClass" type="log4net.Appender.RollingFileAppender" >
<file value="App_Data/Logs/MyClass.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="32" />
<maximumFileSize value="10000KB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level %date [%-5.5thread] %-40.40logger - %message%newline" />
</layout>
</appender>
<logger additivity="false" name="MyNamespace.MyClass">
<level value="DEBUG" />
<appender-ref ref="RollingFileAppender_MyClass" />
</logger>
And for completeness, it's called in the standard way documented within the AspNet Boilerplate documentation:
https://aspnetboilerplate.com/Pages/Documents/Logging
Way-1:
In this sample, the default log file is App_Data/Logs/Logs.txt.
But when I use the logger in the namespace MySite.Web.Controllers.PaymentController, the logs will be written in App_Data/Logs/PaymentLogs.txt
log4net.config
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender" >
<file value="App_Data/Logs/Logs.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10000KB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level %date [%-5.5thread] %-40.40logger - %message%newline" />
</layout>
</appender>
<appender name="RollingFileAppender_PaymentController" type="log4net.Appender.RollingFileAppender" >
<file value="App_Data/Logs/PaymentLogs.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="32" />
<maximumFileSize value="10000KB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level %date [%-5.5thread] %-40.40logger - %message%newline" />
</layout>
</appender>
<root>
<appender-ref ref="RollingFileAppender" />
<level value="DEBUG" />
</root>
<logger name="NHibernate">
<level value="WARN" />
</logger>
<logger name="MySite.Web.Controllers.PaymentController" additivity="false">
<appender-ref ref="RollingFileAppender_PaymentController" />
<level value="DEBUG" />
</logger>
</log4net>
Way-2:
You can get a specific logger by calling LogManager.GetLogger() with a appender name.
private static readonly ILog paymentLogger = LogManager.GetLogger("MySite.Web.Controllers.PaymentController");

What's wrong with my log4net config file

I have a config file with two appenders, one file appender and one database appender. I want to log everything to the file appender, and only log exceptions to the database appender. When setting up both appenders in the section it logs fine but all log events are sent to both appenders, which is not what i want.
I changed the configuration but with this current configuration, exceptions get logged to the database, and nothing is getting written to the file appender. Can anyone tell me why I am not getting anything written to the file appender?
<log4net debug="true">
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="C:\Log4net\Workflow\TestLog.txt" />
<threshold value="All" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10KB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5p {%logger} %d %5rms %-22.22c{1} %-18.18M - %m%n" />
</layout>
</appender>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<!-- Removed to keep this snippet simple-->
</appender>
<root>
<level value="Error" />
<appender-ref ref="AdoNetAppender" />
</root>
<logger name="AllLogs">
<level value="ALL" />
<appender-ref ref="RollingLogFileAppender" />
</logger>
</log4net>
What you have here is the following:
all logs events with the level Error or more will go to the AdoNetAppender
all logs events originating from a logger whose name is based on AllLogs will go to the RollingLogFileAppender
From what I understand you want all logs to default to the file, and only error ones to go also to the database. Then simply add both appenders to your root logger so that both get all events, and add filters to only let filters you're interested in pass through: a level range filter on your database appender would work
<log4net debug="true">
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<!-- rest of config snipped to save space -->
</appender>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="ERROR" />
<levelMax value="FATAL" />
</filter>
<!-- rest of config snipped to save space -->
</appender>
<root>
<appender-ref ref="AdoNetAppender" />
<appender-ref ref="RollingLogFileAppender" />
</root>
</log4net>
Of course if you don't want any duplicate just filter errors and above in the rolling file appender

log4Net - Loggers between classes - Releasing a File

I am new to log4net. Here is my app.config. What is happening is at a point after going through a switch statement, my logger "X" stops writing to my log file. I tried x.Logger.Repository.Shutdown();, and all that does is stop my "Y" from even logging. My suspicion is that the file is in use, and can't be written to (the next logging statement does begin in a different class. Again, I'm new. Basically, it writes about 10 lines, goes to another class with a logger of the same name, works in that class for a few more lines, and then when it goes back to the original class, it stops logging. I'm a little lost. P.S. I have the correct section name, and I am calling my log as such:
private static readonly ILog eventLog = LogManager.GetLogger("EventLog");
<appender type="log4net.Appender.FileAppender" name="event">
<file value="C:X.log" />
<layout type="log4net.Layout.PatternLayout">
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<conversionpattern value="%d [%t] %-5p %c - %m%n" />
</layout>
</appender>
<appender type="log4net.Appender.FileAppender" name="cLog">
<file value="Y.log" />
<layout type="log4net.Layout.PatternLayout">
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<conversionpattern value="%d [%t] %-5p %c - %m%n" />
</layout>
</appender>
<logger name="EventLog">
<level value="INFO" />
<maximumfilesize value="256KB" />
<param value="INFO" name="Threshold" />
<appender-ref ref="event" />
</logger>
<logger name="crLog">
<level value="INFO" />
<maximumfilesize value="256KB" />
<param value="INFO" name="Threshold" />
<appender-ref ref="cLog" />
</logger>
As it turns out, when you call x.Logger.Repository.Shutdown(); it kills any logs that you might want to write to at that point in time.
I will either move x.Logger.Repository.Shutdown(), or find a different method for releasing my files so the last portion of my app can use (email) the file.

Different levels of logging with log4net

I must log some methods. In one method I must log everything. In all others method I've just log exception...
I have done this configuration:
<log4net>
<appender name="OneMethodFileAppender" type="log4net.Appender.RollingFileAppender">
...
<filter type="log4net.Filter.PropertyFilter">
<key value="realMethod" />
<stringToMatch value="xxx" />
<acceptOnMatch value="true" />
</filter>
</appender>
<appender name="WebsiteFileAppender" type="log4net.Appender.RollingFileAppender">
...
<filter type="log4net.Filter.PropertyFilter">
<key value="realMethod" />
<stringToMatch value="xxx" />
<acceptOnMatch value="false" />
</filter>
</appender>
<root>
<appender-ref ref="WebsiteFileAppender">
<threshold value="ERROR" />
</appender-ref>
<appender-ref ref="OneMethodFileAppender">
<threshold value="INFO" />
</appender-ref>
</root>
</log4net>
So, when I match the property realMethod I should use the appender OneMethodFileAppender that log at the INFO level; in all other cases i should use the appender WebsiteFileAppender that log at ERROR level.
I have a different output.
1. When i match the method xxx everything works correctly. I mean that a log at INFO level in the correct log.
2. But when I do not match the method xxx, I log in both files and both at INFO level.
I would suggest to use the logger element to configure your logging:
<log4net>
<appender name="OneMethodFileAppender" type="log4net.Appender.RollingFileAppender">
...
</appender>
<appender name="WebsiteFileAppender" type="log4net.Appender.RollingFileAppender">
...
</appender>
<root>
<appender-ref ref="WebsiteFileAppender">
<threshold value="ERROR" />
</appender-ref>
</root>
<logger name="LoggerName1">
<level value="INFO" />
<appender-ref ref="WebsiteFileAppender" />
</logger>
<logger name="LoggerName2">
<level value="INFO" />
<appender-ref ref="OneMethodFileAppender" />
</logger>
</log4net>
Both methods should have there own logger:
logger = LogManager.GetLogger("logger1");

Is there a way to have log4net create log file only when there is logging activity?

We changed our log4net file name to include the current date but only want log files created on those dates that there is logged activity. This is our current configuration:
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="{0}\\logfiles\\log%date{{yyyyMMdd}}-${{COMPUTERNAME}}.log" />
<appendToFile value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level %logger %message%newline" />
</layout>
</appender>
<root>
<level value="WARN" />
<appender-ref ref="RollingFileAppender" />
</root>
</log4net>
It's producing empty files on days when the logger is created but no messages of WARN or greater are written. Is there a configuration to prevent empty files?

Resources