The Logging Handler

The logging handler provides the capability to write log messages and trace messages as the client code invokes the selected method or accesses the selected property of the target object. This handler uses the Logging Application Block, taking advantage of the wide range of log types, formatting, and tracing features that it provides.

The logging handler applies both before and after the invocation of the selected method or accessing the selected property of the target object, depending on settings in the application configuration.

Note

This call handler is implemented in Microsoft.Practices.EnterpriseLibrary.Logging.PolicyInjection namespace of the Logging Application Block in the assembly Microsoft.Practices.EnterpriseLibrary.Logging.dll.

The logging handler will initialize the Logging Application Block using the same configuration source as used to create the logging handler. By default, this will be the default configuration source. It is possible to specify an alternative configuration source if you instantiate the logging handler yourself using code. If you do this, you should create the configuration source once and use the same instance each time you create a logging handler to prevent performance issues and memory leaks.

Note

The Enterprise Library 5.0 Configuration tool does not support Environmental Overrides for the logging handler Categories. This means you will not be able to use the configuration tools at design time to customize the run-time settings of your logging handler Categories configuration to suit a particular environment such as a test or instrumentation environment.

Behavior of the Logging Handler

The logging handler does the following:

  • It uses the values of a list of properties that define the logging behavior.

  • It builds up an instance of the TraceLogEntry class, which inherits from LogEntry, and contains (in addition to the properties exposed by the LogEntry class) the following strongly-typed properties:

    • TypeName
    • MethodName
    • ReturnValue
    • CallStack
    • Exception
    • CallTime

    Note

    The values of parameters passed to the target member are available through the ExtendedProperties property of the LogEntry base class, which returns a populated Dictionary instance. You can optimize performance by configuring the properties the handler will collect information for and populate. Be aware that, because the properties in the preceding list are not available in the standard LogEntry class in the Logging Application Block, the default formatter templates will not display their values. You can use the {property} formatter token in the Log Formatter template to display these values—for example, {property(TypeName)}.

  • It sends the TraceLogEntry to the Logging Application Block before, after, or both before and after the method call, depending on the configuration settings.

  • If the configuration specifies logging after the method call and includes the option to log the call duration, the logging handler records the difference between the times when its preprocessing tasks and post-processing tasks occur, and it logs this along with any other configured values.

Creating Instances of the Logging Handler

When you use this call handler with the Unity interception mechanism, you must provide values for any mandatory parameters of its constructors, and optionally provide values for other parameters. If you configure the container with Enterprise Library's classes, then you want that configured LogWriter to be injected. If you are using an unconfigured container then you will need to get the facade's writer, which will belong to Enterprise Library's default container. If you want to inject the log writer from the container being configured, then you must provide it by using typeof(LogWriter) or new ResolvedParameter<LogWriter>() as the first element in the InjectionConstructor to specify that the constructor parameter is to be resolved The values provided are used to set the properties of the handler at run time. The constructors you can use are shown in the following code.

// Uses the default values. Gets the logWriter from the Logger.Writer facade method.
LogCallHandler()

LogCallHandler(LogWriter writer)

LogCallHandler(LogWriter writer, int eventId,
               bool logBeforeCall, bool logAfterCall, 
               string beforeMessage, string afterMessage,
               bool includeParameters, bool includeCallStack,
               bool includeCallTime, int priority)

LogCallHandler(LogWriter writer, int eventId,
               bool logBeforeCall, bool logAfterCall, 
               string beforeMessage, string afterMessage,
               bool includeParameters, bool includeCallStack,
               bool includeCallTime, int priority, int order)
'Usage
LogCallHandler()

LogCallHandler(writer As LogWriter)

LogCallHandler(writer As LogWriter, eventId As Integer, _
               logBeforeCall As Boolean, logAfterCall As Boolean, _
               beforeMessage As String, afterMessage As String, _
               includeParameters As Boolean, includeCallStack As Boolean, _
               includeCallTime As Boolean, priority As Integer)

LogCallHandler(writer As LogWriter, eventId As Integer, _
               logBeforeCall As Boolean, logAfterCall As Boolean, _
               beforeMessage As String, afterMessage As String, _
               includeParameters As Boolean, includeCallStack As Boolean, _
               includeCallTime As Boolean, priority As Integer, order As Integer)

The following table describes the values for the parameters shown above.

Property

Description

writer

LogWriter collection. The list of categories to which the logging handler will write events. Each category can be a literal value, and/or include the tokens {method}, {type}, {namespace}, and {assembly}.

eventId

Integer. The ID of the event to log.

logBeforeCall

Boolean. Whether to write a log entry before the call passes to the target object. Note that when this property is set to true in a LogCallHandler attribute, the LogAfterCall property is always also true.

logAfterCall

Boolean. Whether to write a log entry after the call returns from the target object. Note that this property is true when the LogBeforeCall property is set to true in a LogCallHandler attribute.

beforeMessage

String. The message that the Logging Handler will log before the target method executes.

afterMessage

String. The message that the Logging Handler will log after the target method executes.

includeParameters

Boolean. Whether to include the parameter values in the log message.

includeCallStack

Boolean. Whether to include the call stack in the log message.

includeCallTime

Boolean. Whether to include the call duration in the AfterMessage for the log entry.

priority

Integer. The priority value to include in the log message.

order

Integer. The position of the handler within the policy handler chain, starting from 1. The default value is zero, which means that there is no explicit order specified for the handler in relation to other handlers in the same handler chain.

The Logging Handler also exposes these values as the LogWriter, EventId, LogBeforeCall, LogAfterCall, BeforeMessage, AfterMessage, IncludeParameters, IncludeCallStack, IncludeCallTime, Priority, and Order properties. It also exposes the Categories property as a List of String values, and the Severity property as a value from the TraceEventType enumeration (such as Critical, Error, or Warning).

The following code extract shows how you can add a Logging Handler to a policy using the Unity type resolution and interception mechanisms. This example specifies that LogWriter is to be resolved by the container and it provides values for the LogCallHandler property values.

myContainer.Configure<Interception>()
           .AddPolicy("MyPolicy")
               .AddMatchingRule<TypeMatchingRule>(
                    new InjectionConstructor("My.Order.Object", true))
               .AddCallHandler<LogCallHandler>( 
                  new ContainerControlledLifetimeManager(),
                  new InjectionConstructor(
                      typeof(LogWriter), 
                      9000, true, true, 
                      "started", "finished", true, false, true, 1, 5
                      ));
'Usage
myContainer.Configure(Of Interception)() _
    .AddPolicy("MyPolicy") _
        .AddMatchingRule(Of TypeMatchingRule) _
            (New InjectionConstructor("My.Order.Object", True)) _
        .AddCallHandler(Of LogCallHandler) _
            (New ContainerControlledLifetimeManager(), _
                New InjectionConstructor(GetType(LogWriter), _
                9000, True, True, "started", "finished", _
                True, False, True, 1, 5))

Using the Logging Handler Attribute

Instead of configuring a call handler as part of a call hander pipeline, you force it to be applied by adding the appropriate attribute to your classes. The following code shows the use of the LogCallHandler attribute on a simple method. This attribute can also be applied to the class declaration, in which case it applies to all members of that class.

[LogCallHandler]
public void Deposit(decimal depositAmount)
{
  balance += depositAmount;
}
'Usage
<LogCallHandler> _
Public Sub Deposit(depositAmount As Decimal)
  balance += depositAmount
End Sub

The following table describes the properties of the LogCallHandlerAttribute class.

Property

Description

AfterMessage

String. The message that the logging handler will log after the target method executes.

BeforeMessage

String. The message that the logging handler will log before the target method executes.

Categories

String collection. The list of categories to which the logging handler will write events. Each category can be a literal value, and/or include the tokens {method}, {type}, {namespace}, and {assembly}.

EventId

Int. The event identifier to include in log entries.

IncludeCallStack

Boolean. Whether to include the call stack in the log message.

IncludeCallTime

Boolean. Whether to include the call duration in the AfterMessage for the log entry.

IncludeParameters

Boolean. Whether to include the parameter values in the log message.

LogAfterCall

Boolean. Whether to write a log entry after the call returns from the target object. Note that this property is true when the LogBeforeCall property is set to true in a LogCallHandler attribute.

LogBeforeCall

Boolean. Whether to write a log entry before the call passes to the target object. Note that, when this property is set to true in a LogCallHandler attribute, the LogAfterCall property is always also true.

Order

Integer. The position of the handler within the policy handler chain, starting from 1. The default value is zero, which means that there is no explicit order specified for the handler in relation to other handlers in the same handler chain.

Priority

Integer. The priority value to include in the log message.

Severity

The severity value of an exception to include in the log message, using values from the TraceEventType enumeration, such as Critical, Error, and Warning.

To set these properties using an attribute, add them as parameters to the attribute declaration, as shown in the following code.

[LogCallHandler(Categories=new string[]{"My Category"}, LogBeforeCall=true, 
         BeforeMessage="This occurs before the call to the target object")]
'Usage
<LogCallHandler(Categories:=New String(){"My Category"}, LogBeforeCall:=True, _
         BeforeMessage:="This occurs before the call to the target object")>

For more information about using call handler attributes and attribute driven policies, see Attribute-Driven Policies.