IExplicitInstrumentationBinder or ICustomFactory?

Topics: Building and extending application blocks, General discussion
Apr 19, 2007 at 10:01 PM
Hi! I'm still trying to get my head around the EntLib 2.0. I'm attempting to instrument an custom content management application using the InstrumentationListener/InstrumentationProvider/InstrumentationConsumer attributes. I've seen examples that use the IExplicitInstrumentationBinder interface to explicitly define how instrument sources are bound to listeners. I also found an example that instead implements the ICustomFactory interface to bind the listener and the provider. Which should I use for EntLib v2.0?

Also, once I've figured that out, how do I trigger the events I've instrumented? Do I somehow tie in the Logging and App Block? How do I do that? I've looked at the Logging QuickStart, but I'm not sure if I should use it. Thanks for the help. I hope I'm making this more complicated than it needs to be.
Apr 19, 2007 at 10:12 PM
I'm not very familiar with the details of the instrumentation subsystem so unfortunately I can't answer your main question, but I'll try to find someone to help you out. But I can tell you that the instrumentation mechansim is completely independent from the Logging Application Block.

Tom
Apr 20, 2007 at 1:20 PM
Tom,

Thanks for the reply and for all your help. I would greatly appreciate any assistance you can provide for me. I am subscribed via email to this thread, so I can respond quickly to any posts from you or your colleagues.

Cheers,

Byron
Apr 23, 2007 at 2:16 PM
Can anyone help me? I'd really appreciate it.
Apr 23, 2007 at 2:16 PM
Edited Apr 23, 2007 at 2:17 PM
Apr 23, 2007 at 3:19 PM
Hi Byron,

The InstrumentationProvider/InstrumentationConsumer attributes are used by the ReflectionInstrumentationBinder to match events in the instrumentation provider to methods in the listener. This of course is costly, so in some cases a type implementing the IExplicitInstrumentationBinder interface is specified when configuring the instrumentation listener for an instrumentation provider through a parameter in the InstrumentationListener attribute; you can compare the database and authorization cases, where the former uses the explicit approach and the latter the reflection based one:

InstrumentationListener(typeof(DataInstrumentationListener), typeof(DataInstrumentationListenerBinder))
public class DataInstrumentationProvider


InstrumentationListener(typeof(AuthorizationProviderInstrumentationListener))
public class AuthorizationProviderInstrumentationProvider

The result of both approaches should be the same: the listener's handler methods are attached to the provider's events.

By default, a strategy in the ObjectBuilder chain for EnterpriseLibrary will fire the creation and attachment of the listener for a new object. However in complex cases, like logging, the creation of some instrumentation objects is triggered manually.

If you want to see examples, in increasing order of complexity you can look at:
- AuthorizationProviderInstrumentationProvider/AuthorizationProviderInstrumentationListener - simple objects, reflection based binding
- DataInstrumentationProvider/DataInstrumentationListener - simple objects, custom binding
- Logging - complex objects, mixed binding sometimes triggered in custom code.

Hope this helps,
Fernando
Apr 23, 2007 at 4:15 PM
Thank you, Fernando. This is indeed helpful. For reasons of requirement, I am going with the IExplicitInstrumentationBinder interface. I have created instrumentation providers, listeners, and binders. As well, I've created separate classes for my events and eventargs. If you or anyone wants to see specific code, please reply to this thread.

My question now is how do I trigger the events I've instrumented? Do I somehow tie in the Logging and App Block? If so, how do I do that?
Apr 23, 2007 at 6:55 PM
Hi Byron,

The short answer to your question is "whenever it makes sense for your block". This usually means an occurrence of your block's services or an error, and the code in your block's objects will likely trigger the calls to the instrumentation provider that will make instrumentation happen. You can use the same examples mentioned before as a starting point, just look for references to the instrumentation provider.

The support for instrumentation and the Logging block are not related (other than the Logging block having its own instrumentation); you shouldn't need to use the Logging block to provide instrumentation to your own block.

Fernando
Apr 23, 2007 at 9:09 PM
Edited Apr 23, 2007 at 9:32 PM
Fernando,

Thanks again for the reply. My problem is that I can't seem to find examples that go from writing the instrumentation code to actually writing to event logs, etc. I've seen examples that do either, but never both. That's why I'm confused. I understand that instrumentation has nothing to do with the Logging App Block (LAB), per se, but in the end I'm instrumenting my code to do something with the events I'm firing. That's why I'm stuck on the LAB.

My project will use the EntLib 2.0 classes for instrumentation. I need to create perfmon counters, log WMI events, and log to the Windows event log. Doesn't it make sense to use the LAB for these tasks since it creates a common framework for such tasks across an application?

One more thing. Do the EntLib 2.0 classes replace the Enterprise Instrumentation Framework?

Regards,

Byron
Apr 24, 2007 at 1:13 PM
Hi Byron,

Your typical Block will have a factory that will give you properly constructed implementations for a service, that will invoke the appropriate instrumentation when a service is requested. Taking IAuthorizationProvider as an example, you'll have:
- The IAuthorizationProvider interface describing a service
- The AuthorizationFactory factory to request instances of the IAuthorizationProvider service
- The AuthorizationProviderInstrumentationProvider and AuthorizationProviderInstrumentationListener combo where the interesting instrumentation events for the IAuthorizationProvider service are specified (in the provider) and given a concrete implementation (in the listener).
- The AuthorizationRuleProvider as one implementation (out of potentially many) of the IAuthorizationProvider service.

When you request the factory for an authorization provider you will get a concrete implementation, say an instance of the AthorizationRuleProvider class. This instance will have a reference to an instance of the AuthorizationProviderInstrumentationProvider class, and the events in this provider instance will have as handlers the appropriate methods from an instance of the AuthorizationProviderInstrumentationListener class created and attached (either through an explicit or reflection based binder) by the factory.
When a service is requested through the methods in IAuthorizationProvider, the implementation will carry out the required functionality and when doing so it will call methods in the instrumentation provider. These methods will raise events and the handlers in the listener will issue the appropriate instrumentation for that specific event as allowed by configuration. You can see this exemplified in the following sequence of messages:
- AuthorizationRuleProvider.Authorize(IPrincipal, string) -> will perform many calls to the instrumentation provider
- AuthorizationProviderInstrumentationProvider.FireAuthorizationCheckPerformed(string, string) -> will raise an event
- AuthorizationProviderInstrumentationListener.AuthorizationCheckPerformed(object, AuthorizationOperationEventArgs) -> will emit the appropriate instrumentation, like incrementing a perf counter or firing a Wmi event (this listener does not do event log, but others do).

I don't understand what you mean by "in the end I'm instrumenting my code to do something with the events I'm firing". You want to emit instrumentation so the behavior of your application can be known. The block object will determine when a certain "logical event" has occurred, the instrumentation listener will interact with the instrumentation APIs to represent the logical event and the instrumentation provider sits in between to decouple one from the other.

Fernando

Apr 24, 2007 at 3:04 PM
Fernando,

Thanks again for the reply. I'm sorry to take up your time with this, but I do find your posts helpful. I hope others just starting out with the Ent Lib 2.0 do as well.

Your example of the IAuthorizationProvider makes sense. In your paragraphs, you mention perf counters, WMI events, etc. I have such code in my listener:

CODE
InstrumentationConsumer("DataManagerFailedEvent")
public void DataManagerFailedEventHandler(object sender, DataManagerFailedEventArgs e)
{
if (EventLoggingEnabled)
{
string entryText = eventLogEntryFormatter.GetEntryText(e.ErrorMessage, e.Exception);
EventLog.WriteEntry(GetEventSourceName(), entryText, EventLogEntryType.Error);
}

if (WmiEnabled)
{
ManagementInstrumentation.Fire(new DataManagerFailedEvent(instanceName, e.ErrorMessage.ToString(), e.Exception));
}
}
/CODE

Three questions:

1. Where, in my front-end web application would my instrumentation be consumed?
2. If I use the explicit provider/listener instrumentation binding with a binder class, do I need to create a factory class as in your example?:

CODE

/// <summary>
/// This type supports the Enterprise Library infrastructure and is not intended to be used directly from your code.
/// Explicit binder for data access instrumentation.
/// </summary>
public class ManagerInstrumentationListenerBinder : IExplicitInstrumentationBinder
{
/// <summary>
/// Binds the events exposed by the source to the handlers in the listener.
/// </summary>
/// <param name="source">The source of instrumentation events. Must be an instance of <see cref="ManagerInstrumentationProvider"/>.</param>
/// <param name="listener">The listener for instrumentation events. Must be an instance of <see cref="ManagerInstrumentationListener"/>.</param>
public void Bind(object source, object listener)
{
ManagerInstrumentationListener castedListener = (ManagerInstrumentationListener)listener;
ManagerInstrumentationProvider castedProvider = (ManagerInstrumentationProvider)source;

castedProvider.DataManagerFailedEvent += castedListener.DataManagerFailedEventHandler;
}
}
/CODE
3. Do the EntLib 2.0 classes replace the Enterprise Instrumentation Framework?

Thanks for your patience and responses to-date.

Regards,

Byron