Category Archives: Debug

Log4net Initialization/Configuration alternatives

In a previous post where I talked about using log4net I used one of the alternative ways to initialize and configure the logging services.

This post will summarize these alternatives.

 

1. Programmatic initialization

The programmatic initialization should be done somewhere in your code.

This was the type of initialization used on the first post and its code is something like this.

using log4net;

using log4net.Config;

public class MyApp
{
    private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));

    static void Main(string[] args)
    {
        // BasicConfigurator replaced with XmlConfigurator.
        XmlConfigurator.Configure(new System.IO.FileInfo(args[0]));

            log.Info("Entering application.");

    }

}

2. Assembly attribute initialization

The assembly attribute initialization does not imply the inclusion of any code in your application. Instead, you just have to place an assembly level attribute in some file of your assembly. This way your code could be:

using log4net;

[assembly: log4net.Config.XmlConfigurator()]

public class MyApp
{
    private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));

    static void Main(string[] args)
    {
        log.Info("Entering application.");
    }
}

 

The assembly level attribute by itself does not mean a instruction to initialize the logging framework. Instead, the logging framework is initialized by the first call that is made to log4net (in the example the log.Info) initialized. This means that when using assembly attributes you should make a logging call as soon as possible and before calling any other external assembly.

 

Finally, if you are using logger objects defined per-class, a simple way to define a logger object that enables it to be copy-pasted in a very simple way is to do:

private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

 

This instruction uses reflection for determining the class type name that will be used in the logging messages.

For more information please refer to the log4net homepage.

Debugging Windows Services

Recently I had to develop my first Windows
Service in C#. I had already done Services in C++, and I was used to launch and
debug the Services thru Visual Studio (just by normally hitting F5). 

I was surprised to see that the normal C# Windows
Service code base does not allow this to be possible in a "out-of-the-box"
experience, and one had to do things like "Attach to Process", and/or put in
the source code "System.Diagnostics.Debugger.Launch();".

Not satisfied with these solutions, I searched
the web and I found this page that as a "perfect solution".

http://theimes.com/archive/2006/12/28/Debugging-Windows-Services-is-a-Pain.aspx

The author developed a Service Debugger Helper
class, that incorporates a GUI for allowing all the expected Start, Stop, etc,
interaction with the service. It is also possible to automatically start a
service by default, thus allowing the normal F5 experience.

Check out the author article and his source
code if you are interested in knowing how he made this. Also this other link
could be of interest to someone.

Run a Service without a debugger attached (.NET
Windows Service Runner)

http://theimes.com/archive/2007/08/22/net-windows-service-runner.aspx

PS: Regarding the usage of Timers in Windows
Services, be careful to use the ones in System.Timers.Timer, or else the timer may never (or
stop) be (being) fired.

Using log4net logging services

Whenever you have the need for debugging some application that by whatever reason cannot be properly debugged in Visual Studio, or even because your application requires some kind of logging/auditing functionality, instead of developing your own tool you have the option to use some existent logging frameworks.

One that I have tried and enjoyed its features and ease of use is log4net – http://logging.apache.org/log4net/.

Like they say on their webpage, "log4net is a tool to help the programmer output log statements to a variety
of output targets. log4net is a port of the excellent log4j framework to the
.NET runtime
". Its features are present here: http://logging.apache.org/log4net/release/features.html.

One of its great features is the ability to control and configure the logging framework entirely by an XML file. This allows the building and deployment of applications that at run-time can dynamically change its logging configuration. For this you should initialize to log in the following manner (in the example the XML configuration file is received in the application arguments):

// Import log4net classes.
using log4net;
using log4net.Config;

public class MyApp
{
    private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));

    static void Main(string[] args)
    {
        // BasicConfigurator replaced with XmlConfigurator.
        XmlConfigurator.Configure(new System.IO.FileInfo(args[0]));      
    }
}

After this, you can check if the initialization went ok by testing the value of: _log.Logger.Repository.Configured .

Now it is real easy to start logging things. You just have to do:

            log.Info("Entering application.");

        log.Debug("Entering application.");

and the framework takes care of the rest, logging acording to the configuration that you provided. Note that in the above code I am already logging into two different log levels, just as an example for showing you, that while developing I can have the level configured at DEBUG, and at production I can reduce the level to INFO, or even NONE, if I dont want any logging at all. If a problem occurs in production, I can just as easily change the log level to DEBUG again, and without having to change anything in the application, the logs start being generated. 

As a final example of the capabilities of the framework, I just want to show here a possible XML configuration file:

<?xml version="1.0" encoding="utf-8" ?>
<log4net>   
    <!– Rolling File Appender –>
    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
        <file value="log-file.txt" />
        <appendToFile value="true" />
        <maximumFileSize value="1KB" />
        <maxSizeRollBackups value="0" />
        <staticLogFileName value="true" />           
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date [%thread] %-5level %logger – %message%newline" />
        </layout>
    </appender>

    <!– Console appender –>
    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
        <target value="Console.Error" />
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%message%newline" />
        </layout>
    </appender>
   
    <root>
        <level value="DEBUG" />
        <appender-ref ref="RollingFileAppender" />
        <appender-ref ref="ConsoleAppender" />
    </root>   
</log4net> 

In this configuration, I define two different appenders (RollingFile and Console), each with its own configuration. At the root level, I define the logging level at DEBUG (so I want to see everything until this level), and that the logging should be done to the two defined appenders. So, when I log something with this configuration, the log is done to a file and to the application's console.

So, you see that it is easy to add logging capabilities to your application.