AutoSteps Source Code

formerly known as Business Transaction Monitoring

PerformanceGuard by default measures response times for single transactions against a single server. If you want to monitor more complex business transactions that involve several steps or several servers, you must specify where transactions begin and end so that PerformanceGuard can record the execution time.

This is where the PerformanceGuard BTM (Business Transaction Monitoring) feature is useful. It essentially works as a stop watch that lets you time any event or business transaction on your client and view response times in the PerformanceGuard web interface. This way, BTM can help you easily identify bottlenecks in your business processes, even when processes are complex.

Read more about BTM, including technical information about methods, properties, etc. under Monitor Complex Activity with AutoSteps in the Setup section of this help system.

Source Code

Java

To call the ITransactionHelper COM object for Monitor Complex Activity with BTM (Business Transaction Monitoring) from Java you must use a COM2Java bridge.

We provide an interface that uses COM4J from java.com. You can find all necessary files in the attached archive BTMv2COM4J-v1.zip.

Prerequisites:

  • com4j.dll must be located in the same folder as com4j.jar

  • com4j.jar must be in your classpath

  • BTMv2COM4J.jar must be in your classpath

BTMv2example2.java

In the archive you'll find an example source file, BTMv2example2.java, that shows you how to invoke the BTM COM object from Java:

import com.premitech.btm2.StopWatch;

public class BTMv2example2 {

     public static void main(String[] args) {

         // Set variables
         String OEMTarget = "";
         String trans_group = "BTMv2 Java Test";
         String trans_name = args[0];
         String trans_tag = "";
         String user_name = "testuser";
         String user_domain = "testdomain";
         int execution_time_millis = Integer.parseInt(args[1]);

         // Create ITransactionHelper COM object
         StopWatch sw = new StopWatch();

          // Set OEM agent target
         sw.setOEMTarget(OEMTarget);

         // Set user name and domain
         sw.setUserName(user_name);
         sw.setDomain(user_domain);

          // Set transaction group name (usually the name of the application)
         sw.setTransactionGroup(trans_group);

         // Mark start of business transaction
         long contextId = sw.start(trans_name);

          System.out.println("Transaction started with context id = "+contextId);

         // Set any transaction tag
         sw.setTag(trans_tag, contextId);

         try {
                  // Execute transaction code
                  Thread.sleep(execution_time_millis);

                  // Mark end of business transaction
                  sw.stop(contextId);

                  System.out.println("Transaction stopped with context id = "+contextId);

         } catch (Exception e) {
                 // Transaction failed - report the failure
                 sw.fail(contextId);
         }
     }
}


To compile the example source file execute this command:

javac -cp BTMv2COM4J.jar;. BTMv2example2.java

To run the example, make sure that com4j.jar and com4j.dll are located in the same folder, and that com4j.jar and BTMv2COM4J.jar are in the classpath:

java -cp BTMv2COM4J.jar;.;com4j.jar BTMv2example2 testing 123

C#

Add a reference to the PGExtHelper.dll.


using System;
using System.Threading;
using PGExtHelper;
namespace PGExtHelperTest
{
     class Program
     {
         static void Main(string[] args)
           {
            // Simple
            ITransactionHelper trans = new TransactionHelper();
            trans.transactionGroup = "Test Group";
            trans.start("Trans1", null);
            trans.stop();

            // More complete
            ITransactionHelper trans2 = new TransactionHelper();
            trans2.transactionGroup = "Test Group";
            object contextId1 = trans.start("Trans2", null);
            trans2.setTag("Tag1", contextId1);
            trans2.stop(contextId1);
          }
      }
}

C++

  //
  // BtmSimpleTest.cpp : Defines the entry point for the console application.
  //

  // ***************** Import the PGExtHelper class ********************* //
  #import "C:\\pgexthelper.dll" named_guids
  // ***************** Import the PGExtHelper class ********************* //

  int _tmain(int argc, _TCHAR* argv[])
  {
    // Must be called before any COM-operations
    CoInitialize(NULL);

    // Instantiate the COM-Object
    PGExtHelper::ITransactionHelperPtr pTransaction;

    // Create a StartStop COM object smart ptr.
    HRESULT aHr=pTransaction.CreateInstance(__uuidof(PGExtHelper::TransactionHelper));
    if (aHr!=S_OK) {
   // some error code here
    }

   // make 10 100ms requests,
   for(int i=0; i<20; i++)
   {
       // Following properties is optional, but it's possible to change any of them to supply own values.
       // Please note that the length for all of them is limited with 32 characters
       pTransaction->userName=_variant_t(L"Any user");
       pTransaction->domain=_variant_t(L"Any domain");
       pTransaction->transactionGroup=_variant_t(L"Any group");

       /*unsigned _int64 contextId=*/pTransaction->start(_variant_t(L"Any transaction"));
       pTransaction->setTag(_variant_t(L"Any tag")/*, contextId*/);
       pTransaction->setValue(_variant_t(L"Any value"), 1.0/*, contextId*/);
       Sleep(100);
       pTransaction->stop(/*contextId*/);
   }

   return 0;
 }

Example Notes

Example client code for calling the PerformanceGuard agent COM start-stop interface:

Dim comPG As Variant
Dim flagPG As Variant

Err = 0
On Error Resume Next
Set comPG = createobject("PGExtHelper.TransactionHelper")

If Err = 0 Then
flagPG = True
Else
flagPG = False
End If

If flagPG = True Then
comPG.start("Any Transaction")
End If

........................ Insert transaction code here ............................

If flagPG = True Then
comPG.stop()
End If

Generation of IDs

The VB.Net samples in this section will not work directly in VBScript

Simple Case

For simple cases where the start and stop methods are invoked non-interlaced from the same thread you don't need to worry about the context ID at all.

Example:

Dim PGConnector As PGExtHelper.ITransactionHelper
PGConnector = New PGExtHelper.TransactionHelper

'Change the following to "true" to suppress internal BTM errors.
'ignoreErrors defaults to false if it is not set
PGConnector.ignoreErrors=false

PGConnector.start("Test_1")
PGConnector.stop() 'Stops Test_1

PGConnector.start("Test_2")
PGConnector.stop()'Stops Test_2

PGConnector.start("Test_3")
PGConnector.stop()'Stops Test_3

PGConnector.start("Test_1")
PGConnector.stop()'Stops Test_1

In this case PGExtHelper handles the context IDs itself.

Interlaced Starts and Stops

If you have interlaced starts and stops in the same thread like this:

Start Test_1
Start Test_2
Stop Test_1
Stop Test_2
And you implement them like this:
PGConnector.start("Test_1")
PGConnector.start("Test_2")

PGConnector.stop() 'Will actually stop Test_2
PGConnector.stop() 'Will actually stop Test_1


PGExtHelper assumes that start and stop are naturally nested. In order to achieve the other behavior, you must supply context IDs yourself. You can, for example, implement a function like this:

Private Function ContextId() As Int64
    Dim aId As Int64
    Dim aCtr As Int32

    aId = Thread.CurrentThread.ManagedThreadId() + (Process.GetCurrentProcess.Id << 16)
    aId <<= 32
    aId += Interlocked.Increment(aCtr)
    ContextId = aId
End Function


And use it like this:
Int64 Id1 = ContextId()
Int64 Id2 = ContextId()
PGConnector.start("Test_1", Id1)
PGConnector.start("Test_2", Id2)

PGConnector.stop(Id1) 'Will correctly stop Test_1
PGConnector.stop(Id2) 'Will correctly stop Test_2

The suggested ContextId function correctly handles cases where you have multiple threads accessing the same instance of the PGExtHelper object.

Currently there is no way to access the ContextIds that are internally generated by the PGExtHelper object.

VBScript

If you use VBScript, it's easy to use the same method with process and thread IDs as described in the previous. The solution is based on using two instances of TransactionHelper, and simply parsing a 0 for the ID:

dim PGConnector1
set PGConnector1 = WScript.CreateObject("PGExtHelper.TransactionHelper")
dim PGConnector2
set PGConnector2 = WScript.CreateObject("PGExtHelper.TransactionHelper")

PGConnector1.start "Test_1", 0
PGConnector2.start "Test_2", 0

PGConnector1.stop 0 'Will correctly stop Test_1
WScript.sleep 2000
PGConnector2.stop 0 'Will correctly stop Test_2

VisualBasic.NET

The following shows the code used to connect to the component and direct the measured values to the correct instance of the PerformanceGuard agent:

Private Sub Form1_Load(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs)
Handles MyBase.Load
PGConnector = New PGExtHelper.TransactionHelper
txtStatus.Text = "Ready \!"End Sub

Private Sub CmdStart_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs)
Handles CmdStart.Click
On Error Resume Next
PGConnector.transactionGroup="Test from VB.Net";
PGConnector.start("Start click")
End Sub

Private Sub CmdStop_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs)
Handles CmdStop.Click
On Error Resume Next
PGConnector.stop()
End Sub

VisualBasic Script (.vbs)

May be used in Citrix login scripts, for example to measure drive mappings:

dim comPG
Set comPG = CreateObject("PGExtHelper.TransactionHelper")

' Initialise optional variables

comPG.userName="User"comPG.domain="Domain"comPG.transactionGroup="My Transaction Group"comPG.start("My Transaction Name")

comPG.setTag("My option")
comPG.setValue "My extra value" , 3.14

' Some code for which you want to measure execution time goes here

comPG.stop()

Python

The following code shows how to perform a single measurement. You must have Python installed with the win32 extensions (they come with ActivePython).

import win32com.client
import time
# Create COM object
obj = win32com.client.Dispatch("PGExtHelper.TransactionHelper")

# Set the user and domain
obj.userName="user"obj.domain="domain"# Set the transaction group
obj.transactionGroup="My Transaction Group"# An example of usage user-provided context (id=1000)

# Start the transaction helper
obj.start("My Transaction Name", 1000)

# Do some work (in this case, sleep 1 second)
time.sleep(1.0)

# Stop the timer
obj.stop(1000)

Search this documentation

On this page

In this section