Monday, April 16, 2012

Use MS practices enterprise library logger in Sharepoint timer jobs

If you work with server technologies and applications you know how important to have reliable logging system which will allow to monitor work and find problems if something went wrong. Sharepoint is not exception. It has flexible ULS (unified logging service) with many configuration options (I recommend to use convenient tool for reading Sharepoint logs: ULS Viewer. It allows to filter events of different types and displays critical errors with red color which will attract your attention faster).

Sometimes ULS is not enough however. You may need to use Windows event viewer as reserve logging system – e.g. write all errors and warnings both to ULS and to event log, while information messages can be written only to ULS. In event log errors are displayed more expressively so you will find it faster). In order to work with event viewer you may use logger from Microsoft Enterprise Library. It contains convenient wrappers and allows to write messages to the Windows event log like this:

   1: LogEntry entry = new LogEntry();
   2: entry.Severity = TraceEventType.Error;
   3: entry.Message = msg;
   4: Logger.Write(entry);

In order to use Enterprise library logger you need to configure it first. Configuration is added to the config file and looks like this (I divided some rows on several lines in order to keep it within width of my blog layout. In the real config you should remove line breaks):

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <configuration>
   3:   <configSections>
   4:     <section name="loggingConfiguration"
   5: type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings,
   6: Microsoft.Practices.EnterpriseLibrary.Logging,
   7: Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
   8:   </configSections>
   9:   <loggingConfiguration name="Logging Application Block" tracingEnabled="true"
  10: defaultCategory="General" logWarningsWhenNoCategoriesMatch="true">
  11:     <listeners>
  12:       <add source="My source" formatter="Text Formatter" log="Application" machineName=""
  13: listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData,
  14: Microsoft.Practices.EnterpriseLibrary.Logging, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
  15: traceOutputOptions="None" filter="All"
  16: type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener,
  17: Microsoft.Practices.EnterpriseLibrary.Logging, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
  18: name="Formatted EventLog TraceListener" />
  19:     </listeners>
  20:     <formatters>
  21:       <add template="Timestamp: {timestamp}&#xD;&#xA;Message: {message}&#xD;&#xA;
  22: Category: {category}&#xD;&#xA;Priority: {priority}&#xD;&#xA;EventId: {eventid}&#xD;&#xA;
  23: Severity: {severity}&#xD;&#xA;Title:{title}&#xD;&#xA;Machine: {machine}&#xD;&#xA;
  24: Application Domain: {appDomain}&#xD;&#xA;Process Id: {processId}&#xD;&#xA;
  25: Process Name: {processName}&#xD;&#xA;Win32 Thread Id: {win32ThreadId}&#xD;&#xA;
  26: Thread Name: {threadName}&#xD;&#xA;Extended Properties: {dictionary({key} - {value}&#xD;&#xA;)}"
  27: type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter,
  28: Microsoft.Practices.EnterpriseLibrary.Logging, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
  29: name="Text Formatter" />
  30:     </formatters>
  31:     <categorySources>
  32:       <add switchValue="All" name="General">
  33:         <listeners>
  34:           <add name="Formatted EventLog TraceListener" />
  35:         </listeners>
  36:       </add>
  37:     </categorySources>
  38:     <specialSources>
  39:       <allEvents switchValue="All" name="All Events" />
  40:       <notProcessed switchValue="All" name="Unprocessed Category" />
  41:       <errors switchValue="All" name="Logging Errors &amp; Warnings">
  42:         <listeners>
  43:           <add name="Formatted EventLog TraceListener" />
  44:         </listeners>
  45:       </errors>
  46:     </specialSources>
  47:   </loggingConfiguration>
  48: </configuration>

This configuration sections should be added to the web.config of the Sharepoint site. After that you will be able to write messages to the Windows event log from the context of the site (e.g. in codebehind of application layouts pages, user control or web part).

But what if you need to write messages to event log also from Sharepoint timer job? Is it possible to configure it by the same way? The answer is yes. As you probably know job is executed in the separate process (Sharepoint timer service). Executable owstimer.exe is located in 14/bin folder (12/bin in case of Sharepoint 2007). So in order to MS Enterprise library logger you have to create owstimer.exe.config file (or modify it if it is already exists) and add configuration to it like shown above. After that restart Sharepoint timer service from Administration > Services and run your job. You will see that it now writes messages to the Windows event log.

No comments:

Post a Comment