Creating a basic logging wrapper for StreamInsight adapters/applications using log4net

Creating a basic logging wrapper for StreamInsight adapters/applications using log4net

  • Comments 2

There are many different ways of implementing logging on the Microsoft .NET platform (Trace, ETW, etc).  To provide for a range of flexibility (not necessary for this post.. just setting the stage) let’s go ahead and put together a generic logging interface that we’ll use throughout various applications (all of the code samples I post on this blog will use this approach).  Behind this interface we’ll deliver implementations that can target various logging frameworks such as Tracing, ETW, and in this case log4net.

  • Download the log4net binary package, and unpack the zip file onto your local hard drive.  The critical file is the log4net-1.2.10\bin\net\2.0\release\log4net.dll assembly.
  • From a Visual Studio 2010 command window (with Run as Administrator), navigate to the log4net directory and install the log4net.dll assembly into the GAC (gacutil /i log4net.dll).
  • Add the log4net.dll assembly into the project references.
  • Create a StreamInsightLog class based on the following code:
   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  using System.Diagnostics;
   6:  using log4net.Config;
   7:  using System.IO;
   8:   
   9:  namespace IntroHost
  10:  {
  11:      /// <summary>
  12:      /// StreamInsight log implementation leveraging log4net.
  13:      /// </summary>
  14:      public class StreamInsightLog
  15:      {
  16:          /// <summary>
  17:          /// Reference to the log4net logging object
  18:          /// </summary>
  19:          private readonly log4net.ILog log;
  20:   
  21:          /// <summary>
  22:          /// The category under which this object will log messages
  23:          /// </summary>
  24:          private string category;
  25:   
  26:          /// <summary>
  27:          /// Default initialization of the log4net library based on
  28:          /// entries in the app.config file.
  29:          /// </summary>
  30:          public static void Init()
  31:          {
  32:              XmlConfigurator.Configure();
  33:          }
  34:   
  35:          /// <summary>
  36:          /// Initialization of the log4net library based on a separate
  37:          /// configuration file.
  38:          /// </summary>
  39:          /// <param name="configFile"></param>
  40:          public static void Init(string configFile)
  41:          {
  42:              XmlConfigurator.ConfigureAndWatch(
  43:                  new FileInfo(configFile));
  44:          }
  45:   
  46:          /// <summary>
  47:          /// Initialize a StreamInsightLog object with the stated category
  48:          /// </summary>
  49:          /// <param name="category"></param>
  50:          public StreamInsightLog(string category)
  51:          {
  52:              this.log = log4net.LogManager.GetLogger(category);
  53:              this.category = category;
  54:          }
  55:   
  56:          /// <summary>
  57:          /// Log an exception to the ERROR log with the specified message
  58:          /// </summary>
  59:          public void LogException(Exception ex0, string fmt, params object[] vars)
  60:          {
  61:              log.Error(string.Format(fmt, vars), ex0);
  62:          }
  63:   
  64:          /// <summary>
  65:          /// Log a message of the specific log level
  66:          /// </summary>
  67:          public void LogMsg(TraceEventType type, string fmt, params object[] vars)
  68:          {
  69:              string message;
  70:   
  71:              if (vars.Any())
  72:                  message = String.Format(fmt, vars);
  73:              else
  74:                  message = fmt;
  75:   
  76:              switch (type)
  77:              {
  78:                  case TraceEventType.Verbose:
  79:                      log.Debug(message);
  80:                      break;
  81:   
  82:                  case TraceEventType.Information:
  83:                      log.Info(message);
  84:                      break;
  85:   
  86:                  case TraceEventType.Warning:
  87:                      log.Warn(message);
  88:                      break;
  89:   
  90:                  case TraceEventType.Error:
  91:                      log.Error(message);
  92:                      break;
  93:   
  94:                  case TraceEventType.Critical:
  95:                      log.Fatal(message);
  96:                      break;
  97:              }
  98:          }
  99:   
 100:          public void LogInfo(string fmt, params object[] vars)
 101:          {
 102:              log.InfoFormat(fmt, vars);
 103:          }
 104:   
 105:          public bool ShouldLog(TraceEventType type)
 106:          {
 107:              switch (type)
 108:              {
 109:                  case TraceEventType.Verbose:
 110:                      return log.IsDebugEnabled;
 111:   
 112:                  case TraceEventType.Information:
 113:                      return log.IsInfoEnabled;
 114:   
 115:                  case TraceEventType.Warning:
 116:                      return log.IsWarnEnabled;
 117:   
 118:                  case TraceEventType.Error:
 119:                      return log.IsErrorEnabled;
 120:   
 121:                  case TraceEventType.Critical:
 122:                      return log.IsFatalEnabled;
 123:   
 124:                  default:
 125:                      return false;
 126:              }
 127:          }
 128:      }
 129:  }

The logging interface is up and ready to go; in order to configure log4net (the underlying logging library), let’s create an appropriate app.config with this content, defining a:

  • Console appender (write out log records to the console)
  • File appender (write out log records to a file, commented out by default)
  • Two log categories (General and Adapter)

   1:  <?xml version="1.0" encoding="utf-8"?>
   2:  <configuration>
   3:    <configSections>
   4:      <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
   5:    </configSections>
   6:    <log4net>
   7:      <!-- Uncomment this block to log to files 
   8:      <appender name="ServiceLog" type="log4net.Appender.RollingFileAppender">
   9:        <file value="logs\StreamInsightHost.log" />
  10:        <appendToFile value="true" />
  11:        <maxSizeRollBackups value="10" />
  12:        <maximumFileSize value="50MB" />
  13:        <rollingStyle value="Size" />
  14:        <staticLogFileName value="true" />
  15:        <layout type="log4net.Layout.PatternLayout">
  16:          <header value="[Header]&#13;&#10;" />
  17:          <footer value="[Footer]&#13;&#10;" />
  18:          <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
  19:        </layout>
  20:      </appender>
  21:      -->
  22:      <!-- Log to the console -->
  23:      <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
  24:        <layout type="log4net.Layout.PatternLayout">
  25:          <conversionPattern value="%date %-5level - %message%newline" />
  26:        </layout>
  27:      </appender>
  28:      <root>
  29:        <!-- The master logging level; change to update all logging categories -->
  30:        <level value="INFO" />
  31:        <!-- Log to the console -->
  32:        <appender-ref ref="ConsoleAppender" />
  33:        <!-- Uncomment to log to file 
  34:        <appender-ref ref="ServiceLog" />      
  35:        -->
  36:      </root>
  37:      <!-- Levels are DEBUG, INFO, WARNING, ERROR and FATAL -->
  38:      <logger name="General">
  39:        <level value="INFO" />
  40:      </logger>
  41:      <logger name="Adapter">
  42:        <level value="DEBUG" />
  43:      </logger>    
  44:    </log4net>
  45:  </configuration>

 

  • In the Main.cs file, initialize the logging interface:

   1:  static void Main(string[] args)
   2:  {
   3:      StreamInsightLog.Init();
   4:  }

 We’re now set up for some logging and tracing.  On to actually building an adapter!

Leave a Comment
  • Please add 6 and 8 and type the answer here:
  • Post
  • Looks interesting, but just some words why do we need all this?

  • The main reason for this post was to explain the StreamInsightLog class that I'll refer to in future posts; it's not directly necessary, but a lot of my example code uses it for tracing.

Page 1 of 1 (2 items)