Wednesday, December 6, 2017

Real Time monitoring Windows Event Logs using Reactive Extensions

In this post, I want to demonstrate how I have used Reactive Extensions to monitor Windows Event Log entries as they get added to Event Logs by a specific provider.  The main piece that enables us to do this is Tx.All a single nuget package that exposes event log events as observables using Reactive Extensions. I will create two console projects, one for monitoring event logs and another to generate Event Logs.   

Part 1 – Monitoring Console App

Create a blank .NET console project (do not select .NET core).  Then Install Tx.All Nuget Package and your packages.config file should look as shown below.


<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="System.Reactive" version="3.1.1" targetFramework="net47" />
  <package id="System.Reactive.Core" version="3.1.1" targetFramework="net47" />
  <package id="System.Reactive.Interfaces" version="3.1.1" targetFramework="net47" />
  <package id="System.Reactive.Linq" version="3.1.1" targetFramework="net47" />
  <package id="System.Reactive.PlatformServices" version="3.1.1" targetFramework="net47" />
  <package id="System.Reactive.Windows.Threading" version="3.1.1" targetFramework="net47" />
  <package id="Tx.All" version="2.1.1" targetFramework="net47" />
  <package id="Tx.Core" version="2.1.1" targetFramework="net47" />
  <package id="Tx.SqlServer" version="2.1.1" targetFramework="net47" />
  <package id="Tx.Windows" version="2.1.1" targetFramework="net47" />
  <package id="Tx.Windows.TypeGeneration" version="2.1.1" targetFramework="net47" />
</packages>

Then use the following code to query specific provider inside Event Log. We are interested into Application event logs and our provider is ConsoleEventLogGenerator.

using System;
using System.Collections.Generic;
using System.Diagnostics.Eventing.Reader;
using System.Linq;
using System.Reactive.Linq;
using System.Text;
using System.Threading.Tasks;
using Tx.Windows;

namespace ConsoleMonitor
{
    class Program
    {
        static void Main(string[] args)
        {
            IObservable<EventRecord> evtx = EvtxObservable.FromLog("Application");
            IDisposable d = evtx.Where(y => y.ProviderName == "ConsoleEventLogGenerator").Subscribe(e => {
                Console.WriteLine(e.FormatDescription());
            });

            Console.WriteLine("Waiting for Event Log entry for provider - \"ConsoleEventLogGenerator\"");
            Console.Read();
        }
    }
}

Now we will create another console project to create event in the Event Log. 

Part 2 – Create another Console Project.

In the following code we are creating lots of events log entries and our source is ConsoleEventLogGenerator. This string has to match the string shown in the earlier section.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleEventLogGenerator
{
    class Program
    {
        static void Main(string[] args)
        {
            EventLog log = new EventLog("Application");
            log.Source = "ConsoleEventLogGenerator";

            for (int i = 0; i < 100; i++)
            {
                Thread.Sleep(1000);
                log.WriteEntry("test " + i);
            }
        }
    }
}

In the next section you will fire up both the application side by side and you will see events showing up in real time.

image

I have created a simple console app like this to monitor event log when I am debugging a certain application that writes everything to event log.  Seeing output in real time helps a lot in debugging.