Skip to content
Jon Wagner edited this page Oct 24, 2013 · 3 revisions

A Quick Tour

Creating a Logging Interface

Here is ESP implementing a logging interface for you automatically. All calls to the interface are logged to ETW, including parameters:

public interface ILog
{
	void SomethingIsStarting(string message);
	void SomethingIsFinishing(string message);
}

// yeah, this is it
var log = EventSourceImplementer.GetEventSourceAs<ILog>();

log.SomethingIsStarting("hello");
log.SomethingIsFinishing("goodbye");

Implementing an EventSource

In .NET 4.5, you could also derive a class from EventSource and implement calls to WriteEvent yourself. But this is boilerplate code that is error prone. Just let ESP do it for you by declaring your class as abstract. ESP will automatically implement any abstract methods.

public abstract MyEventSource : EventSource
{
	public abstract void SomethingIsStarting(string message);
	public abstract void SomethingIsFinishing(string message);
}

// ESP does the rest
var log = EventSourceImplementer.GetEventSourceAs<MyEventSource>();

You can also add Event and EventSource attributes to your class and ESP will honor them.

Instrumenting an Existing Interface

You probably have a few interfaces designed into your existing code to provide boundaries between parts of your system. This is a great place to add tracing, but why write any code to do that? Let ESP do it for you! ESP can take any interface and create a proxy for it, with the calls being automatically logged to an ETW source.

Here is ESP wrapping an existing interface for tracing:

public interface ICalculator
{
	void Clear();
	int Add(int x, int y);
	int Multiply(int x, int y);
}

public class Calculator : ICalculator
{
	// blah blah
}

Calculator calculator = new Calculator();

// again, that's it
ICalculator proxy = TracingProxy.Create<ICalculator>(calculator);

// all calls are automatically logged when the ETW source is enabled
int total = proxy.Add(1, 2);

Controlling the Data that is Logged

The best way to control the data that is logged is to add TraceParameterProvider rules.

Say you have the following interface:

interface IEmailer
{
	void Send(Email email, DateTime when);
	void Receive(Email email);
	void Cancel(string from, string to, DateTime earliest, DateTime latest);
}

class Email
{
	public string From;
	public string To;
	public string Subject;
	public string Body;
	public IEnumerable<byte[]> Attachments; 
}

You can set up rules to log something entirely different to ETW. See Controlling Logged Data for a more thorough discussion.

TraceParameterProvider.Default
	.For<IEmailer>()
		.With<Email>()
			.Trace(e => e.From).As("Sender") 
			.Trace(e => e.To).As("Recipient")
			.Trace(e => e.Subject).As("s")
				.And(e => e.Body).As("b")
				.TogetherAs("message")
	.For<IEmailer>(m => m.Send(Any<Email>.Value, Any<DateTime>.Value)
		.Ignore("when");