Implementing Diagnostic Logging and Tracing in Your Application

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

The latest Enterprise Library information can be found at the Enterprise Library site.

patterns & practices Developer Center

On this page:
Using the Remote Service Trace Listener - Adding the Log Service to Your Web Server, Configuring the Logging Application Block on the Server, Configuring the WCF Binding in the Silverlight Application, Configure the Logging Application Block to Use the Remote Service Trace Listener, Using a LogServiceFactory to Configure the WCF Binding Programmatically, Customizing the Log Service by Creating A Derived Class | Using the Isolated Storage Trace Listener - Configuring the Isolated Storage Trace Listener, Reading the Log Messages from Isolated Storage | Using the Notification Trace Listener - Configure the Notification Trace Listener, Respond to the Notification Event | Changing the Logging Levels in the Application - Turning Logging On Or Off, Changing the Logging Level for a Trace Source, Adding a Trace Listener to a Trace Source, Changing the Remote Service Trace Listener, Changing the Isolated Storage Trace Listener | More Information

The basics for implementing logging and tracing in your application are already described in detail in the Enterprise Library documentation on MSDN and in the Developer's Guide.

In this chapter, we'll discuss how you can implement the Silverlight-specific scenarios, such as using the Remote Service trace listener in your application.

Using the Remote Service Trace Listener

In this section, we'll describe how you can log messages to a remote service. To complete these steps, you will need a web application project that will host the WCF service. This can be the same web application that hosts the Silverlight application. You will also need a Silverlight application. These projects do not need to be together in the same solution.

When you want to use the Remote Service trace listener, you should perform the following steps:

  1. Add the log service to your web server
  2. Configure the Logging Application Block on the web server
  3. Configure the WCF binding in the Silverlight application
  4. Configure the Logging Application Block to use the Remote Service trace listener

These steps are described in more detail in the following paragraphs.

Adding the Log Service to Your Web Server

First, you will need to add the required references to your web application:

  • Microsoft.Practices.EnterpriseLibrary.Common.dll
  • Microsoft.Practices.EnterpriseLibrary.Logging.dll
  • Microsoft.Practices.EnterpriseLibrary.Logging.Service.dll

Then you will need to create the endpoint by adding the LogService.svc file to your solution. You can also use a different name for this file, but this name defines the URL used to access the service. This should be the contents of the LogService.SVC file:

<%@ ServiceHost Language="C#" Debug="true" Service="Microsoft.Practices.EnterpriseLibrary.Logging.Service.LoggingService" %>

This creates an endpoint that uses the LoggingService class that is located in the Microsoft.Practices.EnterpriseLibrary.Logging.Service assembly. If you wish to use a different implementation for the logging service, then you should change the Service property accordingly.

Then you will need to configure the binding to use for this service in the web.config file. The following example shows how you can set up a binding for this service that uses binary message encoding and HTTP for transport.

<configuration>
  <system.serviceModel>
    <bindings>
        <binding name=
          "Microsoft.Practices.EnterpriseLibrary.Logging.Service.customBinding0">
          <binaryMessageEncoding />
          <httpTransport />
        </binding>
      
    </bindings>
    <services>
      <service name="Microsoft.Practices.EnterpriseLibrary.Logging.Service.LoggingService">
        <endpoint address="" binding="customBinding" bindingConfiguration="Microsoft.Practices.EnterpriseLibrary.Logging.Service.customBinding0"
         contract="Microsoft.Practices.EnterpriseLibrary.Logging.Service.ILoggingService" />
      </service>
    </services>
  </system.serviceModel >
</configuration>

You can use any binding that is supported by Silverlight, but keep in mind that both the server and the client need to be configured the same way. This page on MSDN describes all the available bindings you can use in Silverlight.

Note

Forbrevity, this sample doesn't use any form of message or transport security, so it is possible to intercept or tamper with the log messages. If you are planning to log sensitive information, consider using message or transport security. Also consider storing the log messages in a secure location.

Configuring the Logging Application Block on the Server

The Logging Service will use the Logging Application Block on the web server to process the log messages from the Silverlight client. You will need to configure the Logging Application Block to handle the log messages appropriately.

The following example shows how you can configure the Logging Application Block in the web.config file to send all the log messages to the Windows Event Log:

<configuration>
  <configSections>
    <section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
  </configSections>
  <loggingConfiguration name="" tracingEnabled="true" defaultCategory="General">
    <listeners>
      <add name="Event Log Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging"
        listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging"
        source="Enterprise Library Logging" formatter="Text Formatter"
        log="" machineName="." traceOutputOptions="None" />
    </listeners>
    <formatters>
      <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging"
        template="Timestamp: {timestamp}{newline}&#xA;Message: {message}{newline}&#xA;Category: {category}{newline}&#xA;Priority: {priority}{newline}&#xA;EventId: {eventid}{newline}&#xA;Severity: {severity}{newline}&#xA;Title:{title}{newline}&#xA;Machine: {localMachine}{newline}&#xA;App Domain: {localAppDomain}{newline}&#xA;ProcessId: {localProcessId}{newline}&#xA;Process Name: {localProcessName}{newline}&#xA;Thread Name: {threadName}{newline}&#xA;Win32 ThreadId:{win32ThreadId}{newline}&#xA;Extended Properties: {dictionary({key} - {value}{newline})}"
        name="Text Formatter" />
    </formatters>
    <categorySources>
      <add switchValue="All" name="General" />
    </categorySources>
    <specialSources>
      <allEvents switchValue="All" name="All Events">
        <listeners>
          <add name="Event Log Listener" />
        </listeners>
      </allEvents>
    </specialSources>
  </loggingConfiguration>
</configuration>

For more information on how to configure the Logging Application Block, please refer to the chapter on Configuring the Logging Application Block on MSDN or the Developer's Guide.

Configuring the WCF Binding in the Silverlight Application

Now that the server is configured, we will also need to configure the WCF binding on the client. To do this, you will need to add an XML file called ServiceReferences.ClientConfig to your web application. Set the build action for this file to "Content," so that it ends up in the XAP file for your application.

In the ServiceReferences.ClientConfig file, you will configure what binding the Logging Service should use. The following is an example of a ServiceReferences.ClientConfig file:

<configuration>
  <system.serviceModel>
    <bindings>
      <customBinding>
        <binding name="CustomBinding_ILoggingService">
          <binaryMessageEncoding />
          <httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
        </binding>
      </customBinding>
    </bindings>
    <client>
      <endpoint address="/LoggingService.svc"
          binding="customBinding" bindingConfiguration="CustomBinding_ILoggingService"
          contract="Microsoft.Practices.EnterpriseLibrary.Logging.Service.ILoggingService" name="CustomBinding_ILoggingService" />
    </client>
  </system.serviceModel>
</configuration>

The binding configuration in this file should match the binding configuration for the server. In this case, we're using binaryMessageEncoding over HTTP.

A couple of things are very important in this file:

  • The address property on the endpoint element refers to the location where your service endpoint is located. In this case, it assumes that the service endpoint is located on the same server where the XAP file was deployed. If the logging service is located in a different location, of if you have given your SVC file a different name, you should change this URL.
  • The name property on the endpoint element will be used in the next step, where we're configuring the Logging Application Block to use the Remote Service trace listener.

For more information on creating ServiceReference.ClientConfig files, please refer to the following page on MSDN.

Configure the Logging Application Block to Use the Remote Service Trace Listener

Now we'll create a XAML configuration file that will send all events to the Remote Service trace listener.

  1. Open the Enterprise Library configuration console.

  2. Select **Blocks -> Add Logging Settings for Silverlight
    **This automatically adds a Remote Service trace listener to the configuration.

    Hh852699.9D2109C4FFC60DF9D180096C8F6273A5(en-us,PandP.51).png

  3. Open the All Events special category and click the plus sign (+) to add the Remote Service trace listener.

    Hh852699.9568F51A83E78239AD14D7FEA7C20836(en-us,PandP.51).png

  4. Open the Remote Service trace listener and set the value of the Logging Service Factory property to the name of the binding that was configured in the previous step. In this example, this is CustomBinding_IloggingService.

  5. Select Wizards -> Export to XAML. Browse to the root of your Silverlight project and save the file there under the name Configuration.xaml.

    Follow link to expand image

  6. Add the Configuration.xaml file to your Silverlight application project and set the build action to Resource or Page in the file properties.

Your Silverlight application is now configured to send all log messages to the Remote Service trace listener. On the server, all the log messages from the Silverlight client will be written to the Windows Event Log.

Using a LogServiceFactory to Configure the WCF Binding Programmatically

Instead of using a ServiceReferences.ClientConfig file and specifying the name of the binding in the configuration.xaml file, you can also configure the binding for the Logging Service programmatically. You will do this by specifying a custom Logging Service Factory for the Remote Service trace listener.

Note

You can only configure a custom Logging Service Factory in code or a XAML configuration file. You cannot select a LogServiceFactory using the configuration console, nor can you set it in an application configuration file and export it to a XAML configuration file.

You will first need to create a custom LoggingServiceFactory that creates the channel programmatically. The following example shows how to create a custom Logging Service Factory that sets up the binding to use Binary Message Encoding and Transport over HTTP.

Customizing the Log Service by Creating A Derived Class

If you wish to customize the Logging Service, for example to add additional information to the log messages, then you can create a class that derives from the Logging Service. By overriding the CollectInformation method, you can add additional information to the log message. For example, you can add the IP address of the caller to the log message.

The following example shows an example of an extended logging service.

public class ExtendedLoggingService : LoggingService
{
    protected override void CollectInformation(Microsoft.Practices.EnterpriseLibrary.Logging.LogEntry entry)
    {
        // Get the user IP address and add it as an extended property. 
        // NOTE. This information can easily be spoofed by the caller. Use this information only
        // for diagnostic purposes, not for authentication or auditing purposes. 
        var messageProperties = OperationContext.Current.IncomingMessageProperties;
        var endpoint = messageProperties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
        string clientAddress = endpoint != null ? endpoint.Address : string.Empty;

        entry.ExtendedProperties.Add("ClientIPAddress", clientAddress);

        // Also add the client host address as a category. This allows you to turn on server side logging for a single client
        if (!string.IsNullOrEmpty(clientAddress))
        {
            entry.Categories.Add(clientAddress);
        }

        base.CollectInformation(entry);
    }
}

To use this, you will need to update the LoggingService.svc file to point to the new extended service:

<%@ ServiceHost Language="C#" Debug="true" Service="StockTraderRI.Logging.ExtendedLoggingService" %>

And you will need to update the web.config to also use the Extended Logging Service:

<service name="StockTraderRI.Logging.ExtendedLoggingService">
    <endpoint address="" binding="customBinding" bindingConfiguration="Microsoft.Practices.EnterpriseLibrary.Logging.Service.customBinding0"
      contract="Microsoft.Practices.EnterpriseLibrary.Logging.Service.ILoggingService" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>

Using the Isolated Storage Trace Listener

In this section, we'll describe the steps you should take to log all messages to the Isolated Storage trace listener. We'll also describe how you can read the written log messages.

Configuring the Isolated Storage Trace Listener

  1. Open the Enterprise Library configuration console.

  2. Select Blocks -> Add Logging Settings for Silverlight

    Hh852699.9D2109C4FFC60DF9D180096C8F6273A5(en-us,PandP.51).png

  3. Add the Isolated Storage trace listener.

    Follow link to expand image

  4. Specify the name of the repository. This name is used to create a file on the file system, but also to retrieve the log messages again using the IsolatedStorageLogEntryRepository.

    Hh852699.70B910E8D6FA6B192D6527A7C48295E4(en-us,PandP.51).png

  5. Configure the All Events Trace Source to use the Isolated Storage trace listener.

    Follow link to expand image

  6. Select Wizards -> Export to XAML. Browse to your Silverlight project and save it with the name Configuration.xaml.

    Follow link to expand image

  7. Add the Configuration.xaml file to your Silverlight application project and set the build action to Resource or Page in the file properties.

Reading the Log Messages from Isolated Storage

You can use the Isolated Storage Log Entry Repository to retrieve log messages that were written to isolated storage. You will need to provide the name of the repository that was specified in configuration.

You can use the following code example to read all log messages that are present in isolated storage:

public IEnumerable<LogEntry> GetLogMessages()
{
    // Get the Isolated Storage Log Repository. The Name used here should
    // correspond to the repository name specified in configuration
    IsolatedStorageLogEntryRepository repository = EnterpriseLibraryContainer.Current.GetInstance<IsolatedStorageLogEntryRepository>("Logname");

    return repository.RetrieveEntries();
}

Using the Notification Trace Listener

In this section, we'll discuss how you can use the Notification trace listener so you can respond to an event every time a log message is written.

Configure the Notification Trace Listener

  1. Open the Enterprise Library configuration console.

  2. Select Blocks -> Add Logging Settings for Silverlight

    Hh852699.9D2109C4FFC60DF9D180096C8F6273A5(en-us,PandP.51).png

  3. Add the Notification trace listener.

    Follow link to expand image

  4. Configure the All Events Special Trace Source to use the Notification trace listener.

    Follow link to expand image

  5. Select Wizards -> Export to XAML. Browse to your Silverlight project and save it with the name "Configuration.xaml."

    Follow link to expand image

  6. Add the configuration.xaml file to your Silverlight application project and set the build action to Resource or Page in the file properties.

Respond to the Notification Event

To respond to the event when a new log message is written, you will need to get an instance of the ITraceDispatcher and register an event handler to the TraceReceived event. The following example shows how this works:

public void StartMonitoringForNewLogMessages()
{
    var dispatcher = EnterpriseLibraryContainer.Current.GetInstance<ITraceDispatcher>();
    dispatcher.TraceReceived += dispatcher_TraceReceived;
}

void dispatcher_TraceReceived(object sender, TraceReceivedEventArgs e)
{
    // A log entry was received. Handle it as appropriate:
    LogEntry logEntry = e.Data as LogEntry;
}

Changing the Logging Levels in the Application

Using the Change API, you can make run-time changes to the Logging Block. To make any changes, you will need to call the GetUpdateContext method on the LogWriter class to get an ILogWriterUpdateContext instance. You can use this instance to change the logging settings. The changes you make will be activated when you call ApplyChanges().

Turning Logging On Or Off

The following code demonstrates how you can turn logging on, if it was disabled in configuration:

public static void TurnLoggingOn()
{
    LogWriter logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
    ILogWriterUpdateContext updateContext = logWriter.GetUpdateContext();

    updateContext.IsLoggingEnabled = true;
    updateContext.ApplyChanges();
}

Changing the Logging Level for a Trace Source

The following code sample demonstrates how you can increase or decrease the logging level for a particular trace source. For example, if your trace source is configured to log only messages with a severity of Error or greater, then you can use this sample to change that setting to Warning or greater.

public static void IncreaseTraceLevel()
{
    LogWriter logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
    ILogWriterUpdateContext updateContext = logWriter.GetUpdateContext();

    // This will update the special trace sources
    updateContext.AllEventsCategory.Level = SourceLevels.Warning;
    updateContext.ErrorsCategory.Level = SourceLevels.Warning;

    // This will update a custom category, with the name "Custom"
    updateContext.Categories.First(c => c.Name == "Custom").Level = SourceLevels.Warning;
    
    updateContext.ApplyChanges(); ;
}

Adding a Trace Listener to a Trace Source

The following code sample demonstrates how you can add a trace listener to a trace source.

public static void AddTraceListener()
{
    LogWriter logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
    ILogWriterUpdateContext updateContext = logWriter.GetUpdateContext();

    // Add a trace listener with the name "Service" 
    updateContext.AllEventsCategory.Listeners.Add("Service");

    // This will update a custom category with the name "Custom" to add the trace listener
    updateContext.Categories.First(c => c.Name == "Custom").Listeners.Add("Service");

    updateContext.ApplyChanges();
 
}

Note

The trace listener you are trying to add must already be used by another trace source. You cannot add new trace listeners or use trace listeners that have been configured but are not used by any trace sources.

Changing the Remote Service Trace Listener

The following code sample demonstrates how you can make run-time changes to the Remote Service Trace Listener. In this sample, we're enabling buffering and increasing the size of the isolated storage buffer to 512 Kb:

public static void ChangeRemoteServiceTraceListener()
{
    LogWriter logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
    ILogWriterUpdateContext updateContext = logWriter.GetUpdateContext();

    // Get the update context for the trace listener
    var listener = 
        updateContext.Listeners
                     .OfType<IRemoteServiceTraceListenerUpdateContext>()
                     .FirstOrDefault();
    if (null != listener) 
    {
        // Set the size of the isolated storage buffer and enable buffering
        listener.IsolatedStorageBufferMaxSizeInKilobytes = 512;
        listener.SendImmediately = false;

        updateContext.ApplyChanges();
    }
}

Changing the Isolated Storage Trace Listener

The following code sample demonstrates how you can change the size of the Isolated Storage Log at run time. You should test if the repository is actually available. If there is more than one instance of your application running, then only a single instance can change the repository:

public static void ChangeIsolatedStorageTraceListener()
{
    LogWriter logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
    ILogWriterUpdateContext updateContext = logWriter.GetUpdateContext();

    // Get the update context for trace listener
    var listener = updateContext.Listeners.First(l => l.Name == "Isolated Storage Trace Listener")
        as IIsolatedStorageTraceListenerUpdateContext;

    // You should test if the repository is available. If you have multiple
    // instances of your application running at the same time, then
    // only a single instance can update the size of the repository
    if (listener.IsRepositoryAvailable)
    {
        // Change the size of the isolated storage trace listener to 5 kb
        listener.MaxSizeInKilobytes = 512;
    }

    updateContext.ApplyChanges();
}

More Information

In this chapter, we discussed how you can apply the Logging Application Block to a Silverlight application. To learn more about the Logging Application Block, please read the chapter on the Logging Application Block on MSDN and in the Developer's Guide.

Next Topic | Previous Topic | Home

Last built: July 8, 2011