Log4net for .NET 4.0 & .NET 3.5/4.0 client

By DimitriC at January 19, 2012 08:26
Filed Under: General, log4net, tools & Utilities, Programming

Release 1.2.11 of log4net has these changes (source):

 

General:

 

log4net 1.2.11 is not only a bug fix release, it also adds support for Microsoft® .NET 4.0 as well as the client profiles of .NET 3.5 and .NET 4.0. … The binary distributions no longer contain assemblies built for the Compact Framework 1.0 or the Shared Source CLI - you can build those yourself using the source distribution.

NOTE: The signature of ILoggerFactory.CreateLogger has changed!

 

Some of the bug fixes:

- Visual Studio 2010 .NET 4.0 Application does not copy log4net lib to bin directory

- RemoteFileAppender Tests fail on Windows 7

- log4net doesn't log when running a .Net 4.0 Windows application built in Release mode

- EventLogAppender's ActivateOptions throws SecurityException on Vista/Win2k3 and later when not run as administrator

 

Some of the improvements:

 

- support .NET 2.0 connectionStrings configuration section

- IPAddressConverter improvement for .NET 2 or .NET 3

- Add Cc and Bcc support to SmtpAppender

 

Some new features:

 

- add the ability to roll files based on universal time (UTC).

- Support ASP.Net related PatternConverters to allow items from the HttpContext.Current.Session, Cache, Request, etc. to be captured.

- Build for Compact Framework 2.0

- Added ExceptionEvaluator

- Add TimeEvaluator

- New property ReplyTo address for the SmtpAppender required

- Buildable with VS 2008 and .NET FW 3.5

  • - Support .NET 4.0 including Client Profile

 

 

Previous articles:

 

- Logging: Log4Net Part I

- Logging: Log4Net Part II

- Logging: Log4Net Part III

- Logging: What/When to log?

- Logging: Log4Net Custom AdoNetAdapter and RollingFileAppender with XML

 

Links:

 

- Log4net web site

- Download Log4net

Log4Net logging framework, custom AdoNetAdapter and RollingFileAppender with XML

By DimitriC at October 04, 2010 10:00
Filed Under: Architecture, log4net, Programming, tips & tricks, tools & Utilities

Mike Bevers has done some cool work with log4net. Next to creating his own logging framework using L4N, he also implemented a custom AdoNetAdapter (logging to a database) and a RollingFileAppender with XML.

 

For more information, please check his blog, or the Log4Net posts:

 

- Logging Framework with Log4Net
- Log4Net: custom AdoNetAppender
- Log4Net: RollingFileAppender with XML

Logging: Log4Net – What/When to log?

By DimitriC at April 27, 2010 11:51
Filed Under: log4net, Programming

Let’s say we have an application and we’ve implemented logging so we can keep an eye on performance, errors,… There are several strategies on how to configure your logging to ensure you that you not only get the right information, but also the right amount of information.

 

While developing an application (whether it’s a Windows Forms or Web application), usually you development environment provides you with a set of tools that help you debug your solution. .NET has the System.Diagnostics namespace which, next to the EventLog (interact with the Windows event logs), Process (interact with local and remote processes and start/stop local system processes) and PerformanceCounter classes, contains the Trace and Debug classes. As with log4net, the Trace class provides the ability to define the output target. You can do this by adding instances of the TraceListener to the Listeners collection. The TraceListener is also defined and configured in the applications configuration file, but the output is not as extensive as Log4Net and does not provide as many appenders. The PerformanceCounterCategory class allows you to define new counters and categories but doesn’t allow you to turn on/off logging per category. There is also no possibility to provide several output targets. This is logical since these tools shouldn’t be used as logging-mechanisms in production environments. Nonetheless, they are very helpful and efficient when using them while developing your applications.

 

Does this mean that log4net isn’t of any use while developing your application? Of course not! The logging functionalities should be embedded in your application’s architecture. Like this it becomes very normal for you to interpret log-files and you immediately have an idea of possible performance impact. During development you can also play with the log4net settings to optimize the amount of data that is stored in files/database.

 

In production environments, you can’t depend on the .net tools you used during the development of your solution. Here is where log-files come in handy. Of course, the amount of data we can keep in our logs isn’t infinite. The amount and size of log-files you wish to keep can be approached in several ways:

 

- archival logging

- circular logging

- rolling logging

 

Archival logging means that you will create log files of a certain size and each time the size is reached, a new file is started. A good way to distinguish between these files is to add the date to the filename, that way you have a chronically correct view of your log files. This can keep going until your hard drive is full. This type of logging can be interesting during development (keeping in mind you watch your available disk space). When your application is running in a production environment, circular logging becomes more interesting.

 

Circular logging will overwrite the oldest log-entry with a new log-entry. Here you will need to specify for how long you wish to keep a log-entry. For example, let’ say you want to keep all the logs for the past month, so every day the log entries older than today minus one month will be deleted and of course, the log-entries for today are added. The advantage here is that you have a defined set of logs which is interesting concerning disk space, of course, if you generate gigabytes of logs every day, this may still be a problem. This problem can be addressed by defining the boundaries of your log not in time but in size (of course, there is always data-loss) You can solve this by adapting the strategy to (compress and) move your log files on a daily/weekly/monthly basis to a storage server (generally slower, but with enough disk space so you can keep the files for the timeframe you want).

 

Rolling logging means that you define the size of a log and the number of repetitions the log can have. Let me clarify this with an example: Let’s say we write our logging-events to a file. I will define the maximum size of a log (let’s say 5MB) and the maximum amount of repetitions this file can have (let’s say 10). Now, the maximum size of your log is 50 MB, divided into 10 files of 5MB each. This can be very interesting for actually reading a log file in a text editor. These usually don’t do so well with big text-files. When the maximum number of files is reached the oldest log messages in the oldest file will be deleted and the new messages are added to the most recent file. Like this your logs represent a rolling window on the last 50MB of log-information.

 

In the previous methods, there is always a loss of data at some point. It can be interesting (especially for production environments) to keep a Log Digest. This is where a digest is generated of log-content that is to be deleted or overwritten. This can be a statistical summary of the events and you may include the most severe log-entries for future use. This digest can be used to have some statistics about your application over a long period of time. It will let you see the evolution in error/warning/informational logging-statements.

 

Using email

Often, there is a development team somewhere and the end users are some place else. And of course, you don’t have developers looking at the log-files all day to see that something has happened. Here notifications via email become crucial. Of course you want to keep spam-mail to a minimum, so make sure that the log-level for the SMTP-appender is set to ERROR. You can do this using the <evaluator> tag in the appender’s configuration. Apart from that the SMTPAppender has more, but expected, fields in it’s configuration such as sender (from), recipient(to), subject, smtpHost and buffersize (how many messages per email):

 

<to value="to@domain.com" /> 
<from value="from@domain.com" /> 
<subject value="test logging message" /> 
<smtpHost value="SMTPServer.domain.com" />
<bufferSize value="512" /> 
<evaluator type="log4net.Core.LevelEvaluator">
 <threshold value="WARN"/> 
</evaluator> 

 

Using XML

When using the XmlLayout-class, you can, as the name would suggest, output your log messages in XML-format. As far as readability goes, the XmlLayout won’t do you any good, but it makes your log output structured. This can be essential when you want to automatically interpret log files  for let’s say to filter out specific error-patterns, messages from a certain user or even when you want to write your own log-interpreter. Every attribute you use in your PatternLayout will be a tag in the XML-output.

 

Note: log4net does not add the root-node. So if you are opening the log file with an XML-reader you might need to add this yourself.

Logging: Log4Net – Part II

By DimitriC at April 27, 2010 10:32
Filed Under: log4net, Programming, tools & Utilities

I’ve started an example-application which is a simple Console application. Using this application I will try to show you how to set up, configure and use log4net.

To use log4net in your application, add it as a reference (right-click on the References-folder, navigate to where you’ve extracted the log4net-DLL, select it and click ‘OK’ ). And in the code, add the following using-statement on top of the page:

using log4net;

 

Now we need to add a configuration file to the project. Here we will have the necessary configuration settings for log4net. So right-click on the project, Add, New Item and in the Add New Item window, select the “Application Configuration File”. Leave the default name (App.config) and click “Add”.

image

 

When you open up the App.config file, you will see an empty configuration section.

 

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
</configuration>

 

First of all we need to define a new configuration section for log4net. We also need to mention by what DLL the configuration section will be handled. We do this by adding a configSections-section in the configuration-section of the App.config:

 

  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>

 

Do note that we haven’t done any configuration for log4net. At this point, we’ve just told .NET that in the App.config-file there will be a section called “log4net” that will be handled by the Log4NetConfigurationSectionHandler found in the log4net assembly.

 

As said in Log4Net – Part I, log4net allows you to output log-information to several targets. This goes from obvious logging targets such as files, console- and trace-window, Windows Event log, database, email,… to less used output targets such as in memory buffers, Telnet sessions,… For a full list of output targets, check the “Output to multiple logging targets”-section on the features-page. Of course, it’s possible to define multiple output targets in the configuration (write a log-entry to a log-file and send an email to someone with the log-entry).

 

For this example I will log to both a flat file and the console-windows of my application. So now, in the App.config file I will configure log4net to do just that. The configuration will be placed in a section with the same name as I previously defined in the configSections-section (and still within the <configuration>-tags).

 

<log4net>
    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
      <file type="log4net.Util.PatternString"
            value="Log4NetSampleApp-%appdomain_%property{log4net:HostName}.log"/>
      <rollingStyle value="Composite"/>
      <datePattern value="yyyyMMdd"/>
      <maxSizeRollBackups value="10"/>
      <maximumFileSize value="2MB"/>
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date %-5level %logger: %message%newline" />
      </layout>
    </appender>

    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
     <threshold value="ERROR" />
     <layout type="log4net.Layout.PatternLayout">
       <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
     </layout>
    </appender>
  </log4net>

 

The RollingFileAppender


<appender>: Here I define the name and type (the library used in log4net to correctly interpret this configuration)

<file>: You can just set the value property to set the name and location of the log file like so:

<file value="C:\logfile.log" /> 
 

But it’s more interesting to define your own name using a pattern. Doing so allows you to add some information to the filename. In my case it will set the name to Log4NetSampleApp-Log4netSample.vshost.exe_DimitriPC.log. Of course, the HostName will always be my PC, but when developing applications that might run on several machines, it’s interesting to see which log file comes from which machine. Note that I haven’t set a path for the file, just a filename. The file will be dropped where the executable is: \Log4netSample\Log4netSample\bin\Debug


<rollingStyle>: This setting will tell log4net to roll files on a the date pattern defined in <datePattern>. This means that it create a new log file per day and append the date as described in the date pattern to the file. So log4net will detect that there isn’t a log file for today, and create one. If it sees that there was a log file for yesterday, it will append yesterday’s date to that file:

Log4NetSampleApp-Log4netSample.vshost.exe_DimitriPC.log20100202

 

Also, for each day it will only keep the last 2MB of log data (the amount of data is defined in the <maximumFileSize>-tag. The value defined in <maxSizeRollBackups> says how many files will be kept per day. In this configuration it will only keep the last 10 files (of max 2MB each).

 

<layout>: This is where we define the layout of the messages that are written to the log-target.  The type defines what log4net-class will interpret what we define in the <conversionPattern>-tag. Do note that every parameter starts with a % (percent sign).

- First we set a timestamp (to the milisecond) which will look something like this: 2010-02-04 07:40:37,624.

- After that comes the level of the logging event. When writing informational logs this will say INFO, when writing errors it will say ERROR. When we look at the code, we will see how to specify the level of the logging event.
The –[number] defines how many characters can be used to specify this information. Here the level can be 5 characters maximum.

- Now we set the logger which is the type of class that actually logs the event. In this case: Log4netSample.Program

- As final piece of information we set the message that we set in the code appended by a newline.

 

For an informational logging event, it gives something like this:


2010-02-04 07:40:37,624 INFO  Log4netSample.Program: test

 

For an error logging event (meaning that an exception was thrown in the code):

2010-02-04 07:41:11,995 ERROR Log4netSample.Program: Problem: System.Exception: something happened
   at Log4netSample.Program.Main(String[] args) in D:\projects\MyProjects\Log4netSample\Log4netSample\Program.cs:line 20

 

Here the stacktrace of the exception is also written to the log file.

 

For a complete overview of all the settings you can use to create your own layout, I refer to the PatternLayout documentation page.

 

The ConsoleAppender

 

<treshold>: This setting can be used to define what logging level you want for this appender. In this case, only the errors will be written to the console window.

Some of the predefined levels recognized by the system are: Off, Fatal, Error, Warn, Info, Debug, All.


The configuration is practically the same for the consoleAppender. The only thing different is the layout of the log message. In the console we will also see the thread number and the NDC-property which is the Nested Diagnostic Context associated with the thread (if any, else it will be null).

 

 

Now that the configuration is done, we can use log4net in our code. In my class I’ve defined a variable to hold the logger.

 

private static ILog log = LogManager.GetLogger(typeof(Program));
 
To make it easier, you can look up the type-parameter used by the GetLogger() method using reflection:
 
private static ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
 
In my Main method, I will let log4net know it needs to read the App.config to load my configuration:
 
log4net.Config.XmlConfigurator.Configure();

 

And now for some code that will use log4net:

 

try
{
    Console.WriteLine("program started");
    throw new Exception("something happened");
}
catch (Exception ex)
{
    log.Info("test");
    log.Error("Problem: ", ex);
//so we can check the output to the console Console.Read(); }