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 6 and type the answer here:
  • Post
  • Zhiliang, thanks for catching this, this is fixed in the updated NuGet package we've just released.

  • Muhammad and Teja, regarding the warning "publisher <eventsourcename> resources are not accessible", you need to make sure the MAN and DLL files are deployed to a folder with the appropriate ACL (a folder under a user profile, e.g. somewhere under the default VS "Projects" folder, does not have the right permissions). This is one of the reasons why the samples performing manifest registration have the "simulated deployment" step that copies the files to %APPDATA%\EventSourceSamples.

  • Future GUIs, a new version that addresses some build timing issues has been released today to NuGet. Please contact us if it does not fix the issues you are seeing.

  • Brian, I'm surprised to hear this has created problems for you. Can you provide me with steps to reproduce the problem? What OS are you running this on? Have you explicitly disabled some services on your machine?

  • The build issues appear to have been resolved, thank you!  What about the naming rules, can we get spaces and dashes to be allowed?  Are you able to give us any updates on future features/release dates?

  • I'm also seeing something strange with writing to an Admin channel.  I can almost never get an event written to it, but as soon as I switch the method's attribute to write to the Operational channel, it logs just fine.  This is being used in a asp.net web project.  In another windows service project it writes just fine to the admin channel

  • I use the EventSource class in my application for logging and want to run my application as a cloud application. In the cloud I would like to use Windows Azure Diagnostics. Does Windows Azure Diagnostics work well with the EventSource or must some refactoring be done?

  • The feature of logging events to the Windows EventLog is very nice. Will this feature be added to the System.Diagnostics.Tracing.EventSource in the near future or must I use  Microsoft.Diagnostics.Tracing.EventSource?

  • Anyone experience any memory leaks?  I seem to be in a web app.

    Also, what is the max text length of the message part of the log entry?  

  • From what i understand ETW logging is done in kernel itself, with the custom event source, is there a system call overhead when logging events from a user mode processes?

  • When enabled, logging to ETW is a system call. However, in most real scenarios the cost is dwarfed by the scenario you're trying to better understand. Many production high-volume Microsoft services rely on ETW for operational data, with quite a few providers. Often you'll couple your own custom user-mode providers (like EventSources, which incur the system call transition) with system call events (like Thread events, etc.) that are already executing in the kernel context.

    And also remember, you can measure the overhead of ETW, by using the ETW Sampled Profile events.

  • I have two keywords define that I OR together on a write event.  The values are 8 and 4 (ORs to 0xC).  However, when I dump this event in PerfView, I'm seeing 0xF0000000000C.  Why is the leading nibble getting set to 0xF?  I was also under the impression that I would see the field name (text) associated the values and not just the number in PerfView.  Is that correct?

  • @Keith "I have two keywords define that I OR together on a write event.  The values are 8 and 4 (ORs to 0xC).  However, when I dump this event in PerfView, I'm seeing 0xF0000000000C."

    Are you OR'ing with 0xC or 0x00000000000C? I'm guessing PerfView is showing in little endian which means the least significant nibble is the one to the left which would explain the behaviour? Just a guess...

  • With the latest nugets, I got the "publisher <eventsourcename> resources are not accessible" error until I removed the /rf and /mf arguments. The .man file already has the resourceFileName and the messageFileName defined. Any chance you can add a EventAttribute.ChannelName property? I realize the current name follows the convention of providername/channeltype, but I'd like to set custom names. I'm sure others would as well.

  • @Future GUIs:

    > I'm also seeing something strange with writing to an Admin channel.

    Please take a look at the RC release. There was an issue we addressed in this area that you might have been hitting.

    > Anyone experience any memory leaks?  I seem to be in a web app.

    I'm not aware of any memory leaks with the package. It would be extremely useful if you had a repro I could try.

Page 2 of 4 (52 items) 1234