When implementing IComMethodEvents you get three events.
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.
...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
andoriginal 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.
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.
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