Creating a basic logging wrapper for StreamInsight adapters/applications using log4net
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] " />
17: <footer value="[Footer] " />
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!