Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correlating IComMethodEvents

When implementing IComMethodEvents you get three events.

  1. OnMethodCall
  2. OnMethodException
  3. OnMethodReturn

The goal of what I am trying to do is to log call times per method in COM+ components.

The time of the event can be retrieved by using lTime and lMicroTime in the COMSVCSEVENTINFO structure so by logging that time in both OnMethodCall and in OnMethodReturn I should be able to calculate the call time but how can I be sure that the two events are related.

By testing it looks as I should be able to use the just-in-time (JIT) activated object oid.

Any problems in doing it like that or are there other ways?

One problem that might be is that I see the oid is frequently being reused so if the events for some reason is fired out of order it might be a bit more difficult to implement the correlation.

Update 1:

Further testing shows that oid is not enough in a multi user scenario. The same object is used at the same time so correlation has to be done using at least oid and original caller. A follow up question would be: How to get the original caller from a COM+ event subscriber?

Update 2:

Just found IComMethod2Events. Difference is that the events has an identifier of the thread executing the call. Looks promising in tests and I can't imagine a scenario where the correlation could fail. The threading model for the COM+ components are Any Apartment.

Update 3

In this article Creating COM+ PerfMon Counters to Monitor COM+ Data oid is used. I don't think that is enough in a multithreaded apartment.

Note: I will eventually implement this in Delphi so I added the Delphi tag. I also added the C# tag because chances are that the language used to implement the interface is not important at all. Update: Tentatively adding the c++ tag just to draw the attention of someone who has actually used this stuff before.

like image 797
Mikael Eriksson Avatar asked Mar 14 '13 06:03

Mikael Eriksson


2 Answers

...if the events for some reason are fired out of order...

They never do. The COM+ system event publisher fires these events using COM+ Events service. Invocation of an event is synchronous from event publisher's point of view. When a publisher fires an event, it doesn't proceed with the next one until all the subscribers complete processing of fired event. Quite naturally, OnMethodReturn/OnMethodException events are not published before matching OnMethodCall ones. I recall reading KBs concerning race conditions/broken subscriptions in COM+ events. All of those bugs, to my knowledge, have been addressed in various Service Packs for Windows 2000. Though, admittedly, I do not try to stay up-to-date in this area.

When implementing IComMethod2Events you subscribe to the very same transient subscription as for IComMethodEvents. So order of fired events is the same too.

...so correlation has to be done using at least oid and original caller...

At this point I'm really not sure whether you do interpret results of your tests correctly. How do you test, exactly?

oid should already encapsulate all the information required, even in "multiple clients" scenario with JIT and pooling. Last time I implemented such event listener (it has been a while), relying on oid worked out fine. Though, majority of components in my environment was written in VB6 (hence, lived in STA). Yet, even with STA you can have several calls at various stages of execution by a single thread. As there is an upper bound for number of threads in COM+ STA thread pool you can have the following situation: call A starts on particular thread, call B starts on the same thread, call B returns, call A returns. I do not recall any trouble tracking the calls by oid without "some additional info about the caller".

Implementation idea you consider is, by large, canonical. COM+ spy sample that comes with Platform SDKs uses oid argument to trace individual calls. You can find the application's sources in <Path to SDK samples>\Samples\com\administration\spy. The sample has been using this implementation for quite a while (since Windows 2003 at least). And today it is aeons after MTA and even COM+ introduction. Should there be flaws the sample would be updated at this point. Hopefully.

like image 161
Ilya Kurnosov Avatar answered Nov 18 '22 17:11

Ilya Kurnosov


The MSDN link "Creating COM+ PerfMon Counters to Monitor COM+ Data" seems to do pretty much what you are aiming for (although in managed C++ I think).

The relevant part is this, I guess:

void IComMethodEvents.OnMethodCall(ref COMSVCSEVENTINFO ei, ulong
    lObjID, ref Guid gClsID, ref Guid gIID, uint nIndex)
{
    //Make sure that monitoring is enabled and that our performance
    //counter has been initialized.
    if (Monitor && pcMethodDuration != null)
    {
    try
    {                    
        //We are going to store the initial value in a Sorted List 
        //collection. To do this we are going to need a key that
        //represents this call.
        string strKey = lObjID.ToString() + gClsID.ToString() + 
            gIID.ToString() + nIndex.ToString();

This might be the solution to your pondering about oid (lObjID in their example). Don't know if this covers your multi-user scenario, you'll have to give it a try. The page has quite a bit of details on the subject so hopefully you'll be able to figure it out. Good luck.

like image 1
Per Lundberg Avatar answered Nov 18 '22 17:11

Per Lundberg