Sunday, January 29, 2006

2191.aspx

egilhComTracker: Free component to track com+ call times with

The Component Services Console displays all sort of useful information like the number of objects in call, average call time etc. But, there is no official way to get the com+ call timers directly. You have to do the dirty work yourself and calculate the average call times. There is an official way and documented way to do this but it takes a lot of code and work. I found a way  to get the com+ call times the unofficial way which is a lot simpler. The egilh COM+ tracker gives you access to all the hidden statistics in COM+.


The egilh COM+ tracker download contains the com+ call time tracker and a VBScript example client. You can do a lot of neat stuff with it:




  • Use it a ASP page to monitor the call time of your components live
  • Use Cacti to show how average call time changes during the day.
  • Use the COM+ Admin API to automatically shut down/recycle components with high call times

Installation



  • Download the egilh Com+ Tracker
  • Extract the files
  • Register the DLL in COM+ or run regsvr32 EgilhComTracker.dll in the directory where you extracted the files

Usage
The egilh.ComTracker object only has one method: string getStatistics()


It returns a xml formatted string that contains information about all the running applications. The XML has the following layout:
/applications
  /application
     /classes 
         /class


Example:


<applications>


      <application>


      <guid>{98CDBB6E-3CAF-46F2-ABE6-EABECD6AA4EB}guid>


      <ID>10ID>


      <processID>1792processID>


      <statistics>


            <callsPerSecond>0callsPerSecond>


            <totalCalls>0totalCalls>


            <totalClasses>1totalClasses>


            <totalInstances>1totalInstances>


      statistics>


      <classes>


            <class>


                  <progID>Test.Sleep.1progID>


                  <bound>1bound>


                  <inCall>0inCall>


                  <pooled>-1pooled>


                  <references>1references>


                  <responseTime>120responseTime>


                  <callsCompleted>0callsCompleted>


                  <callsFailed>0callsFailed>


            class>


      classes>


      application>


applications>


 



Test client
The following VB code shows the call times for all classes registered in com+ on the local machine.


Dim oTracker 'As Object


Dim sResult 'As String


Dim oDOM 'As DOMDocument30


Dim oNode 'As MSXML2.IXMLDOMNode


 


'Get the com+ call times


Set oTracker = CreateObject("egilh.ComTracker")


sResult = oTracker.getStatistics()


Set oTracker = Nothing


   


'Display call times


Set oDOM = CreateObject("MSXML2.DomDocument.3.0")


oDOM.loadXML (sResult)


For Each oNode In oDOM.selectNodes("/applications/application/classes/class")


   WScript.echo oNode.selectSingleNode("progID").Text & _


          " call time: " & oNode.selectSingleNode("responseTime").Text


Next


 


With all the call information at hand, it is also possible to shut down components with high call times etc. The example below loads the XML returned by the COM+ tracker in a DOM using MSXML 3.0 and checks the responseTimes. It uses the COM+ Admin API to shut down the application if the call time is higher than the configured MAX_CALL_TIME and there are objects in call. The ShutDownApplication method works on Windows 2000 as well as Windows 2003. It has the same "brutal" effect as right clicking a COM+ application and selecting "shut down"; clients currently in call will get a COM+ error. With Windows 2003 it is possible to use recycling which routes new request to a new application instance but lets existing calls finish.


Option Explicit


 


Const MAX_CALL_TIME = 10000  'Max allowed call time in miliseconds


Const CHECK_INTERVAL = 5000  'How often we should check the call times


Const RECYCLE_REASON = 408  'The reason for the recyle. Any number is OK


 


 


'Never ending main loop that monitors the call time


Do While True


    checkCallTimes


    WScript.Sleep(CHECK_INTERVAL)


Loop


 


Private Sub checkCallTimes()


'**


'Purpose: Check the call times and shut down applications that have too high call times


    Dim oTracker 'As Object


    Dim sResult 'As String


    Dim oDOM 'As DOMDocument30


    Dim oNode 'As MSXML2.IXMLDOMNode


    Dim sProgID 'As String


    Dim lResponseTime 'As Long


    Dim lInCall 'As Long


    Dim oApp 'As MSXML2.IXMLDOMNode


    Dim bHighCallTimes 'As Boolean


 


     'Get the com+ call times


    oTracker = CreateObject("egilh.ComTracker")


    sResult = oTracker.getStatistics()


    oTracker = Nothing


 


    bHighCallTimes = False


 


    'Check call times


    oDOM = CreateObject("MSXML2.DomDocument.3.0")


    oDOM.loadXML(sResult)


    For Each oNode In oDOM.selectNodes("/applications/application/classes/class")


        lInCall = CLng(oNode.selectSingleNode("inCall").Text)


        lResponseTime = CLng(oNode.selectSingleNode("responseTime").Text)


 


        ' Check if we should recycle


        If lResponseTime > MAX_CALL_TIME And lInCall > 0 Then


            'Log that we are recycling


            sProgID = oNode.selectSingleNode("progID").Text


            WScript.Echo(Now() & " Shutting down '" & sProgID & _


                              "' because of high call time: " & lResponseTime)


 


            'We shut down the parent process: ../../processID


            oApp = oNode.parentNode.parentNode


            shutDownApplication(oApp.selectSingleNode("guid").Text)


            bHighCallTimes = True


        End If


    Next


 


    If Not bHighCallTimes Then WSCript.Echo(Now() & " Call Times OK")


End Sub


 


 


Private Sub shutDownApplication(ByVal appGuid)


'**


'Purpose: Shut down an application


'Description: Shuts down a com+ application identified by its guid.


Dim adminCatalog 'As COMAdmin.COMAdminCatalog


Dim appInstanceGUID 'As Object


 


    adminCatalog = CreateObject("COMAdmin.COMAdminCatalog")


 


    'ShutdownApplicationInstances


    adminCatalog.shutDownApplication(appGuid)


 


    adminCatalog = Nothing


End Sub


No comments:

Post a Comment