A Complete Guide to Manage Your .NET , .NET Core Applications Logging Using Log4net.

Unit testing, design documentation, logging — all of these are secondary development activities that we know we really should be doing!. However, logging doesn’t seem to receive the same level of attention; consequently, developers find it hard to know the ‘what, when, and how’ of logging. Is it important? I think anyone who has been in the position of debugging a live application armed with just a log file will tell you, “yes!” There is nothing more frustrating than finding a log file swamped with superfluous detail. Logging, like unit testing, should be considered from day one of a project. It is a valuable tool, not a tedious task. so let’s dive in our story and answer the first question:

What is logging?

Logging is the process of recording application actions and state to a secondary interface maybe file or DB … and here the question is coming what is information we need to log in our application which actions and what application state we should record (log). You can log for different reasons maybe you need to observe the application actions and the state, however, an application log may also be use for creating statistics relating to the application usage. for example, a log file maybe be used to determine the number of concurrent users as a measure of performance.

Logging Messages Classifications

The typical classification system associates a log level with each item sent to the log. These log levels are usually comprised of three types which describe events or problems that have occurred within the application, of gradually increasing severity, WARN, ERROR, FATAL, one for general information purposes, INFO, and one for the purposes of debugging, DEBUG.

  • INFO → Just information messages. not used for a fault or error state in the application. Like version information of the software, usage information (who is using the software? what are they currently doing), what is external services is the application use.
  • WARN → indicates some form of application failure, however, the user experience has not been affected in any way. For example, a WARN message might be appropriate if an external service could not be used; however, a secondary service which performs the same functions was available. Also, a WARN message is appropriate if repeated attempts were required to access a given resource.
  • ERROR → it should indicate that something more critical has occurred. ERROR messages should be used to indicate that the application faced a significant problem and that, as a result, the user experience was affected in some way. For example, a database connection could have failed, resulting in parts of the application being rendered unusable.
  • FATAL → The user experience was not just affected, it has entirely ceased! For example, a component which is central to the operation of the application has failed in a way that leaves it in an unstable state, with the only possible course of action being to terminate the application altogether.
  • DEBUG → indicate that the logged message is to be used for debugging purposes

What should i be logging?

“what should I be logging?” This is not an easy question to answer, and it depends very much on the nature of the application which is being developed.

And here is the Logging frameworks are important because they make it easy to write your logs to different places by simply changing your configuration. You can write your .NET logs to a file on disk, a database, a log management system or potentially dozens of other places, all without changing your code.

What is the log4net ?

log4net has been around for a long time and is very similar to log4j which is for java.so, we can say 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. Trust me, you have to configure it before writing your first line of application code. With log4net it is possible to enable logging at runtime without modifying the application binary.

Log4net has three main components: loggers, appenders and layouts. These three types of components work together to enable developers to log messages according to message type and level, and to control at runtime how these messages are formatted and where they are reported. These components are helped by filters that control the actions of the appender and object renderers that turn objects into strings.

Loggers it is the logging space, that is the space of all possible logging statements, is categorized according to some developer-choses criteria. Loggers are named entities. Logger names are case-sensitive and they follow the following hierarchical naming rule: For example, the logger named “Foo.Bar” is a parent of the logger named “Foo.Bar.Baz”. Similarly, “System” is a parent of “System.Text” and an ancestor of”System.Text.StringBuilder”.
Appenders are how you direct where you want your logs sent. The most popular of the standard appenders are most likely the RollingFileAppender and ConsoleAppender.
Layouts, More often than not, users wish to customize not only the output destination but also the output format. This is accomplished by associating a layout with an appender. The layout is responsible for formatting the logging request according to the user’s wishes, whereas an appender takes care of sending the formatted output to its destination. The PatternLayout, part of the standard log4net distribution, lets the user specify the output format according to conversion patterns similar to the C language printf function.

What is the root logger ?

The root logger resides at the top of the logger hierarchy. It is exceptional in three ways:

  1. It always exists
  2. It cannot be retrieved by name
  3. It always has an assigned level. The default value for the root logger is DEBUG.

This rule is at the heart of log4net. It assumes that levels are ordered. For the standard levels, we have DEBUG < INFO < WARN < ERROR < FATAL.

Log4net in ACTION

  1. Add log4net package
  2. Add log4net.config file to your project or you can put log4net configuration directly in web.config , app.config but i preferred a separate file for log4net configuration.
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />

3. on log4net.config file Set “Copy to Output Directory” to Copy Alway

4. Tell log4net to load your config.

  • putting this in your AssemblyInfo.cs file. You can find it under the Properties section in your project. or by using xml configurator class inside log4net namespace
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config")]

5. Log something

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

Use log4net as Engineer

Be sure to use Debug, Info, Warning, Error, and Fatal logging levels as appropriate within your code. Don’t lot everything as Debug. Be sure to think about how you would be viewing the logs and what you want to see it later when coding your logging statements.

You can specify in your log4net config which log4net logging levels you want to log. This is really valuable if you want to specify only certain levels to be logged to a specific log appender or to reduce logging in production. This also you to log more or less data without changing your code.

log4net levels:

  • All — Log everything
  • Debug
  • Info
  • Warn
  • Error
  • Fatal
  • Off — Don’t log anything

Log4net Pattern Layout

<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%-5p %d{MM-dd hh:mm:ss.ffff} [%thread] %m%n" />

let’s explain the above layout : write the level (%p), current date time (%d), thread # (%thread), the message (%m) and a new line (%n). The “-5” in the “%-5p” is to set the width of the field to 5 characters.

you can log more information but it will have performance impact to your app & are not recommended for high volume of logging like the following:

  • %method — name of the method where the log message was written
  • %stacktrace{level} — output a stack trace to show where the log message was written
  • %type — type of the caller issuing the log request. Mostly likely your class name
  • %line — the line number from where your logging statement was logged

log4net for .NET Core

the log4net team published new NuGet packages that support .Net Standard 1.3, which means it should work with .NET Core. i already done with one basic Hello world example explaining how you can configure log4net inside one .Net Core console application.

log4net Best Practices

  1. Define your LogManager Object as static
  2. IF you have issues with log4net appenders, you can enable internal log4net logging via web.config file.
<trace autoflush="true">
initializeData="C:\tmp\log4net.txt" />

3. Do not send emails on every exception. [SmtpAppender]

4. Use log management system to views logs files across many servers.

5. You can make your own custom log4net appenders. for example, you can build custom appenders to log your message to any cloud services such as azure table or AWS.

6. Customize the layout in logs file using log4net pattern layouts.

7. You can use the diagnostic contexts to log additional fields, i am really in love with this feature. let’s explain more about this, you can also log custom fields to help give some more context about the user, customer or even the transaction related to the log statements, then you can modify log4net pattern layout to include “%property{customer}” to output it in the logs.

log4net.ThreadContext.Properties["customer"] = "My Customer Name";

log.Debug("We are going to try and do a web request");

catch (Exception ex)
log.Error("Error trying to do something", ex);
log.Debug("We are done with the web request");

8. Using log4net, you can log an object or properties with a message


Let me know in the comments if you have any feedback or feel free to reach out to me through my LinkedIn.

Or my about me Link. Follow me on Medium.

Don’t forget to hit the 💙 if you enjoyed this article.

Cheers and happy learning!