Using ARM Macros


Overview of ARM Macros

The ARM macros invoke the ARM API function calls. The ARM macros automatically manage the returned IDs from the ARM API function calls.

The ARM API function calls are implemented in SAS software with SAS ARM macros and these function calls provide a way to measure the performance of SAS applications as they are running. For each ARM API function call, there is a corresponding macro. The following table shows the relationship among the SAS ARM macros and ARM API function calls:

Table 6.1: Relationship among SAS ARM Macros and ARM API Function Calls

SAS ARM Macro

ARM API Function Call

%ARMINIT

ARM_INIT

%ARMGTID

ARM_GETID

%ARMSTRT

ARM_START

%ARMUPDT

ARM_UPDATE

%ARMSTOP

ARM_STOP

%ARMEND

ARM_END

The SAS ARM macro invokes the ARM API function call.

The following ARM macros are available:

'%ARMINIT Macro' on page 1072

generates a call to the ARM_INIT function call, which names the application and optionally the users of the application and initializes the ARM environment for the application. Typically, you would insert this macro in your code once.

'%ARMGTID Macro' on page 1070

generates a call to the ARM_GETID function call, which names a transaction. Use %ARMGTID for each unique transaction in order to describe the type of transactions to be logged. A %ARMGTID is typically coded for each transaction class in an application.

'%ARMSTRT Macro' on page 1079

generates a call to the ARM_START function call, which signals the start of a transaction instance . Insert %ARMSTRT before each transaction that you want to log. Whereas %ARMGTID defines a transaction class, %ARMSTRT indicates that a transaction is executing.

'%ARMUPDT Macro' on page 1082

is an optional macro that generates a call to the ARM_UPDATE function call, which provides additional information about the progress of a transaction. Insert %ARMUPDT between %ARMSTRT and %ARMSTOP in order to supply information about the transaction that is in progress.

'%ARMSTOP Macro' on page 1077

generates a call to the ARM_STOP function call, which signals the end of a transaction instance. Insert %ARMSTOP where the transaction is known to be complete.

'%ARMEND Macro' on page 1068

generates a call to the ARM_END function call, which terminates the ARM environment and signals that the application will not make any more ARM calls.

The ARM macros permit conditional execution by setting the appropriate macro options and variables .

Some general points about the ARM macros follow:

  • A general recommendation with all ARM macros is to avoid, in the program, the use of either macro variables or SAS variables beginning with the letters '_ARM.'

  • All macro options are keyword parameters. There are no positional parameters. Values for the macro options should be valid SAS values-that is, a SAS variable, quoted character string, numeric constant, and so on.

  • ARM macros can function either inside a DATA step or in open code. Use the _ARMACRO global variable or the MACONLY=YESNO macro option to tell the macro execution which mode is being used. For more information, see 'Setting the Macro Environment' on page 1063.

Using Variables with ARM Macros

The ARM macros use variables to pass IDs and other information from one macro to another. Because the ARM macros function within the same DATA step, across DATA steps, and in open code, variables that are used by the macros can take the form of DATA step variables or macro variables as determined by the macro environment.

SAS DATA step variables are used to pass ID information between two or more ARM macros in the same DATA step. In the DATA step environment, but not in the SCL environment, DROP statements are generated for these variables so that they are not inadvertently included in any output data sets.

If ID information must be passed between two or more ARM macros across separate DATA steps, then macro global variables are used.

The following SAS DATA step variables and macro variables are considered global:

Table 6.2: Global ARM Macro Variables

Variable

Description

Set By

Used as Input by

_ARMAPID

application ID

%ARMINIT

%ARMEND

_ARMTXID

transaction class ID

%ARMGTID

%ARMSTRT

_ARMSHDL

start handle

%ARMSTRT

%ARMUPDT,

%ARMSTOP

_ARMRC

error status

%ARMUPDT

%ARMSTOP

%ARMEND

none

_ARMGLVL

global level indicator

calling program

all

_ARMTLVL

target level indicator

calling program

all

_ARMEXEC

global enablement

calling program

all

_ARMACRO

open code enablement

calling program

all

_ARMSCL

SCL code enablement

calling program

all

ARM API Objects

The following three classes of objects are specified in the ARM API:

  • applications represent the systems that you are creating, such as an inventory or order entry application. Because the SAS interface to the ARM API provides totals on a per application basis, you might want to consider this when you define the scope of your application.

  • transaction classes specify a unit of work. You should create a transaction class for each major type of work that you want to create within an application. In concept, the transaction class is a template for the started transaction.

  • transaction instances specify the actual start time for a unit of work. Transaction instances have response time information that is associated with them.

The ARM API uses numeric identifiers or IDs to uniquely identify the ARM objects that are input and output from the ARM macro. The three different classes of IDs that correspond to the three ARM classes are

  • application IDs

  • transaction class IDs

  • start handles (start time) for transaction instances.

ID Management Using ARM Macros

These examples demonstrate how the ARM macros work. The ARM macros automatically manage application IDs, transaction IDs, and start handles. The default ID management works best in simple ARM call schemes. See 'Complex ARM Macro Call Schemes' on page 1057 for more information. By default, the ARM macros use IDs that were generated from the most recent macro call. The following example demonstrates how to use all of the ARM macros:

 /*global macro variable to indicate ARM macros are outside the data step*/  %let _armacro=1;      /* start of the application */  %arminit(appname='Sales App', appuser='userxyz');      /* define the transaction classes */  %armgtid(txnname='Sales Order', txndet='Sales Order Transaction');      /* more arm_getid function calls go here for different transaction classes */      /* start of a transaction */  %armstrt;  data _null_;      /* place the actual transaction code here */      /* update the status of the transaction as it is running */  %armupdt(data='Sales transaction still running...',maconly=no);  run;      /* place the actual transaction stop here */      /* the transaction has stopped */  %armstop(status=0);      /* end of the application */  %armend; 

All ID management is performed by the macros without requiring the calling program to track IDs. Each macro in the previous example uses the most recently generated ID values from previous macros. The following example is identical, but the comments explain the passing of IDs in more detail:

 %let _armacro=1;      /*      *  This %arminit macro will generate both a SAS      *  variable and global macro variable by the name      *  of _armapid and set it in the ID that is returned      *  from the arm_init() function call that is      *  wrapped by the macro.      */    %arminit(appname='Sales App', appuser='userxyz');      /*      *  This %armgtid macro uses the _armapid SAS variable      *  as input to the arm_getid() function call that it wraps.      *  It also generates both a SAS variable and global macro      *  variable by the name of _armtxid and sets them to the      *  ID that is returned from the arm_getid function call that      *  it wraps.      */   %armgtid(txnname='Sales Order', txndet='Sales Order Transaction');      /*      * Because we are still in the same DATA step, the %armstrt      * macro below will use the _armtxid SAS variable that is      * generated from the previous %armgtid macro as input      * to the arm_start() function call that it wraps. It      * also generates an _armshdl variable.      */    %armstrt;      /*      * The %armupdt call below uses the _armshdl SAS variable      * that is generated from the previous %armstrt macro.      */    %armupdt(data='Sales transaction still running...');      /*      * The armstop call also uses the same _armshdl SAS      * variable from the %armstrt.      */    %armstop(status=0);           /*      * The %armend call uses the _armapid SAS variable      * generated by the %arminit macro earlier to end      * the application.      */    %armend;  run; 

You can code the ARM macros across different DATA steps as follows and achieve the same results:

 data _null_;      /* note the end of the application */    %arminit(appname='Sales App', appuser=''userxyz');  run;  data _null_;    %armgtid(txnname='Sales Order', txndet='Sales Order Transaction');      /* more arm_getid calls go here for different transaction classes */  run;  data _null_;      /* note the start of the transaction */    %armstrt;      /* place the actual transaction here */  run;  data _null_;      /* update the status of the transaction as it is running */    %armupdt(data='Sales transaction still running...');  run;  data _null_;      /* place the actual transaction stop here */      /* note that the transaction has stopped */    %armstop(status=0);  run;  data _null_;      /* note the end of the application */    %armend;  run; 

The end result is the same as in the first example, except that the macros are using the generated macro variables rather than the SAS variables for passing IDs.

Complex ARM Macro Call Schemes

Allowing the macros to automatically use the global variables in basic scenarios simplifies coding. However, macros that use global variables can lead to misleading results in more complicated scenarios when you attempt to monitor concurrent applications or transactions as follows:

 data _null_;    %arminit(appname='App 1',getid=yes,txnname='txn 1');  run;      /* start transaction instance 1*/  data _null_;    %armstrt;  run;      /* start transaction instance 2 */  data _null_;    %armstrt;  run;      /* WRONG!  This assumes that the %armupdt is updating      *  the first transaction. However, it is actually updating the      *  second transaction instance because _armshdl contains the value      *  from the last macro call that was executed, which is the second      *  transaction.     */  data _null_;    %armupdt(data='txn instance 1 still running...');  run; 

To save the IDs use the *var options (APPIDVAR=, TXNIDVAR=, and SHDLVAR=) to pass or return the IDs in your own named variables. Here is an example that uses the SHDLVAR= option to save the start handles:

 data _null_;    %arminit(appname='xyz',getid=YES,txname='txn 1');  run;      /*  start transaction instance 1 and save the ID using shdlvar= */  data _null_;    %armstrt(shdlvar=savhdl1 );  run;      /*  start transaction instance 2 and save the ID using shdlvar= */  data _null_;    /*armstrt( shdlvar=savhd12 );  run;      /*  Now use the shandle= parameter after retrieving the first id. */  data _null_;    %armupdt(data='updating txn 1', shdlvar=savhdl1);  run;      /*  Use the same technique to stop the transactions */      /*  in the order they were started. */  data _null_;    %armstop(shdlvar=savhdl1);    %armstop(shdlvar=savhdl2);    %armend();  run; 

As the previous example shows, using the *var option simplifies the code. The previous technique is recommended for use on all ARM macro calls.

The following example demonstrates how to use all of the *var options to automatically manage IDs for concurrent applications, transaction classes, transaction instances, and correlated transaction instances:

 data _null_;    %arminit(appname='Appl 1', appuser='userid', appidvar=app1);    %arminit(appname='Appl 2', appuser='userid', appidvar=app2);    %arminit(appname='Appl 3', appuser='userid', appidvar=app3);  run;  data _null_;    %armgtid(txnname='Txn 1A', txndet='Txn Class 1A',             appidvar=appl,txnidvar=txnidvar=txn1a);    %armgtid(txnname='Txn 1B', txndet='Txn Class 1B',             appidvar=appl,txnidvar=txnidvar=txn1b);    %armgtid(txnname='Txn 2A', txndet='Txn Class 2A',             appidvar=app2,txnidvar=txnidvar=txn2a);    %armgtid(txnname='Txn 2B', txndet='Txn Class 2B',             appidvar=app2,txnidvar=txnidvar=txn2b);    %armgtid(txnname='Txn 3A', txndet='Txn Class 3A',             appidvar=app3,txnidvar=txnidvar=txn3a);    %armgtid(txnname='Txn 3B', txndet='Txn Class 3B',             appidvar=app3,txnidvar=txnidvar=txn3b);  run;  data _null_;    %armstrt(txnidvar=txn1a,shdlvar=sh1a);    %armstrt(txnidvar=txn1b,shdlvar=sh1b);    %armstrt(txnidvar=txn2a,shdlvar=sh2a);    %armstrt(txnidvar=txn2b,shdlvar=sh2b);    %armstrt(txnidvar=txn3a,shdlvar=sh3a);    %armstrt(txnidvar=txn3b,shdlvar=sh3b);  run;  data _null_;    %armupdt(data='Updating txn instance 1a...', shdlvar=sh1a);    %armupdt(data='Updating txn instance 1b...', shdlvar=sh1b);    %armupdt(data='Updating txn instance 2a...', shdlvar=sh2a);    %armupdt(data='Updating txn instance 2b...', shdlvar=sh2b);    %armupdt(data='Updating txn instance 3a...', shdlvar=sh3a);    %armupdt(data='Updating txn instance 3b...', shdlvar=sh3b);  run;  data _null_;    %armstop(status=0, shdlvar=sh1a);  %armstop(status=1, shdlvar=sh1b);    %armstop(status=0, shdlvar=sh2a);  %armstop(status=1, shdlvar=sh2b);    %armstop(status=0, shdlvar=sh3a);  %armstop(status=1, shdlvar=sh3b);  run;  data _null_;    %armend(appidvar=app1);    %armend(appidvar=app2);    %armend(appidvar=app3); run; 

As the previous example demonstrates, you can establish your own naming conventions to uniquely identify applications, transaction classes, and transaction instances across different DATA steps, in open code, or in SCL programs.

The macros support explicit passing of the IDs using the APPID=, TXNID=, and SHANDLE= options. These options are similar to the *var options, except that they do not retrieve values across DATA steps using macro variables. The primary use of the options is to supply numeric constants as ID values to the macros, because the *var options do not accept numeric constants.

Note: The use of APPID=, TXNID=, and SHANDLE= is not recommended for new applications. These options are maintained for compatibility with earlier ARM macro releases only. Use APPIDVAR=, TXNIDVAR=, and SHDLVAR= instead of APPID=, TXNID=, and SHANDLE=, respectively.

Because IDs are generated by the ARM agent, to pass a numeric literal requires that you start a new SAS session. If any SAS subsystems are also functioning, you will not know what the ID will be at execution time.

The use of APPIDVAR=, TXNIDVAR=, and SHDLVAR= options is recommended when coding new applications.




SAS 9.1 Language Reference Dictionary, Volumes 1, 2 and 3
SAS 9.1 Language Reference Dictionary, Volumes 1, 2 and 3
ISBN: N/A
EAN: N/A
Year: 2004
Pages: 704

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net