Configuring Log4Net for specific classes and overreaching error handling - log4net

I am using Log4Net within my project, and would like to configure it so that debug/info messages go to files specific to each class, and all error messages go to a central file.
Within my application, I have several "workers". I would like each worker to have its own log file to capture debug messages. If I get a debug message that isn't captured on a specific worker, I would like it to be logged to a central debug file. I would also like to have central error logging, where all errors from any of the workers are logged in the same file.
I am having difficulty figuring out the XML configuration to do this.
Here is the closest I have come:
<log4net>
<appender name="DebugLog" type="log4net.Appender.RollingFileAppender">
<file value="logs\debug.log" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value="ddMMyyyy" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="DEBUG" />
<levelMax value="FATAL" />
</filter>
</appender>
<appender name="ErrorLog" type="log4net.Appender.RollingFileAppender">
<file value="logs\error.log" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value="ddMMyyyy" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline%stacktrace{1}%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="ERROR" />
<levelMax value="FATAL" />
</filter>
</appender>
<appender name="Worker1" type="log4net.Appender.RollingFileAppender">
<file value="logs\Worker1.log" />
<appendToFile value="true" />
<rollingStyle value="Composite" />
<datePattern value="ddMMyyyy" />
<maxSizeRollBackups value="100" />
<maximumFileSize value="100MB" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="DEBUG" />
<levelMax value="INFO" />
</filter>
</appender>
<appender name="Worker2" type="log4net.Appender.RollingFileAppender">
<file value="logs\Worker2.log" />
<appendToFile value="true" />
<rollingStyle value="Composite" />
<datePattern value="ddMMyyyy" />
<maxSizeRollBackups value="100" />
<maximumFileSize value="100MB" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="DEBUG" />
<levelMax value="INFO" />
</filter>
</appender>
<appender name="Worker3" type="log4net.Appender.RollingFileAppender">
<file value="logs\3.log" />
<appendToFile value="true" />
<rollingStyle value="Composite" />
<datePattern value="ddMMyyyy" />
<maxSizeRollBackups value="100" />
<maximumFileSize value="100MB" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="DEBUG" />
<levelMax value="INFO" />
</filter>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="DebugLog" />
<appender-ref ref="ErrorLog" />
</root>
<logger name="Worker1">
<level value='DEBUG'/>
<appender-ref ref="Worker1" />
</logger>
<logger name="Worker2">
<level value='DEBUG'/>
<appender-ref ref="Worker2" />
</logger>
<logger name="Worker3">
<level value='DEBUG'/>
<appender-ref ref="Worker3" />
</logger>
</log4net>
The first issue I have is that all messages written to Worker1's class, are written to the Debug.log file, and the Worker1.log file. I don't want them written to Debug.log if they are already written to Worker1.log.
I can get around this by changing the section, by adding additivity = false. In this case, it writes to the Worker1.log, and not the Debug.log file.
However, doing this prevents errors from being written to Error.log
What happens is that if I set additivity = "false" and log an error, it gets written to Worker1.log, but does not get written to Error.log.
Is there any way to have the additivity apply to just the debug/info messages, so that I can have Debug messages in Worker1.log, Error messages in Error.log, and any debug messages that aren't specific to a logger in the debug.log file?

You are right about setting additivity="false" to isolate the debug messages to Worker1.log.
To get the error messages of Worker1 back into Error.log you also have to include the ErrorLog appender in the Worker1 logger declaration, as shown below.
<logger name="Worker1" additivity="false">
<level value='DEBUG'/>
<appender-ref ref="Worker1" />
<appender-ref ref="ErrorLog" />
</logger>
Via this setup you overrule the rules as defined in root to use a custom Worker1 Appender for debug messages and the same Error Appenderfor error messages.

Related

log4net not creating new file with datetime stamp

I wanted my log file to be create for each date and if the log got to be bigger then 100mb then it will create a new file. Below is my setting and it will not create a new file.
<log4net>
<root>
<level value="INFO" />
<appender-ref ref="FileAppender" />
</root>
<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file value="D:\inetpub\wwwroot\COTTProduction\ServiceLogs\COTT.log" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="100MB" />
<datePattern value="_yyyyMMdd.log" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %level %logger - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="INFO" />
<levelMax value="FATAL" />
</filter>
</appender>
</log4net>

Problems with Log4net multiple logger to multiple files

log4net version: 1.2.13.0
Runtime Version: v4.0.30319
I've got some Problems with using multiple Loggers and Appenders.
I have a root Logger with 3 Appenders which work well but when im configuring multiple other loggers log4net seems to only register the appenders from the last logger specified in the app.config.
If i put TaskSyncLogger as last logger entry TaskSyncAppender gets recognized
If i put CalendarSyncLogger as last logger entry CalendarSyncLogger gets recognized
only the 3 appenders from the root logger and the appender from the last logger entry is listed in hierarchy.GetAppenders()
Hierarchy hierarchy = (log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository();
var appenders = hierarchy.GetAppenders();
my app.config
<appender name="MainFileAppender" type="log4net.Appender.FileAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level %logger- %message%newline %exception" />
</layout>
<file value="Logs\logs.log" />
<appendToFile value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
</appender>
<appender name="DebugAppender" type="log4net.Appender.DebugAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level - %message%newline %exception" />
</layout>
</appender>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level - %message%newline %exception" />
</layout>
</appender>
<appender name="TaskSyncAppender" type="log4net.Appender.FileAppender">
<appendToFile value="true"/>
<file value="Logs\logsTask.log" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level %logger- %message%newline %exception" />
</layout>
<!--
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="INFO" />
<levelMax value="FATAL" />
<filter type="log4net.Filter.DenyAllFilter" />
</filter>
-->
</appender>
<appender name="CalendarSyncAppender" type="log4net.Appender.FileAppender">
<appendToFile value="true"/>
<file value="Logs\logsCalendar.log" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level %logger- %message%newline %exception" />
</layout>
<!--
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="INFO" />
<levelMax value="FATAL" />
<filter type="log4net.Filter.DenyAllFilter" />
</filter>
-->
</appender>
<root>
<level value="All" />
<appender-ref ref="MainFileAppender" />
<appender-ref ref="DebugAppender" />
<appender-ref ref="ConsoleAppender" />
</root>
<logger Name="CalendarSyncLogger" additivity="true">
<level value="All"/>
<appender-ref ref="CalendarSyncAppender"/>
</logger>
<logger Name="TaskSyncLogger" additivity="true">
<level value="All"/>
<appender-ref ref="TaskSyncAppender"/>
</logger>
further the TaskSyncAppender isn't writing anything the File gets created but it remains empty although the the MainFile Appender is writing the output.
im getting it like
public const string TaskSyncLogger = "TaskSyncLogger";
private static readonly ILog logTask = LogManager.GetLogger(LoggingStrings.TaskSyncLogger);
I can reproduce this, and while I cannot be confident in saying it is definitely a bug, it is certainly unexpected.
You can work around it by adding this last logger to your file:
<logger Name="WillNotBeUsed">
<level value="Off"/>
<appender-ref ref="CalendarSyncAppender"/>
<appender-ref ref="TaskSyncAppender"/>
</logger>
After that all five appenders are loaded.

Generate identical files from log4net

Similar question to here but slightly different
Like the attached link I am trying to get log4net to output to multiple (x2) files.
As opposed to the link I am looking to have the same information sent to both files. For some reason only the first log file is being generated (Logs.log) and not the second (LogsTest.log)
Can anyone shine some light on this for me please?
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="Logs.log" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<threshold value="INFO" />
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="INFO" />
<levelMax value="OFF" />
</filter>
<maxSizeRollBackups value="30" />
<maximumFileSize value="50MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger %P{url} %P{usr} %P{addr} – %message%newline" />
</layout>
</appender>
<appender name="RollingFileAppender1" type="log4net.Appender.RollingFileAppender">
<file value="LogsTest.log" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<threshold value="INFO" />
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="INFO" />
<levelMax value="OFF" />
</filter>
<maxSizeRollBackups value="30" />
<maximumFileSize value="50MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger %P{url} %P{usr} %P{addr} – %message%newline" />
</layout>
</appender>
<logger name="PlaceGen">
<level value="ALL" />
<appender-ref ref="RollingFileAppender" />
<appender-ref ref="RollingFileAppender1" />
</logger>
</log4net>
Would have been smart to have the local operator to restart the application first

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

I have a WinForm that it display log information but I want it to display to only INFO level but I want the log in the log file to contain DEBUG level as well.
Below is my configuration:
<?xml version="1.0" encoding="utf-8" ?>
<!-- This section contains the log4net configuration settings -->
<log4net>
<!-- Define some output appenders -->
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="${ALLUSERSPROFILE}\\Application Data\\logs\\Gateway" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<param name="StaticLogFileName" value="false" />
<datePattern value=".yyyyMMdd.lo\g" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date | [%thread] | %-5level | %logger | %message %newline" />
</layout>
</appender>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
<appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
<mapping>
<level value="DEBUG" />
<backColor value="Blue" />
</mapping>
<mapping>
<level value="INFO" />
<backColor value="Green" />
</mapping>
<mapping>
<level value="WARN" />
<backColor value="Yellow" />
</mapping>
<mapping>
<level value="ERROR" />
<backColor value="Red" />
</mapping>
<mapping>
<level value="FATAL" />
<backColor value="Red, HighIntensity" />
</mapping>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<appender name="RichTextBoxAppender" type="Gateway.RichTextBoxAppender,Gateway" >
<layout type="log4net.Layout.PatternLayout">
<param name="Header" value="[Header]\r\n"/>
<param name="Footer" value="[Footer]\r\n"/>
<param name="ConversionPattern" value="%d [%t] %-5p %c [%x] - %m%n" />
</layout>
<mapping>
<level value="DEBUG" />
<textColorName value="DarkGreen" />
</mapping>
<mapping>
<level value="INFO" />
<textColorName value="ControlText" />
</mapping>
<mapping>
<level value="WARN" />
<textColorName value="Blue" />
</mapping>
<mapping>
<level value="ERROR" />
<textColorName value="Red" />
<bold value="true" />
<pointSize value="10" />
</mapping>
<mapping>
<level value="FATAL" />
<textColorName value="Black" />
<backColorName value="Red" />
<bold value="true" />
<pointSize value="12" />
<fontFamilyName value="Lucida Console" />
</mapping>
</appender>
<!-- Setup the root category, add the appenders and set the default level -->
<root>
<level value="WARN" />
<appender-ref ref="LogFileAppender" />
<appender-ref ref="ColoredConsoleAppender" />
<appender-ref ref="RichTextBoxAppender" />
</root>
<logger name ="Gateway" additivity="false">
<level value="INFO" />
<appender-ref ref="LogFileAppender" />
<appender-ref ref="ColoredConsoleAppender" />
<appender-ref ref="RichTextBoxAppender" />
</logger>
</log4net>
Right now it is set to INFO for both LogFileAppender and RichTextBoxAppender. I tried taking out the LogFileAppender in Gateway logger and move to another logger and set to "DEBUG" level for this new logger but it is still doing one or the other. How do I configure it so that the LogFileAppender has DEBUG level and RichTextBoxAppender has INFO level?
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.
I agree with #gwhitake that you can use the level range filter. I also want to add, however, that you can use the LevelMatch filter if you just want to select one level. This filter allows you to add another filter at the end of it as well so that you could create a filter that had two or more levels even if they aren't next to each other in the order.
For example, the following filter will capture only DEBUG and ERROR messages (just as an example):
<filter type="log4net.Filter.LevelMatchFilter">
<levelToMatch value="DEBUG"/>
</filter>
<filter type="log4net.Filter.LevelMatchFilter">
<levelToMatch value="ERROR"/>
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
The one key here is that we need to have the DenyAllFilter at the end. This tells the logger that if it reaches this line, don't log it. That way it will log DEBUG messages, ERROR messages, and nothing else.
There are a lot of ways to manipulate the filter to get exactly what you want. Here is an article (full disclaimer: I wrote it) that shows you how to do a number of different things with the filter besides just level range:
http://www.codeproject.com/KB/dotnet/Log4net_Tutorial.aspx

log4net ForwardingAppender threshold

I need to configure logger to write messages to several appenders with different Log Levels.
For ex. I want RefreshDataService to log detailed info to TransportFileAppender and Warnings and Errors to RollingFileAppender.
Also, I'm using buffering to improve logging performance.
I setup FilteredFileLog appender to forward Warnings to FileLog->RollingFileAppender.
But for RefreshDataService logger, all log messages including debug and Info getting logged to FileLog.
Can you help me to configure the RefreshDataService logger to log only Warn+ messages to FileLog? Thanks.
Below is excerpt from my log4net config.
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="${TEMP}\logs\client\${ENV}\client.log" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="4096KB" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level [%property{ENV}] [%property{UID}] %logger - %message%newline" />
</layout>
</appender>
<appender name="TransportAppender" type="log4net.Appender.RollingFileAppender">
<file value="${TEMP}\logs\client\${ENV}\client.comm.log" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="4096KB" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<appender name="DetailedTransportLog" type="log4net.Appender.BufferingForwardingAppender">
<threshold value="DEBUG" />
<bufferSize value="200" />
<appender-ref ref="TransportAppender" />
</appender>
<appender name="FileLog" type="log4net.Appender.BufferingForwardingAppender">
<bufferSize value="20" />
<lossy value="false" />
<appender-ref ref="RollingFileAppender" />
</appender>
<appender name="FilteredFileLog" type="log4net.Appender.ForwardingAppender">
<threshold value="WARN" />
<appender-ref ref="FileLog" />
</appender>
<logger name="RefreshDataService" >
<level value="DEBUG" />
<appender-ref ref="FilteredFileLog" />
<appender-ref ref="DetailedTransportLog" />
</logger>
You can use a level range filter on the appender:
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="WARN" />
<levelMax value="FATAL" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
My understanding is that the Threshold property is used tell the appender to flush the buffer when messages of a certain level are logged. This way you can make for instance sure that errors are written immediately to the database.

Resources