Sitecore logging fundamentals

What’s an application without proper logging? You are probably aware that Sitecore comes with it’s own static Sitecore.Diagnostics.Log class to quickly access the logging system. But how does it work under the hood? What is the impact on Sitecore solutions in Azure PaaS? How is logging handled in the new Sitecore Host based .NET core application? Let’s have a deep dive into the world of Sitecore logging.

Sitecore.Diagnostics.Log

Let’s start by covering the basics. The Sitecore.Diagnostics.Log is a static class, part of the Sitecore.Kernel. The class itself does not do the actual logging, in fact it is nothing more then a shell around the Log4Net logging framework.

Log4Net is an open source logging framework that was ported from java’s Log4J library. It has a large community support and is/was widely used in .NET applications. Log4Net uses appenders to determine where you want to log (console, file, database, etc) and can hold different layout patterns to format the messages. Logger are defined to support different log levels per category or namespace. Logging is done through the ILog interface that is instantiated using LogManager.GetLogger(catname or classtype).

By default Log4Net is initialized by adding a config section in your web.config by defining a configSection and then the actual config.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
    </configSections>
    <log4net>
        <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" >
            <layout type="log4net.Layout.PatternLayout">
                <conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
            </layout>
        </appender>
        <root>
            <level value="INFO" />
            <appender-ref ref="ConsoleAppender" />
        </root>
    </log4net>
</configuration>

However, Sitecore created a custom ConfigSectionHandler, so that the loggers can be defined inside the “Sitecore” part of the config and so that they can benefit from Sitecore config patching system.

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

Once the configuration is done, in a standard application , Log4Net is initialized based on it’s configuration by calling log4net.Config.XmlConfigurator.Configure(). In Sitecore the initialization is done by the Sitecore.Diagnostics.LoggerFactory class inside the Kernel.

So in short, when you want to perform logging in Sitecore, you can choose to use the Sitecore.Diagnostics.Log wrapper. Or you can use Log4Net directly and instantiate an ILog class by calling LogManager.GetLogger(class or categoryname).

Microsoft Logging Abstractions

With the introduction of .NET core, Microsoft introduced the their own logging abstractions framework. This framework is also compatible for class asp.NET applications. Just like Sitecore.Diagnotics.Log, MS Logging Abstractions is an empty shell provided by Microsoft to abstract logging. It needs a loggingprovider to do actual logging.

Loggers are created by the LoggerFactory. The loggerproviders are configured on this LoggerFactory by calling factory.AddProvider(new Log4NetLoggerProvider());. Through the factory you can then initiate your Logger class “logger = factory.CreateLogger<HomeController>();” to perform actual logging “logger.Error(‘something wrong’,ex)”.

In Sitecore Host applications all logging is done through the Microsoft Logging Abstractions framework. The loggerfactory is configured at startup and loggers are instantiated using dependency injection. By default, the loggerfactory is configured to use Serilog framework for the actual logging, but you could also configure it to use Log4Net or any other logging framework.

Serilog is a relative new kid on the block and comparable with Log4Net. It is build with powerful structured event data in mind.

In the latest versions of Sitecore, the main Sitecore application is also starting to use the logging abstraction framework instead of the “older” Sitecore.Diagnostics.Log. In the main application, the logging abstractions are backed with the same Log4Net configuration.

Because Logging Abstraction is a higher level and framework independent logging solution, it is my personal preference to also use the Microsoft Logging Abstractions framework in your custom code. The fact that Sitecore itself is more and more using this framework itself, only strengthens this decision.

Linking Logging Abstractions to Log4Net

We have been using Logging Abstraction for a few years now in our custom code, and before Sitecore 9 we had to link logging abstraction to log4net manually by creating our own Logger and LoggerProvider. With Sitecore 9, Sitecore started to use the framework itself and the initialisation of the logging abstraction is a bit tucked away in the Sitecore.xDB.ReferenceData.Client.Xmgmt.Logging dll. In this dll you will find the SitecoreLogger class that implements the ILogger interface and uses log4net to pass the logging through. The SitecoreLoggerProvider is responsible for creating these loggers.

What’s Next?

We have now exposed the Sitecore logging frameworks and mechanisms in a Sitecore 9 solution. In the end, it all comes down to logging by passed to Log4Net net and by default log into different logfiles onto your system (as configured in the sitecore config).

This story will continue with a look on Logging in Sitecore Azure PaaS applications. In this post we will introduce Application Insights and Azure Application Log (Streams) to the logging architecture and find out how logging is added to those system instead of the log files of an IaaS solution.

Leave a Reply