Attaching appenders to classes in config file in Log4net - c#-4.0

I managed to get started with Log4net but all my classes are using the same appender.
I want some classes to use a special appender.
Following is my log file:
<appender name="InfoRollingLogFileAppender" type="log4net.Appender.RollingFileAppender,log4net">
<param name="File" value="C:\Test.log"/>
<param name="RollingStyle" value="Date"/>
<param name="DatePattern" value="_yyyy-MM-dd.log"/>
<param name="StaticLogFileName" value="true"/>
<maximumFileSize value="100KB" />
<appendToFile value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%newline ---------------START---------------------- %newline %date - %message %newline ----------------END--------------------- %newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="DEBUG" />
<levelMax value="DEBUG" />
</filter>
<filter class="log4net.Filter.DenyAllFilter"/>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="InfoRollingLogFileAppender" />
</root>
Here is how I am using it in my code:
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
and then to log I use log.Debug("Goes in Log File").
My question is how can I have different appenders for specific classes?

You can define appenders per logger which in your case translates to "per class":
<root>
<level value="DEBUG" />
<appender-ref ref="InfoRollingLogFileAppender" />
</root>
<logger name="YourNameSpace.YourClass" additivity="false">
<level value="DEBUG" />
<appender-ref ref="YourOtherAppender" />
</logger>
Important is the additivity flag: Without it the appenders defined in the root (or parent) logger are inherited.

Related

Log4net: Multiple loggers single appender

I have multiple loggers referencing the same (rolling file) appender.
Only the first logger's output is appearing in the file.
Is it possible to make the appender work with multiple loggers? (I suppose not, but have not found any info in the docs, so need to confirm).
(I know there's logger inheritance, but I'm asking about non-inherited "independent" loggers)
My logger configuration is as follows
<logger name="a.b.c.Class1">
<level value="ALL"/>
<appender-ref ref="DebugAppender"/>
<appender-ref ref="ErrorsAppender"/>
</logger>
<logger name="a.b.c.Class2">
<level value="ALL"/>
<appender-ref ref="DebugAppender"/>
<appender-ref ref="ErrorsAppender"/>
</logger>
<logger name="a.b.c.Class3">
<level value="ALL"/>
<appender-ref ref="DebugAppender"/>
<appender-ref ref="ErrorsAppender"/>
</logger>
<logger name="a.b.c.Class4">
<level value="ALL"/>
<appender-ref ref="DebugAppender"/>
<appender-ref ref="ErrorsAppender"/>
</logger>
<logger name="a.d.e.Class5">
<level value="ALL"/>
<appender-ref ref="DebugAppender"/>
<appender-ref ref="ErrorsAppender"/>
</logger>
My appender configuratoin is as follows
<appender name="DebugAppender" type="log4net.Appender.RollingFileAppender">
<file value="C:/Debug.log" />
<appendToFile value="true" />
<maximumFileSize value="256KB" />
<maxSizeRollBackups value="10" />
<param name="Threshold" value="DEBUG" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="Event: %d [%t] %-5p %c - %m%nProperties: %properties%n%n" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="DEBUG" />
<levelMax value="FATAL" />
</filter>
</appender>
<appender name="ErrorsAppender" type="log4net.Appender.RollingFileAppender">
<file value="C:/Errors.log" />
<appendToFile value="true" />
<maximumFileSize value="256KB" />
<maxSizeRollBackups value="10" />
<param name="Threshold" value="WARN" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="Event: %d [%t] %-5p %c %stacktrace - %m%nProperties: %properties%n%n" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="WARN" />
<levelMax value="FATAL" />
</filter>
</appender>
The Log4net configuration is loaded with the regular
log4net.Config.XmlConfigurator.Configure()

windsor castle - log4net - RollingFileAppender - Issue - Information is written twice in the file

Issue: All the information that is logged is written twice in the file.
Please find the below configuration that I use:
I could observe the issue only when multiple loggers were introduced.
<root>
<level value="DEBUG" />
<appender-ref ref="LogFileAppender" />
<appender-ref ref="MemoryAppender"/>
<appender-ref ref="EventsFileAppender" />
</root>
<logger name="FileLogger">
<level value="DEBUG" />
<appender-ref ref="LogFileAppender" />
<appender-ref ref="MemoryAppender"/>
</logger>
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender" >
<param name="File" value="C:\log-file.txt" />
<param name="AppendToFile" value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="5MB" />
<staticLogFileName value="true" />
<filter type="log4net.Filter.LoggerMatchFilter">
<LoggerToMatch value="FileLogger" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%date [%thread] %-5level - %message%newline" />
</layout>
</appender>
<appender name="MemoryAppender" type="log4net.Appender.MemoryAppender">
<filter type="log4net.Filter.LoggerMatchFilter">
<LoggerToMatch value="FileLogger" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
</appender>
<logger name="EventsLogger">
<level value="DEBUG" />
<appender-ref ref="EventsFileAppender" />
</logger>
<appender name="EventsFileAppender" type="log4net.Appender.RollingFileAppender" >
<param name="File" value="C:\ObjectServerEvents\ObjectServerEvents-file.txt" />
<param name="AppendToFile" value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="100MB" />
<staticLogFileName value="true" />
<filter type="log4net.Filter.LoggerMatchFilter">
<LoggerToMatch value="EventsLogger" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%date [%thread] %-5level - %message%newline" />
</layout>
</appender>
Can you spot the mistake in this? How to resolve this?
You are adding the appenders twice: once to the root element, and once to each logger.
Remove the appender declarations from either the root element or the loggers, and each event will only be logged once.
<root>
<level value="DEBUG" />
<appender-ref ref="LogFileAppender" />
<appender-ref ref="MemoryAppender"/>
<appender-ref ref="EventsFileAppender" />
</root>
<logger name="FileLogger">
<level value="DEBUG" />
</logger> <!-- etc -->

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.

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

Why does log4net only log errors if my <root> level is INFO?

I obviously don't understand log4net. My root log level is configured as follows:
<root>
<level value="ERROR"/>
<appender-ref ref="FileAppender" />
</root>
My log initialization looks as follows:
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
And my actual logging call looks as follows:
LOG.Error("Error submitting Registration.", exc);
Here's the funny part. This log statement ONLY works if I set the root log level to INFO. Why does the log level ERROR not work (and I only want errors, not Info, Debug etc...)?
<root>
<level value="ALL" />
...
</root>
Someone of my log4net-Configfile:
<appender name="FileAppender_FullLog" type="log4net.Appender.FileAppender">
<file value="Log_Full.txt" />
<appendToFile value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{yyyy-MM-dd HH:mm:ss} [%-5level] [%logger{2}] - %message%newline" />
</layout>
</appender>
<appender name="FileAppender_SmallLog" type="log4net.Appender.FileAppender">
<file value="Log.txt" />
<appendToFile value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{yyyy-MM-dd HH:mm:ss} [%-5level] [%logger{2}] - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="INFO" />
<levelMax value="FATAL" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
</appender>
<appender name="SmtpAppender" type="log4net.Appender.SmtpAppender">
..
</appender>
<!--LogLevel: OFF, FATAL, ERROR, WARN, INFO, DEBUG, ALL -->
<root>
<level value="ALL" />
<appender-ref ref="FileAppender_FullLog" />
<appender-ref ref="FileAppender_SmallLog" />
<appender-ref ref="SmtpAppender" />
</root>
Edit:
<appender name="FileAppender_SmallLog" type="log4net.Appender.FileAppender">
<file value="Log.txt" />
<appendToFile value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{yyyy-MM-dd HH:mm:ss} [%-5level] [%logger{2}] - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="ERROR" />
<levelMax value="FATAL" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
</appender>
<!--LogLevel: OFF, FATAL, ERROR, WARN, INFO, DEBUG, ALL -->
<root>
<level value="ALL" />
<appender-ref ref="FileAppender_SmallLog" />
</root>
The better way ist to use "< filter type="log4net.Filter.LevelRangeFilter">..." because you can change this setting for every appender if you want this in feature.
With the help of our clever architect I figured this one out...
I used to have my log initialization in assemblyInfo.cs (but this was wrong).
I moved the log initialization to my global.asax in app_startup:
protected void Application_Start(Object sender, EventArgs e)
{
string configFilePath = Server.MapPath("~/Config/Log4Net.config");
log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(configFilePath));
}
The server.MapPath bit is very important, otherwise log4net tries to read its configuration from the system32\inetsrv folder.
I think my previous logging worked from time to time due to the order in which the assemblies were loaded, or something like that. Either way, this solution works.

Resources