I'm trying to use Event Tracing for Windows (ETW) in my .NET application via the EventSource class that was included in .NET 4.5. I'm subclassing EventSource
as MyEventSource
and trying to implement an interface IMyEventSource
(for mocking purposes) as follows:
public interface IMyEventSource
{
void Test();
}
public class MyEventSource : EventSource, IMyEventSource
{
public static MyEventSource Log = new MyEventSource();
[Event(1)]
public void Test()
{
this.WriteEvent(1);
}
}
When I run PerfView and execute this code, I get an IndexOutOfRangeException
on the call to WriteEvent
. If I remove the interface by modifying the code...
public class MyEventSource : EventSource
{
public static MyEventSource Log = new MyEventSource();
[Event(1)]
public void Test()
{
this.WriteEvent(1);
}
}
...then everything works just fine.
Here is the code I used for testing in both cases:
static void Main(string[] args)
{
MyEventSource.Log.Test();
}
Why does my subclass of EventSource
break if it simply implements an interface?
Here is a related post.
At time of asking the question, the answer from @LarsSkovslund was correct. However with the stable version of Microsoft.Diagnostics.Tracing.EventSource, Microsoft changed this according to their blog post:
With the RTM release we’ve relaxed some of the event source validation rules in order to enable certain advanced usage scenarios.
The two changes in this area:
EventSource types may now implement interfaces to enable the use of event source types in advanced logging systems that use interfaces to define a common logging target.
The concept of a utility event source type (defined as an abstract class deriving from EventSource) is introduced to support sharing code across multiple event source types in a project (e.g. for optimized WriteEvent() overloads).
System.Diagnostics.Tracing.EventSource, provided with the .NET Framework, supports these scenarios as of .NET 4.6
While you can't have the event source implement an interface, it is possible to wrap it with another class that does. (This is an instance of the Adapter design pattern)
public class EventSourceAdapter : IEventSource
{
private MyEventSource log;
public EventSourceAdapter(MyEventSource log)
{
this.log = log;
}
public void Test()
{
log.Test()
}
}
}
When the EventSource class is building up its event structure base on reflection it will consider direct methods only e.g. inherited members are not considered as in your case with the use of IMyEventSource.
You are getting the IndexOutOfRangeException because WriteEvent will use the event id parameter to lookup a descriptor block with an index matching the event id thus throwing the exception when index does not exist.
So in short DONT used interfaces to define your ETW events using EventSource.
Cheers Lars
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With