Open Source .NET Development [Electronic resources]

Brian Nantz

نسخه متنی -صفحه : 275/ 78
نمايش فراداده

Loggers

A log message in your code using Log4Net all begins with the Logger class. The Logger is the portal into your code. While all of the five main objects can be configured from code, most often you will only need to use the Logger class. Because the LogManager class implements the ILog interface, there is a well-defined strong contract between Log4Net and your code. The ILog interface simply implements the following methods: Debug, Info, Warn, Error, and Fatal. The first set of methods corresponds to the available Levels covered in the next portion of the chapter. All of this makes logging in your program very simple, as shown in Listing 8.1.

Listing 8.1. A Simple Log4NET Log Message
_logger.Error("This is an error message.", exception);

Well, if using a Logger to log is so easy, then how is a Logger instantiated? A Logger is created one of two different ways. The first way to obtain a Logger is by passing in a string to associate with the Logger (see Listing 8.2).

Listing 8.2. Creating a Logger
Logger _logger = LogManager.GetLogger("MyLogger");

The second way to obtain a Logger is to associate the Logger to the type of the class, as in Listing 8.3. This way, once a Logger is instantiated, you are essentially linking that instance of the Logger with that class.

Listing 8.3. The Recommended Way of Getting a Logger
Logger _logger = LogManager.GetLogger(typeof(namespace.class));

Whatever messages are logged will be flagged as coming from this class. The reason for the functionality differences in Listing 8.2 and Listing 8.3 is found in Logger Hierarchy and inheritance.

Hierarchy

Loggers are by default hierarchical and based on a named hierarchy. This allows for powerful inheritance of Loggers and ease of use from multiple assemblies. Named hierarchy should be familiar to .NET developers because it is used in namespaces and fully qualified class names in .NET development. Listing 8.4 is an example of Loggers that are related in a parent-child relationship.

Listing 8.4. Hierarchical Loggers
Parent Logger LogManager.GetLogger(typeof(foo)); Child Logger LogManager.GetLogger(typeof(foo.bar));

If foo.bar is not assigned a Logging Level, it will inherit it from the parent Logger foo. Also, any log messages for foo.bar will be forwarded to any Appenders in foo.bar as well as up the hierarchy to foo's Appenders. Consequently, there is a Logger that exists as the base or root for all Loggers. This Logger always exists and cannot be retrieved by name. Therefore, you must use the getRootLogger static method of the Logger class to retrieve it. This functionality is due to the fact that every child Logger has a reference to its parent, but the parent Logger knows nothing about the child. Fortunately, this allows for child Loggers to be created before parent Logger, and the hierarchy will all work out in the end.

This inheritance and hierarchy functionality can be turned off via the additivity method on the Logger:

_logger.setAdditivity(false);

Alternatively, this functionality can be achieved by using the following code under the Logger section of the Log4Net config file:

<additivity value="false" />

Looking at this hierarchy from a different angle, Listing 8.5 shows two Loggers that refer to the exact same instance of a Logger object.

Listing 8.5. Identical Logger References
Logger a = LogManager.GetLogger(typeof(foo)); Logger b = LogManager.GetLogger(typeof(foo));

This greatly reduces the amount of code needed to use Log4Net by eliminating the need to pass around a reference to a particular instance of the object throughout all the code. This can be useful when using multiple assemblies and should be very useful for Partial Types in .NET 2.0.

LogManager

The LogManager class works with the Hierarchy class to manage all the Loggers for a given instance of Log4Net. LogManager allows for greater runtime control, as seen in Table 8.1.

Table 8.1. Helpful LogManager Methods

Method

Description

ILog [] GetCurrentLoggers()

Gets all the currently available Loggers

ILog [] GetCurrentLoggers(Assembly assembly)

Gets all the currently available Loggers for a given assembly

ILog GetLogger(string name)

Gets a Logger by name

ILog GetLogger(string domain, string name)

Gets a Logger by domain and name

ILog GetLogger(Assembly assembly, string name)

Gets a Logger by assembly and name

ILog GetLogger(Type type)

Gets a Logger by type

ILog GetLogger(string domain, Type type)

Gets a Logger by type for a given domain

ILog GetLogger(Assembly assembly, Type type)

Gets a Logger by type for a given assembly

ILog Exists(string name)

Checks if a Logger exists by name

ILog Exists(string domain, string name)

Checks if a Logger exists by name for a given domain

ResetConfiguration()

Defaults the configuration of all Loggers including the Appenders, Levels, and additivity flags

ResetConfiguration(string domain)

Resets the configuration based on domain

ResetConfiguration(Assembly assembly)

Resets the configuration based on the assembly

Shutdown()

Safely shuts down Log4Net

Using the static methods in Table 8.1 can allow your logging code to be very dynamic at runtime as well as give a great deal of information on the current status of your logging system.