OData to the rescue. Exposing the eventlog as a data feed
Posted
by cibrax
on ASP.net Weblogs
See other posts from ASP.net Weblogs
or by cibrax
Published on Mon, 15 Mar 2010 13:06:00 GMT
Indexed on
2010/03/15
13:10 UTC
Read the original article
Hit count: 606
.NET
|ADO.NET Data Services
In one of the project where I was working one, we used the Microsoft Enterprise Library Exception Application Block integration with WCF for logging all the technical issues on the services/backend in Windows Event Log. This application block worked like a charm, all the errors were correctly logged on the Event Log without even needing to modify the service code. However, we also needed to provide a quick way to expose all those events to the different system users so they could get access to all the them remotely. In just a couple of minutes I came up with a simple solution based on ADO.NET Data Services. ADO.NET data services is very powerful in this sense, you only need to provide a IQueryable implementation, and that’s all. You get a RESTful service with rich query support for free.
In this sample, I used Linq to Objects to get the latest entries from the Event Log, and I also filter the entries by the category used by the Application Block to avoid loading unnecessary entries in memory.
public class LogDataSource
{
string source;
public LogDataSource(string source)
{
this.source = source;
}
public LogDataSource()
{
}
public IQueryable<LogEntry> LogEntries
{
get { return GetEntries().AsQueryable().OrderBy(e => e.TimeGenerated); }
}
private IEnumerable<LogEntry> GetEntries()
{
var applicationLog = System.Diagnostics.EventLog.GetEventLogs().Where(e => e.Log == "Application")
.FirstOrDefault();
var entries = new List<LogEntry>();
if (applicationLog != null)
{
foreach (EventLogEntry entry in applicationLog.Entries)
{
if (source == null || entry.Source.Equals(source, StringComparison.InvariantCultureIgnoreCase))
{
entries.Add(new LogEntry
{
Category = entry.Category,
EventID = entry.InstanceId,
Message = entry.Message,
TimeGenerated = entry.TimeGenerated,
Source = entry.Source,
});
}
}
}
return entries.OrderByDescending(e => e.TimeGenerated)
.Take(200);
}
}
LogEntry is class I created for this service to expose an Event Log Entry.
[EntityPropertyMappingAttribute("Source",
SyndicationItemProperty.Title,
SyndicationTextContentKind.Plaintext, true)]
[EntityPropertyMapping("Message",
SyndicationItemProperty.Summary,
SyndicationTextContentKind.Plaintext, true)]
[EntityPropertyMapping("TimeGenerated",
SyndicationItemProperty.Updated,
SyndicationTextContentKind.Plaintext, true)]
[DataServiceKey("EventID")]
public class LogEntry
{
public long EventID
{
get;
set;
}
public string Category
{
get;
set;
}
public string Message
{
get;
set;
}
public DateTime TimeGenerated
{
get;
set;
}
public string Source
{
get;
set;
}
}
As you can see, I used the new feature “Friendly feeds” to map several properties in the entries with standard ATOM elements. The “DataServiceKey” is only necessary because I am using the Reflection Provider (the exposed IQueryable implementation is just Linq to Objects) rather than the default Entity Framework Provider.
The data service implementation is also quite simple, just a couple of lines were needed to expose the data source created previously.
public class LogDataService : DataService<LogDataSource>
{
public static void InitializeService(IDataServiceConfiguration config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
}
protected override LogDataSource CreateDataSource()
{
string source = ConfigurationManager.AppSettings["EventLogSource"];
if (source == null)
{
throw new ApplicationException("The EventLogSource appsetting is missing in the configuration file");
}
return new LogDataSource(source);
}
}
With this implementation in place, the final users not only get a feed with all the latest errors in the event log, but also support for performing queries against that data. This is one of the great things about ADO.NET Data services.
© ASP.net Weblogs or respective owner