Enterprise Library’s Logger is powerful and convenient. It’s default TextFormatter provides a suitable human readable format, and it also allows you to implement custom formatters to suite your needs. I think that being able to work with log data without having to manually parse strings, can really simplify the development of tools for mining logs. To this end, I whipped up a small WinForms app that demonstrates how to take log entries originating from a text spool, convert them into objects, and query them with Linq. The primary goal was to provide simple UI that enables log search, filter, and find, with sorting, grouping, etc.
First off, the heavy lifting in this sample is provided by the EntLib Contrib LogParser. Their FilteredLogReader class drives a tokenizer, which creates and populates LogEntry objects out of log text. The tokenizer will use any formatting template, in our case, I’ve used the built in “Text Formatter”. When it executes, it generates a RegularExpression capable of matching and trapping the values involved in populating our collection of LogEntry objects. Ultimately, we are provided with a simple API for driving all of this. Here’s a brief sample:
string configFile = "abc.config";
string traceLog = "trace.log";
FilteredLogFileReader reader =
new FilteredLogFileReader(traceLog, configFile,
Filter filter = new Filter
StartTime = DateTime.Now.AddHours(-1),
StopTime = DateTime.Now
IEnumerable<LogEntry> entries = reader.ParseLogFile(filter);
The basic idiom here is:
1. Get a FilteredLogFileReader
2. Setup a Filter
3. Feed the filter to the reader’s ParseLogFile
To facilitate a flexible set of filtering concepts at the UI, I decided to use a simple FilterExpression class to represent a set of keys, values, and match operators. Here’s a quick way to get the intersection result set from applying a set of filters with a single pass through the logs.
private IList<LogEntry> FilterLogEntries(List<LogEntry> lst,
var matchAllExprs = new List<LogEntry>();
List<PropertyInfo> props = typeof(LogEntry).GetProperties().ToList();
int matchCount = 0;
string value = props.Find(prop => prop.Name.Equals(expr.Key))
case "regex match":
if (new Regex(expr.Value).IsMatch(value))
throw new Exception("operator not found");
if (exprs.Count == matchCount)
If any of the LogEntries match all of the expressions, then those are returned to the caller. Now we can place the log data onto our screen for users.
The sample app that I’ve included, gives users the ability to create, configure, and apply FilterExpressions on the fly. Here’s a screenshot.
You can get the source for this sample here. Enjoy..