Instrumenting Your Application to Measure its Performance Part 6 Injecting EventSource Using AOP

 

In the last article, you learned how to wrap your code with a wrapper / envelope class contained in a using statement, which quickly instruments a block of code with enter / exit traces.

You can find the source code to this article in my GitHub repository  BizGear

So far in this series, instrumenting your code means adding, or ‘sprinkling’ trace statements through your code. A drawback to this technique is code can quickly become littered and adding the trace statements becomes something you need to manually do.

Even though the last article demonstrated an easier route, there is another technique shown in this article to instrument your code without ‘sprinkling’ trace statements through your methods. This technique is Aspect Oriented Programming, or AOP.

Wikipdia defines AOP

“In computing, AOP is a programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns.”

The power of AOP is you can decorate interfaces with attributes which define code to call before entering a method and after exiting a method. The trace statements executed, or ‘injected’ into the method remains separate from the method implementation.

There are several popular AOP frameworks. Because I use the Unity IOC container in my day job, I will use Unity’s AOP capabilities to demonstrated injecting ETW trace statements.

I recommend the following articles as two starting points for more information about Unity Interception:

Aspect-Oriented Programming, Interception and Unity 2.0 by Dino Esposito, MSDN Magazine, December 2010,

Interception with Unity MSDN


Overview

The following picture is taken from the Unity Interception documentation on MSDN.

image

What this diagram shows is you that need to register your object in the Unity container. When you (the client in the diagram) ask the container to instantiate an object, the container returns a proxy to your object, not the actual object. The proxy references a Behaviors Pipeline, which you write, and which is called as you (the client) makes calls to the target object.

The behaviors in the pipeline can be chained together. In the example used in this article, there is only one behavior. You can write the behavior so it is called before the Target is invoked as well as after the target returns. The implementation of the behavior performs the ETW tracing.

 


First Steps

The BizGear application implements a Business Rule called CanReturnMerchandise. This business rule is a bare bones implementation, called through the WCF service and merely returns a true value when called from the WPF client when the user clicks the Return button on the Merchandise tab:

image

In a real world application, the rule implementation would likely call a repository to access data tables and implement business rule logic using data read from a database.

To demonstrated Unity Interception, this implementation is good enough.

CanReturnMerchndiseRule
  1. publicclassCanReturnMerchandiseRule : ICanReturnMerchandiseRule
  2. {
  3.     [Performance]
  4.     publicbool CanReturnMerchandise(Product product, SalesOrder salesOrder)
  5.     {
  6.         return ValidateProductIsReturnable(product) && ValidateReturnTimePeriod(product, salesOrder);
  7.     }
  8.     //Validate product is not discontinued or purchased “as is”
  9.     privatebool ValidateProductIsReturnable(Product product)
  10.     {
  11.         returntrue;
  12.     }
  13.     privatebool ValidateReturnTimePeriod(Product product, SalesOrder salesOrder)
  14.     {
  15.         returntrue;
  16.     }
  17. }

Figure 1

 

This is the ICanReturnMerchandiseRule interface

ICanReturnMerchandiseRule
  1. publicinterfaceICanReturnMerchandiseRule
  2. {
  3.     bool CanReturnMerchandise(Product product, SalesOrder salesOrder);
  4. }

 

Figure 2

 

What we first do is register the CanReturnMerchandiseRule via its interface to the Unity container and tell Unity that it should perform Interception when it instantiates (the client requests the container to resolve) CanReturnMerchandiseRule.

To register the interface and request Unity to perform interception, you register like this:

RegistrationMoudule
  1. publicclassRegistrationModule : IRegistrationModule
  2. {
  3.     publicvoid Register(IUnityContainer container)
  4.     {
  5.         container.AddNewExtension<Interception>();
  6.         container.RegisterType<ICanReturnMerchandiseRule, CanReturnMerchandiseRule>()
  7.         .Configure<Interception>()
  8.         .SetInterceptorFor<ICanReturnMerchandiseRule>(newInterfaceInterceptor());
  9.     }
  10. }

Figure 3

Line 20 configures unity to create a CanReturnMerchandiseRule instance when resolving an object using the ICanReturnMerchandiseRule interface.

Line 21 and 22 configures Unity to perform Interception.

You may have noticed the [Performance] attribute in line 7, Figure 1, which decorates the CanReturnMerchandise method, of the first code example above.

Here is the implementation of the Performance attribute:

Code Snippet
  1. publicclassPerformanceAttribute : HandlerAttribute
  2. {
  3.     publicoverrideICallHandler CreateHandler(IUnityContainer container)
  4.     {
  5.         returnnewCanReturnMerchandiseRuleHandler();
  6.     }
  7. }

 

Figure 4

This attributes overrides CreateHandler, which is called by Unity Interception before performing CanReturnMerchandiseRule.CanReturnMerchandise().

All that’s left to do is provide the implementation to CanReturnMerchandiseRuleHandler:

CanReturnMerchandiseRuleHandle
  1.   classCanReturnMerchandiseRuleHandler : ICallHandler
  2.   {
  3.       publicIMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
  4.       {
  5.           var productData = string.Empty;
  6.           var salesData = string.Empty;
  7.           var etwTracer =  MerchandiseReturnContextEventSource.Log;
  8.           if (etwTracer.IsEnabled())
  9.           {
  10.               var methodName = input.MethodBase.Name;
  11.               var className = input.Target.ToString();
  12.               var product = input.Inputs[0] asProduct;
  13.               if (product != null)
  14.               {
  15.                     productData = string.Format(“Product: Id {0} Description {1}, product.Id, product.Description);
  16.               }
  17.               var salesOrder = input.Inputs[1] asSalesOrder;
  18.               if (salesOrder != null)
  19.               {
  20.                   salesData = string.Format(“SalesOrder Id {0} SalesDate {1}, salesOrder.Id, salesOrder.SalesDate);
  21.               }
  22.               etwTracer.Business(className, methodName, productData + salesData);
  23.           }
  24.           // Perform the operation
  25.           var methodReturn = getNext().Invoke(input, getNext);
  26.           return methodReturn;
  27.       }
  28.       publicint Order { get; set; }
  29.   }

 

Figure 5

Line 17 creates an instance of the class to create ETW traces.

To incur as little performance impact as possible, Line 19 checks if logging is enabled before composing a log message.

Recall that CanReturnMerchandise() accepts two parameters: a Product object and a SalesOrder object. (Line 7, Figure 2)

In the code example shown in Figure 5:

Lines 21 and 22 obtain the method name (CanReturnMerchandise()) and the class name (CanReturnMerchandiseRule).

Lines 24 – 28 get a reference of the Product object and formats a message containing information identifying the Product object.

Lines 30 – 34 get a reference to the SalesOrder object and formats a message containing information identifying the SalesOrder object.

Line 36 logs a ETW message containing the class name, method name, and identifying information for the Product and SalesOrder object passed from the client.

Finally, Line 40 calls CanReturnMerchandiseRule.CanReturnMerchandise().

Line 42 returns the result (true) returned by CanReturnMerchandiseRule.CanReturnMerchandise().

The following code, in the MerchandiseReturnViewModel, is performed when the user clicks the Return button:

MerchandiseReturnExecute
  1. privatevoid MerchandiseReturnExecute()
  2. {
  3.     using (var proxy = newMerchandiseReturnClient())
  4.     {
  5.         var dto = newMerchandiseDto {ProductId = 1, SalesOrderId = 1};
  6.         var canReturn = proxy.CanReturnMerchandise(dto);
  7.         ReturnResult = “Complete”;
  8.         _etwLogger.Presentation(“MerchandiseReturnViewModel”, “MerchandiseReturnExecute”, canReturn.ToString());
  9.     }
  10. }

 

Which calls, on line 37, the server side code CanReturnMerchandiseRule.CanReturnMerchandise()

CanReturnMerchandise
  1. [Performance]
  2. publicbool CanReturnMerchandise(Product product, SalesOrder salesOrder)
  3. {
  4.     return ValidateProductIsReturnable(product) && ValidateReturnTimePeriod(product, salesOrder);
  5. }

 

Without Unity Interception, all you should see in the ETW output is the trace statement created from line 40 on the client when you run the demo on the same machine.

With Unity Interception, you should see the trace statement emitted on the client in the MerchandiseReturnViewModel and the trace statement emitted on the server by the CanReturnMerchandiseRuleHandler:

image

 

Summary

Using AOP- in this example Unity Interception- you can see how you can separate implementation from the instrumentation implemented in the handlers which Unity ‘injects’ into your code during run time.

Although a simple example, I hope the example provides enough information to build upon for real world application instrumentation.

In the next article, I’ll show you how to take the idea of AOP- code injection- and inject instrumentation into the WCF call stack.

This entry was posted in ETW and tagged . Bookmark the permalink.

One Response to Instrumenting Your Application to Measure its Performance Part 6 Injecting EventSource Using AOP

  1. Pingback: Dew Drop – July 11, 2013 (#1,583) | Alvin Ashcraft's Morning Dew

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>