log4net smtpappender subject based on log level - log4net

Is it possible to configure log4net to have two smtp appenders - one that sends emails only when log level is >= WARN and second that sends everything, but never two on the same time.
<appender name="SmtpAppenderWarn" type="log4net.Appender.SmtpAppender">
<to value="to#domain.com" />
<from value="from#domain.com" />
<subject value="Import completed with warnings / errors" />
<smtpHost value="localhost" />
<bufferSize value="512" />
<lossy value="true" />
<evaluator type="log4net.Core.LevelEvaluator">
<threshold value="WARN"/>
</evaluator>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%newline%date [%thread] %-5level %logger [%property{NDC}] - %message%newline%newline%newline" />
</layout>
</appender>
<appender name="SmtpAppenderSuccess" type="log4net.Appender.SmtpAppender">
<to value="to#domain.com" />
<from value="from#domain.com" />
<subject value="Import completed successfully" />
<smtpHost value="localhost" />
<bufferSize value="512" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level %logger: %message%newline" />
</layout>
<filter type="log4net.Filter.LevelMatchFilter">
<levelToMatch value="INFO" />
</filter>
</appender>
I my application I have:
Log.Info("Importer is starting...");
//my logic
//if warn Log.Warn("Warning...");
Log.Info("Import finished");
So I'm using INFO all the time. Now when I encounter WARN both messages are being sent. I wish of course that the one with success info was not sent.

I have solved the problem by overriding log4net SendBuffer method:
namespace MyProject
{
public class SmtpAppenderInfoOnly : SmtpAppender
{
protected override void SendBuffer(log4net.Core.LoggingEvent[] events)
{
foreach (var loggingEvent in events)
{
if (loggingEvent.Level != Level.Info)
return;
}
base.SendBuffer(events);
}
}
}
And then in config file:
<appender name="SmtpAppenderSuccess" type="MyProject.SmtpAppenderInfoOnly,MyDll">
That way the SendMail method will not be executed when SendBuffer is canceled.

Your appenders can have min/max values like so:
<levelMin value="INFO" />
<levelMax value="INFO" />
<levelMin value="WARN" />
<levelMax value="WARN" />
So you can use different appenders for different ranges. I believe this should work for you.

Related

Configuring Log4Net for specific classes and overreaching error handling

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.

log4Net filtering for multiple outputs confusion

Trying to understand the log4net filtering.
After reading the docs some aspects are still elusive to me.
For example I have this config file:
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="..\Logs\CurrentLog" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10000" />
<staticLogFileName value="true" />
<filter type="log4net.Filter.LevelRangeFilter">
<acceptOnMatch value="true" />
<levelMin value="INFO" />
<levelMax value="FATAL" />
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level %date [%thread] %-22.22c{1} - %m%n" />
</layout>
</appender>
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
<file value="log-file.txt" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<header value="Service Logging -- Start" />
<footer value="Service Logging -- End" />
<conversionPattern value="%date [%thread] %-5level %logger [%ndc]
<%property{auth}> - %message%newline" />
</layout>
</appender>
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender" >
<applicationName value="WindowsService1.exe" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger
[%property{NDC}] - %message%newline" />
</layout>
</appender>
<!-- Set the default logging level and add the active appenders -->
<root>
<level value="DEBUG" />
<appender-ref ref="LogFileAppender" />
<appender-ref ref="RollingFileAppender" />
</root>
<!-- Specify the level for specific categories (“namespace.class”)-->
<logger name="WindowsService1.MyMonitor">
<level value="WARN" />
<appender-ref ref="EventLogAppender" />
</logger>
</log4net>
My expectations were:
The RollingFileAppender has a range of [INFO:FATAL] The Root has a
Level of DEBUG so it would let DEBUG and "greater" pass. Which
means all of RollingFileAppender's range would go through.
The LogFileAppender has no range specified so it would use Root's of DEBUG or greater.
And the EventLogAppender would only send event messages of WARN or greater to the Windows Event System - and - they would only
be messages from the class "WindowsService1.MyMonitor".
However it appears that all the messaging gets filtered to the WARN level!
Including my rolling log files and the log file "log-file.txt"
This seems like it should be simple - don't know why I'm so confused by it.
Hope someone can enlighten me.
Please feel free to use crayons and pictures because I think I need them.
Thanks.
UPDATE
In my Program.cs I have:
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "Log4Net.config", Watch = true)]
And in each class where logging is done:
private static readonly ILog log =
LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
UPDATE 2
At a different computer now. Had to recreate everything and used log4net debugging to assist.
But still can't get the desired output.
Basically want the WARN and above messages to go to one file and the Event logger. And those messages would be a subset of all the INFO and above messages.
The INFO and above messages - superset - would go into the rolling appender and overwrite themselves eventually. But the warnings and errors would always be maintained.
So here is a rework of all the files for a simple service. If I set WARN on the appender-ref ref=EventLogAppender then all the INFOs are suppressed.
Program.cs
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "Log4Net.config", Watch = true)]
// Ref: http://www.c-sharpcorner.com/UploadFile/naresh.avari/develop-and-install-a-windows-service-in-C-Sharp/
//
// use 'sc' to install/delete the service
// run 'sc' as administrator
// sc create "MySillyService" binpath= "C:\whatever\something.exe"
// sc delete "MySillyService"
namespace SimpleService1
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
}
}
Service1.cs
namespace SimpleService1
{
public partial class Service1 : ServiceBase
{
private static readonly ILog log =
LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private Timer timer1;
private int counter = 0;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
timer1 = new Timer();
timer1.Interval = 4000;
timer1.Elapsed += new ElapsedEventHandler(timer1_Tick);
timer1.Enabled = true;
log.Info("my service is started");
}
private void timer1_Tick(object sender, ElapsedEventArgs e)
{
counter++;
if (counter%2 == 0)
{
log.Info(String.Format("Counter({0:D}) is now even", counter));
}
else
{
log.Error(String.Format("Counter({0:D}) is now even", counter));
}
}
protected override void OnStop()
{
timer1.Enabled = false;
log.Info("my service was stopped");
}
}
}
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<appSettings>
<add key="log4net.Internal.Debug" value="true"/>
</appSettings>
<system.diagnostics>
<trace autoflush="true">
<listeners>
<add
name="textWriterTraceListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="C:\tmp\log4net.txt" />
</listeners>
</trace>
</system.diagnostics>
</configuration>
Log4net.config
<?xml version="1.0" encoding="utf-8" ?>
<!--
Ref: http://mitch-wheat.blogspot.com/2007/04/log4net-net-logging-tool.html
I keep this config file in a separate directory and copy it with a
post-build event:
copy /Y $(SolutionDir)Logger\Log4Net.config $(TargetDir)Log4Net.config
-->
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="..\Logs\CurrentLog" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10000" />
<staticLogFileName value="true" />
<filter type="log4net.Filter.LevelRangeFilter">
<acceptOnMatch value="true" />
<levelMin value="INFO" />
<levelMax value="FATAL" />
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level %date [%thread] %-22.22c{1} - %m%n" />
</layout>
</appender>
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
<file value="log-file.txt" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<header value="Service Logging -- Start - " />
<footer value="Service Logging -- End - " />
<conversionPattern value="%date [%thread] %-5level %logger [%ndc]
<%property{auth}> - %message%newline" />
</layout>
</appender>
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender" >
<applicationName value="Service1" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger
[%property{NDC}] - %message%newline" />
</layout>
</appender>
<!-- Set the default logging level and add the active appenders -->
<root>
<level value="DEBUG" />
<appender-ref ref="LogFileAppender" />
<appender-ref ref="RollingFileAppender" />
</root>
<!-- Specify the level for specific categories (�namespace.class�)-->
<logger name="SimpleService1.Service1">
<level value="WARN" />
<appender-ref ref="EventLogAppender" />
</logger>
</log4net>
Thanks for your help
Finally figured out the nuances to get this working as desired. Here's the config for anyone interested.
<?xml version="1.0" encoding="utf-8" ?>
<!--
I keep this config file in a separate directory and copy it with a
post-build event:
copy /Y $(SolutionDir)Logger\Log4Net.config $(TargetDir)Log4Net.config
-->
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="..\Logs\CurrentLog" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10000" />
<staticLogFileName value="true" />
<filter type="log4net.Filter.LevelRangeFilter">
<acceptOnMatch value="true" />
<levelMin value="INFO" />
<levelMax value="FATAL" />
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level %date [%thread] %-22.22c{1} - %m%n" />
</layout>
</appender>
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
<file value="log-file.txt" />
<appendToFile value="true" />
<filter type="log4net.Filter.LevelRangeFilter">
<acceptOnMatch value="true" />
<levelMin value="WARN" />
<levelMax value="FATAL" />
</filter>
<layout type="log4net.Layout.PatternLayout">
<header value="Service Logging -- Start - " />
<footer value="Service Logging -- End - " />
<conversionPattern value="%date [%thread] %-5level %logger [%ndc]
<%property{auth}> - %message%newline" />
</layout>
</appender>
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender" >
<!-- Put whatever name you want to display in the event log
for 'applicationName value=XX'
-->
<applicationName value="ServiceSkippy" />
<filter type="log4net.Filter.LevelRangeFilter">
<acceptOnMatch value="true" />
<levelMin value="WARN" />
<levelMax value="FATAL" />
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger
[%property{NDC}] - %message%newline" />
</layout>
</appender>
<!-- put namespace of service application in following name -->
<logger name="ServiceWithLog4Net">
<appender-ref ref="LogFileAppender" />
<appender-ref ref="RollingFileAppender" />
<appender-ref ref="EventLogAppender" />
</logger>
</log4net>
-Skippy

Log4Net: how to avoid Dummy entry created in Eventlog

I have created a sample program and every time I run this program, it is creating a dummy entry in the event log as below. How to avoid without creating a logger?
2014-02-24 18:04:53,557 [8] ERROR Log4NetSample.Program [(null)] - Error message
My Code:
using log4net;
using log4net.Config;
namespace Log4NetSample
{
class Program
{
static void Main(string[] args)
{
Program pg= new Program();
pg.Log4netCode();
}
private void Log4netCode()
{
XmlConfigurator.Configure();
ILog log = LogManager.GetLogger(typeof(Program));
log.Debug("Debug message");
log.Info("Info message");
log.Warn("Warning message");
log.Error("Error message");
log.Fatal("Fatal message");
}
}
}
Config file:
<log4net>
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="C:\Log\MyFirstLogger.log"/>
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<maxSizeRollBackups value="2" />
<maximumFileSize value="2KB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="DEBUG" />
<levelMax value="WARN" />
</filter>
</appender>
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender">
<Eventid value="100"/>
<LogName value="Log4NetSample" />
<applicationName value="Log4NetSample" source="Api" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="ERROR" />
<levelMax value="ERROR" />
</filter>
</appender>
<root>
<level value="ERROR" />
<appender-ref ref="LogFileAppender" />
<appender-ref ref="EventLogAppender" />
</root>
</log4net>
You message is the actual to message from the line log.Error. You do not need to log or test you logger right after init the config.

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.

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