File: //opt/perf/examples/arm/armsample4.c
/*****************************************************************************/
/* armsample4 Application Response Measurement sample AUG01 */
/* */
/* This program provides an example of using User-Defined Metrics in ARM */
/* calls. Different metric values can be passed through arm_start, */
/* arm_update, and arm_stop calls. Alternatively, arm_complete_transaction */
/* can be used where a tran cannot be delimited by start/stop calls. */
/*****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifndef _WIN32
#include <unistd.h>
#endif
#include <arm.h>
/* Define macros so sleep works on NT. */
#ifdef _WIN32
#define sleep(n) Sleep(1000*(n))
#endif
/* Separate definition of int64 for NT and UNIX */
#ifdef _WIN32
typedef _int64 int64 ;
#else
#ifndef AIX53_64
typedef long long int64 ;
#endif
#endif
arm_appl_id_t metric_appl_id = -1; /* application id */
arm_tran_id_t metric_tran_id = -1; /* transaction id */
int mycounter = 0;
/*****************************************************************************/
/* init_metric_application */
/* Register transaction with meta-data for User-Defined Metrics (UDMs) */
/* The data buffer input to arm_getid defines the number, names and types */
/* UDM data later passed into the arm_start, _update, and _stop calls */
/* as well as arm_complete_transaction. */
/*****************************************************************************/
void init_metric_application(void)
{
arm_user_data101_t *buf_ptr, buf = {
101,
{0, ARM_AllMetrics_f | ARM_String1_f ,0 ,0},
{{1, "Metric 1 - Type 1 is a COUNTER32 "},
{4, "Metric 2 - Type 4 is a GAUGE32 "},
{5, "Metric 3 - Type 5 is a GAUGE64 "},
{9, "Metric 4 - Type 9 is a STRING8 "},
{3, "Metric 5 - Type 3 is a COUNTER32/DIVISOR32"},
{8, "Metric 6 - Type 8 is a NUMERICID64 "},
{10, "The last field is always a STRING32 "}
}};
arm_data_sz_t buf_sz;
buf_ptr = &buf;
buf_sz = sizeof(buf);
metric_appl_id=arm_init("Metric_Application", /* application name */
"*", /* use default user */
0,0,0); /* reserved */
metric_tran_id = arm_getid(metric_appl_id, /* appl_id from arm_init */
"Metric_transaction", /* transaction name */
"Transaction in Metric application",
0, /* reserved */
(arm_data_t *)buf_ptr, /* buffer with meta-data */
buf_sz); /* buffer size */
printf("metric_tran_id = %-d, processing transactions...\n", metric_tran_id);
return;
} /* init_metric_application */
/*****************************************************************************/
/* metric_transaction */
/* Procedure executed in main-line application code repeatedly for each */
/* transaction instance. */
/*****************************************************************************/
void metric_transaction(int trannumber)
{
arm_start_handle_t metric_tran_handle = -1;
arm_user_data1_t *buf_ptr, buf;
arm_data_sz_t buf_sz;
buf_ptr = &buf;
buf_sz = sizeof(buf);
buf_ptr->format = 1;
buf_ptr->flags[0] = 0;
buf_ptr->flags[1] = ARM_AllMetrics_f | ARM_String1_f;
/* initial metric values: in this example, somewhat arbitrary */
buf_ptr->metric[0].counter32 = ++mycounter;
buf_ptr->metric[1].gauge32 = 9;
#ifdef ARM_INT64
buf_ptr->metric[2].gauge64 = 1000000 * trannumber;
#else
buf_ptr->metric[2].gauge64.upper = 123;
buf_ptr->metric[2].gauge64.lower = 321;
#endif
strcpy(buf_ptr->metric[3].string8, "aaaaaaaa");
buf_ptr->metric[4].cntrdivr32.count = mycounter;
buf_ptr->metric[4].cntrdivr32.divisor = 100;
#ifdef ARM_INT64
buf_ptr->metric[5].numericid64 = trannumber;
#else
buf_ptr->metric[5].numericid64.upper = 123;
buf_ptr->metric[5].numericid64.lower = 321;
#endif
strcpy(buf_ptr->string32,"This is a 32 character string ");
metric_tran_handle = arm_start(metric_tran_id, /* tran_id from arm_getid */
0, /* reserved */
(arm_data_t *)buf_ptr, /* metrics buf ptr */
buf_sz); /* user metric buffer size */
/* This is where some normal processing in a real application would occur */
sleep(1);
/* now change metrics for this transaction instance slightly */
/* prior to calling arm_update */
buf_ptr->metric[1].gauge32 = -37;
strcpy(buf_ptr->string32,"This is a NEW CHARACTER STRING ");
arm_update(metric_tran_handle, /* transaction handle from arm_start */
0, /* reserved for future use */
(arm_data_t *)buf_ptr, /* user metrics buffer pointer */
buf_sz); /* user metric buffer size */
/* This is where some normal processing in a real application would occur */
sleep(1);
/* now change metrics prior to calling arm_stop */
buf_ptr->metric[0].counter32 = ++mycounter;
buf_ptr->metric[1].gauge32 = trannumber;
#ifdef ARM_INT64
buf_ptr->metric[5].numericid64 = trannumber;
#else
buf_ptr->metric[5].numericid64.upper = 123;
buf_ptr->metric[5].numericid64.lower = 321;
#endif
arm_stop(metric_tran_handle, /* transaction handle from arm_start */
ARM_GOOD, /* successful completion define = 0 */
0, /* reserved for future use */
(arm_data_t *)buf_ptr, /* user metrics buffer pointer */
buf_sz); /* user metric buffer size */
/* To demonstrate how the arm_complete_transaction call might be used, */
/* we will do another transaction instance for the same transaction id. */
/* The arm_complete_transaction call is like doing an arm_stop without */
/* needing to do a arm_start first. The response time is passed in */
/* explicitly as opposed to being calculated by the ARM agent as the */
/* wall time between start and stop. */
/* Another way of looking at this is that arm_complete_transaction is */
/* to be used as an alternative to doing arm_start/arm_stop: to be used */
/* when you cannot make the arm_start call (perhaps because the start */
/* occurs in a different process context, but the transaction response */
/* time available to the program (so arm_start is not needed). */
/* change some metrics prior to calling arm_complete_transaction: */
buf_ptr->metric[0].counter32 = ++mycounter;
buf_ptr->metric[1].gauge32 = -trannumber;
#ifdef ARM_INT64
buf_ptr->metric[2].gauge64 = -(1000000 * trannumber);
#else
buf_ptr->metric[2].gauge64.upper = 321;
buf_ptr->metric[2].gauge64.lower = 123;
#endif
arm_complete_transaction((char *)&metric_tran_id, /* pointer to tran id */
NULL, NULL, /* unimplemented fields */
ARM_GOOD, /* completion status */
(int64) 500000000, /* response time */
/* 500 million nanoseconds == .5 seconds */
NULL, 0, /* unimplemented fields */
(arm_data_t *)buf_ptr, /* UDM buffer pointer */
buf_sz); /* UDM buffer size */
} /* metric_transaction() */
/*****************************************************************************/
/* Main */
/*****************************************************************************/
int
main(void)
{
int iteration = 1;
init_metric_application();
/* loop for quite a long time... */
while (iteration < 1000)
{
metric_transaction(iteration++);
}
return 0;
}