Click or drag to resize
Log4net

[This is preliminary documentation and is subject to change.]

What is log4net?

log4net is a third party library used for logging in .NET –projects. Quotes from above website:

log4net is a tool to help the programmer output log statements to a variety of output targets. In case of problems with an application, it is helpful to enable logging so that the problem can be located. With log4net it is possible to enable logging at runtime without modifying the application binary. The log4net package is designed so that log statements can remain in shipped code without incurring a high performance cost. It follows that the speed of logging (or rather not logging) is crucial.
At the same time, log output can be so voluminous that it quickly becomes overwhelming. One of the distinctive features of log4net is the notion of hierarchical loggers. Using these loggers it is possible to selectively control which log statements are output at arbitrary granularity.
log4net is designed with two distinct goals in mind: speed and flexibility.
Where should log4net be used?

log4net is useful for debugging "custom" server-side code - examples:

Obviously, it is the responsibility of the application developer to write log output statements in strategically selected places in the code (and with proper log levels - see below chapter).

The contents of the log output are basically only a time stamp and an "unstructured" line of text. Therefore, the application developer must make sure, that the logged output contains enough information to be useful for whoever needs to inspect the logged output.

Why use log4net?

The biggest strength of log4net is that once it is incorporated it in your code, you can configure it in a thousand ways using the log4net configuration file (changing log levels, adding filters, changing appenders …).

Logging helps you finding the cause of the errors you experience in development as well as in production environments.

Appenders

log4net comes with several built-in "appenders" making it possible to log to a number of different targets.

  • The easiest to use (and most commonly used in TOPICA) is the RollingLogFileAppender

    • This appender logs to the file system using a configured number of files of configured maximum size. That is: even if logging is let on for a long time, the log output does not fill up the harddisk.

    • Because the output of the RollingLogFileAppender is text files saved on the web server, it is necessary to access the file system of the web server to study the log output.

  • The AdoNetAppender makes it possible to direct log output to a database table.

    • This requires that a database with a specific name and column layout is created in the database. Refer to the log4net and/or the example configuration files described below.

    • Then, the configurator may design a report that reads data from this database table.

    • This enables an end user (using the web user interface) to wiew log data generated by log4net.

Log levels

Log output statements has a level defined. The configuration defines a log level, that filters what log statements are producing output. Per default, only log statements with level less than or equal to the level in the configuration generate log output.

If for some obscure reason you wish to activate only DEBUG and FATAL it can be done (search the internet), but the default behavior for log levels are hierarchical from DEBUG to FATAL.

DEBUG

All log statements generate output

INFO

Log statements with levels INFO, WARN, ERROR, FATAL generate output

WARN

Log statements with levels WARN, ERROR, FATAL generate output

ERROR

Log statements with levels ERROR, FATAL generate output

FATAL

Log statements with level FATAL generate output

Configuration file

For log4net to work, you need a configuration file defining what appenders, filters and layout to use.

In theory log4net lets you can place the configuration file in any folder and call i whatever you like (as long as the running code has read access to this file).

The TOPICA framework requires the configuration file to be named log4net.config - and it must be placed in the root of the framework folder (the folder that the web home refers to). If such a file does not exist, log4net logging is not activated.

After initial installation of the TOPICA framework, the log4net.config file does NOT exist. A log4net.config is NOT contained in the TOPICA framework distribution files. This is to make sure, that any log4net.config that has been set up and edited / configured for the current environment, does NOT get overwritten, when TOPICA framework is updated to new version.

But the TOPICA framework DOES come with exmple configuration file(s).

  • In versions 4.25 and newer, the framework folder contains a subfolder Log4NetTemplates. Inside this folder you will find a number of example .config files (the filename gives an indication of which appenders are enabled).

    Copy the example file, that most closely fits your needs, to the framework folder (the parent folder), rename this file to log4net.config, and configure log level, appenders, etc. by editing this file.

  • In versions 4.24 and older, the framework folder contains a file log4net.config.example. To enable log4net logging, copy/rename this file to log4net.config, and configure log levels, appenders, etc. by editing this file.

How to implement log4net logging in code
  1. Custom code like custom webforms, custom webservices, pre-processes, and post-processes run "inside" the TOPICA framework, that already contains reference to log4net.dll - so you will not need to add any reference.

    If you are developing e.g. an .exe-file for batch-processing, you will need to add a reference to log4net.dll to your project.

  2. In your source code, add

    C#
    using log4net;
  3. Declare a static logger instance:

    C#
    protected static readonly ILog logger = LogManager.GetLogger((MethodBase.GetCurrentMethod().DeclaringType));
  4. Custom code like custom webforms, custom webservices, pre-processes, and post-processes run "inside" the TOPICA framework, that already handles initialization of log4net.

    If you are developing a piece of code, that does not run inside TOPICA (e.g. an .exe-file for batch-processing), you will to need initialize log4net logging yourself. This can be done in several ways (consult the log4net documentation. Examples:

    • Where your code starts executing:

      C#
      FileInfo configFile = new FileInfo(AppDomain.CurrentDomain.BaseDirectory + "\\Log4Net.config");
      log4net.Config.XmlConfigurator.ConfigureAndWatch(configFile);
    • In the AssemblyInfo.cs file:

      C#
      [assembly: log4net.Config.XmlConfigurator(ConfigFile = "Log4Net.config", Watch = true)]
  5. Now you are ready to add log statements to log4net. Before trying to write to log4net, it is consider good practice to test if the log level, you want to use, is activated in the configuration file to improve performance:

    C#
    if (logger.IsDebugEnabled)
        logger.Debug("... some debug output...");
    if (logger.IsErrorEnabled)
        logger.Error("... some error output...");
Using filters (advanced use)

One TOPICA instance (a web home) may run several applications. log4net obviously does not "know" anything about this, as this is a TOPICA-specific behavior.

When one TOPICA instance runs one application / environment only (as is typically the case in production environments), this is obviously not a problem.

But when one TOPICA instance runs several applications, and log4net has been set up with one of the default configurations, log output related to all the applications will be mixed in the same log output target (e.g. in same text files, or in same database table). But there is something that can be done about it:

Log4net has a feature, which makes it possible to direct and/or format log statements depending on the value of a property. In TOPICABasePage.aspx.cs a property containing the name of the current configuration is defined:

C#
log4net.ThreadContext.Properties["Config"] = base.ConfigurationName;

This makes it possible to filter out log statements to separate log files or using separate layouts for the log statements or both. In the configuration file you might write this, to write log statements for MYAPP in its own log file:

<appender name="RollingLogFileMYAPPAppender"  type="log4net.Appender.RollingFileAppender">
  <file value="..\Logs\MYAPP-rolling-log.txt" />
  <appendToFile value="true" />
  <maxSizeRollBackups value="10" />
  <maximumFileSize value="5MB" />
  <rollingStyle value="Size" />
  <filter type="log4net.Filter.PropertyFilter">
    <Key value="config" />
    <StringToMatch value="MYAPP" />
  </filter>
  <filter type="log4net.Filter.DenyAllFilter" />
  <staticLogFileName value="true" />
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%date (%property{Config}) [%thread] %-5level %logger (%file:%line) - %message%newline" />
  </layout>
</appender>

The above configuration snippet will place all log statements from configuration MYAPP in a rolling log file (of max size 5 MB) placed in .\Logs\MYAPP-rolling-log.txt and keeping at most 10 versions of the file. The <filter type="log4net.Filter.DenyAllFilter" /> ensures that only log statements with property config = "MYAPP" is written to the log file.

See Also

Other Resources