Disclaimer: This website requires Please enable JavaScript in your browser settings for the best experience.

HomeDev GuideRecipesAPI Reference
Dev GuideAPI ReferenceUser GuideLegal TermsGitHubNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev Guide

Logging

Describes the logging functionality in Optimizely Content Management System (CMS), and how to implement logging with log4net, which is one of the logging providers that can be used.

📘

Note

If you ever want to change the underlying logging framework or are using Optimizely Digital Experience Platform (DXP), use the log abstraction EPiServer.Logging.LogManager.

The Logging API shipped with Optimizely Content Management System (CMS) is an abstraction for writing log messages from the system. It does not compete with existing logging frameworks such as log4net; it works as a façade for such frameworks. To manage the logger's configuration and output, refer to the API of the implementing framework.

The API is used internally by the CMS assemblies for logging, but it is also open to be used by any third-party product or implementation. Use this API to develop modules and add-ons for the CMS platform.

📘

Note

When you create new CMS sites using the Visual Studio integration, the package EPiServer.Logging.Log4Net is installed by default, which is the log4net implementation of the API.

Log a message

When you want to log a message, retrieve a logger instance using the LogManager class. Only retrieve the logger once for each class that uses it and store the logger in a static variable, such as:

private static readonly ILogger Logger = LogManager.GetLogger();

This code creates a logger instance with the same name as the type where it is instantiated, including namespace. You can also explicitly pass in another type or name directly to the logger, which could be useful to simulate log messages from another source. This method is guaranteed to return an instance, regardless of whether it finds any implementation, so you can safely use the logger without performing any null checks.

After the logger instance is available in your class, you can call any provided overloads, depending on the message's criticality. The following examples show the Debug level, but equivalent methods are available for other levels (Trace, Information, Warning, Error, Critical).

// Log simple message
logger.Debug("Some message");

// Log message and exception
logger.Debug("Some message", exception);

// Log message formatted with any number of arguments
logger.Debug("Some format {0},{1}", arg0, arg1);

// Log object state formatted with the provided formatting method
logger.Debug(someObject, s => "someObject is currently: " + s.SomeCostlyMethod());

// Log object state and exception formatted with the provided formatting method
logger.Debug(someObject, someException, (s, ex) => "someObject: " + s.SomeCostlyMethod() + " threw an exception: " + ex);

While the API exposes an IsEnabled method on the logger, you do not need to check this before writing a message because it does this before it tries to write it. If there is a cost to constructing the log message, such as an expensive value serialization, use any overloads that take a message formatter delegate and pass in a method that constructs your log message. This delegate is not called until the enabled state is verified, thus avoiding unnecessary work if the logger is disabled.

📘

Note

Most of the logging methods of the logger are provided through extension methods, so it is necessary to import the EPiServer.Logging namespace to get easy access to these.

Backwards compatibility

If you are currently using log4net for logging and want to start using the API in an existing project, there is a dedicated namespace called EPiServer.Logging.Compatibility that will help with the migration. This namespace contains a LogManager class and an' ILoginterface that matches their log4net equivalents, which in most cases should enable a search-and-replace between log4net andEPiServer.Logging.Compatibility` to maintain the same logging.

📘

Note

This compatibility layer only is suggested as a short term solution to speed up the migration and that we are recommending everyone to use the standard API in the longer term.

Implement the API

CMS provides an implementation for log4net through the EPiServer.Logging.Log4Net package, but it is relatively simple for anyone to replace this implementation with another.

Implement ILogger and ILoggerFactory.

  • ILogger writes a message of a specified level to the logging framework of choice.
  • ILoggerFactory creates ILogger instances.

Add the LoggerFactoryAttribute to your assembly to register the implementation and define the type of your logger factory. The type implementing ILoggerFactory is required to have a public parameter-less constructor.

[assembly: LoggerFactory(typeof(MyLoggerFactory))]

The Logging API currently only supports one logger type, and it uses the first factory type it can find when scanning assemblies. Make sure you remove the EPiServer.Logging.Log4Net assembly before you deploy another implementation.