Announcing the EventSource NuGet Package – Write to the Windows Event Log

Announcing the EventSource NuGet Package – Write to the Windows Event Log

Rate This
  • Comments 52

We are announcing the EventSource NuGet package, which enables fast app tracing to the Windows Event Log, including in production. This post was written by Cosmin Radu, a software developer on the .NET Runtime team

We know that you want to build high-quality software. That can be a challenging task if your desktop or web app interacts with users in complex ways or reads unstructured input, as examples. An important quality tool is instrumentation, which makes diagnosing functionality and performance problems much easier.

Starting with the .NET Framework 4.5, you can use the System.Diagnostics.Tracing.EventSource class to add efficient, strongly typed events into your code. With those events in place, you can use a listener to record events, to a text file, for example. In this release, we have extended this API to enable you to write your EventSource events directly to the Windows Event Log. This feature works for processes running with either admin or user credentials.

The screenshot below illustrates the feature. We defined an EventSource named ‘Samples-EventSourceDemos-EventLog’, and marked some of its events with the ‘Channel=EventChannel.Admin’ property. That declaration tells the system that we wish those events to go to the windows event log, and this screenshot shows us inspecting the data in one of the events in the windows event viewer.

clip_image002

This release is a beta of Microsoft.Diagnostics.Tracing.EventSource Nuget Package. This package works on .NET Framework 4 and above. You may notice that we have adopted the Microsoft namespace instead of the System one to avoid collision. If you are already use EventSource, in the System namespace and want to take advantage of this new feature, we recommend that you switch your ‘using’ statements for your app to Microsoft.Diagnostics.Tracing.

Along with the EventSource NuGet package we have provided an EventSource samples NuGet package. We thought that NuGet could be a good way to deliver sample code, too, so we are trying that approach with this release.

How does this relate to ETW?

The EventSource class is integrated with the Event Tracing for Windows (ETW) subsystem. ETW includes a feature called ETW channels, which allows you to direct your ETW events to the Windows Event Log, without you needing to know anything about how to interact with event log APIs. This release builds on top of ETW channels, enabling you take advantage of that feature from EventSource, in your .NET code.

Review: Basic EventSource Usage

There are a number of good references for EventSource that I recommend: the MSDN documentation as well as some great blog entries by Vance Morrison.

Let’s dive right in with an example. A custom event source type definition will generally follow a simple pattern (outlined below): 

    [EventSource(Name = "Samples-EventSourceDemos-Minimal")]
    public sealed class MinimalEventSource : EventSource
    {
        // Define singleton instance
        public static MinimalEventSource Log = new MinimalEventSource();

        // Define Event methods
        public void Load(long baseAddress, string imageName)
        {
            WriteEvent(1, baseAddress, imageName);
        }
    }

The above definition enables your code to call MinimalEventSource.Log.Load() to fire ETW events. These events can be observed by either an ETW listener (generally out of process) or an in-process, user defined EventListener. You can already do this with the .NET Framework 4.5.

Sending Events to the Windows Event Log

Event log support is a new feature provided with this NuGet package. It enables you to specify one additional destination for EventSource events – an application-defined event log. That means that all of your events will show up in a part of the event log that is specific to your app.

In the screenshot below, you will see an area highlighted. That’s the part of the event log that our demo code writes to -- “Samples\EventSourceDemos\EventLog” – and yours would be similar. Your app events might show up under a node such as: “MyCompany\MyApp”.

image

The following is an example of an ETW event definition that takes advantage of this new feature.  

    [EventSource(Name = "Samples-EventSourceDemos-EventLog")]
    public sealed class MinimalEventSource : EventSource
    {
        public static MinimalEventSource Log = new MinimalEventSource();

        [Event(1, Message = "{0} -> {1}", Channel = EventChannel.Admin)]
        public void Load(long baseAddress, string imageName)
        {
            WriteEvent(1, baseAddress, imageName);
        }
    }
   To use this feature, you specify the channel you want to write to in the Channel property of the Event attribute. The Event attribute is associated with the ETW event method your event source defines. In the class above, that’s the Load method. 

The NuGet package supports the four predefined ETW channels that the Windows Event Log defines: Admin, Operational, Analytics and Debug (see the ETW channel documentation for more information). You can see how those show up in the screenshot above. We also used an existing ‘Message’ attribute to create a formatted string for our message.

With the above definition (and a registration step detailed later), the “Load” event will write an event to the “Admin” event log each time it is called. This log can be found in the “Event Viewer” tool under the node “Applications and Services Logs / Samples / EventSourceDemos / EventLog”. Notice that the three-element name specified in the EventSourceAttribute determines the location of the log.

In order for the windows event viewer to know that there is a new source of events to log, it is necessary that you register your EventSource with the operating system, typically when your application is deployed or installed. This operations requires administrator permissions. The artifacts needed for registration (a manifest file and a resource DLL) are generated at build time through a build step injected in your project (when you add the NuGet package reference).

Registering your EventSource

When you install the EventSource NuGet package, the build step previously mentioned generates the following files for each EventSource in your application:

  • <AssemblyName>.<EventSourceTypeName>.etwManifest.man
  • <AssemblyName>.<EventSourceTypeName>.etwManifest.dll.

These files need to be registered with the operating system to enable channel support. To do this you run the following command after the files are in their final deployed location:

wevtutil.exe im <EtwManifestManFile> /rf:"<EtwManifestDllFile>" /mf:"<EtwManifestDllFile>"

Once this registration command is executed, all subsequent calls to MinimalEventSource.Log.Load(), from any process on that machine, will automatically result in events in the Windows Event log.

Note: you can provide localized strings for your EventSource by using the LocalizationResources property on the EventSourceAttribute associated with your EventSource type.

Build-time Validation of User-defined EventSources

Build-time validation of the user defined EventSources provides early feedback into possible issues with the EventSource definition, issues that would otherwise surface only at runtime, as silent logging failures. The build time validation step is injected into your project as a post build step and may lead to build failures when EventSource issues are detected.

Sample code

As I mentioned, we have a sample that you can try, which we released as the EventSource samples NuGet package. For best results, create a new console applications called ‘DemoEventSource’ in Visual Studio and then reference the EventSource Samples NuGet package from that project. The source code is part of the package and the Readme.txt file will tell you how to wire up your main program to the sample code.

This sample was used to create the event log screenshot at the top of this post. You can see what the EventSource definition looked like, for that sample, in the screenshot below.

clip_image006

Feedback

Please let us know what you think. We think that event log support is an important addition to EventSource. Please let us know about any other capabilities you would like to see in EventSource as well as any problems you encounter adopting this new feature.

Leave a Comment
  • Please add 1 and 1 and type the answer here:
  • Post
  • .NET 4.5 is unavailable for pre-Event Tracing for Windows OSes, but what happens when this is used on unsupported but .NET 4.0-capable systems like Windows Server 2003? Are exceptions thrown, can you check for compatibility?

  • EventSource uses the ETW APIs that were introduced in Windows VISTA, and thus will not work on older OSes like Win2003.    I have not confirmed this personally, but what I would expect to happen is for there to be a PINVOKE Exception thrown when it could not find the native API it was looking for.   Now EventSource has a requirement to 'do no harm' in the sense that turning logging on should never cause an exception when there was not one without logging.   Thus EvenSource swallows exceptions by default (you can check for them explicitly with the 'ConstructionException' property).   Thus what I would expect on Win2003 is that EventSource would seem to do nothing.  (unless you check with the ConstructionException).  

  • So leave it in but it just won't work? Fair enough. I suppose you could build an abstraction over this behavior to log sanely in its absence.

  • If you want to support Win2k3 in some fashion it is not hard to do (assuming things behave as I indicated below).  The ETW part of EventSource support will not work as it has a dependency on an newer OS, but EventSources fundamentally send their data to a subscribing EventListener (very analogous to TraceSources going to TraceListeners).   ETW just happens to be a built in EventListener.   Thus you can define your own EventListener that ALSO pipes the data wherever you want independently of ETW.    You will see an example of a EventListener in use in the 'EventSource Samples' NuGet package, and the Sematic Logging CodePlex Package (entlib.codeplex.com/wikipage) has code for logging to a file or to a database.   It is also only about dozen lines to code to have an EventListener send the events to a TraceSource (so you can go through that pipeline.   You could even have the data go to the Pre-VISTA ETW APIs (in fact EventSource used to do exactly this, but we pulled this support because we did not wish to put the work into testing things for a 10 year old OS).    Thus EventSource does not have a HARD dependency on ETW at all, and there is no reason to have to build an abstraction 'on top' of it.  

  • Thanks, great. I'm probably not actually going to use it, I was just wondering how the library dealt with it since the reason it exists is to be available to .NET 4.0 machines, some of which run pre-Vista-era Windows and there was nary a mention of it in the post. But the ability to not be hinged to Event Tracing availability makes sense.

  • I don't usually leave comments, but I have to say bravo on this.  I recently built a service using the .NET Service Model for the first time (written all of my services using native code before), and I was using the EventLog object to write events.  I quickly found out that it didn't have a time stamp granularity smaller than a second, and was frustrated by the out-of-order events in my log.  

    Having worked for Microsoft in the past, I was quite familiar with ETW and looked for a .NET solution using ETW channels.  I found the EventSource class and worked on an implementation of it only to realize this morning that it didn't support channels.  Imagine my surprise when I found this article a day after it was posted with a solution from Microsoft.

    I would like to commend your team on having the agility to use the NuGet release channel to react to immediate customer demands.  This solves a huge issue for .NET developers that native developers are so accustomed to.

  • Thanks, been waiting for this for some time now!

    I can't seem to get the Analytic events in the Event Log though. I do get an event (65534) which I assume its the manifest, but nothing more. I can capture the events with Perfview though.

    Any ideas of what I could be missing?

    Thanks

  • If you are having trouble with non-admin events, are you sure those channels are enabled (right click and select properties).   Only the admin channels are enabled by default.  

  • Is there any reason to the limitation of 3 levels in the Event Viewer, or that names can't have spaces?  Plus debug events have an issue displaying.  

  • The message of the 3rd EventAttribute is not correct. It should be "Stop processing request {0}".

  • Running wevtutil shows following warning:

    warning...publisher <eventsourcename> resources are not accessible.

    Any idea?

  • When's the next version update because there are some limitations and build timing issues we're seeing?  Where can we give/get more info on this package?

  • This has turned my entire event log service completely unstable, I can't go 30 seconds without "The RPC server is unavailble" and everything shutting down.  What's going on?

  • Even I get this warning running wevtutil:

    warning...publisher <eventsourcename> resources are not accessible.

    Anybody resolved this?

  • Stephen, the limitation of 3 levels in the Event Viewer is an OS convention that you may choose to follow (and I recommend you do). Regarding the debug events not showing up, please make sure to enable it, as Vance has suggested above ("are you sure those channels are enabled (right click and select properties).   Only the admin channels are enabled by default. ").

Page 1 of 4 (52 items) 1234