A.2 Referenced Types

A.2.1 FieldFilter

A FieldFilter object is used to include or exclude an HVEvent based on the value of one of its fields. All fields in this object are required. In addition, the regex field must contain a valid regular expression as described here:

http://java.sun.com/javase/6/docs/api/java/util/regex/Pattern.html.

The fieldName value is normally one of standard field names described in metrics.constants Field Names. However, custom field names created with a FieldXform can be used. HVEvents not containing a value in the field specified by fieldName never match the filter.

var appsCollector = metrics.createSummaryCollector();

var testFilter = metrics.createFieldFilter();
testFilter.name = 'testFilter';
testFilter.fieldName = metrics.constants.FN_APPLICATION_NAME;
testFilter.regex = 'TEST.*';
if(testFilter.isValid())
{
   appsCollector.exclusionFilters=[testFilter]; //exclude test events
}
else
{
  bem.logWarning('Test filter not valid:' + testFilter.toString());
}

Properties

Property Name

Value Type

Description

name

String

(Required) Name of the filter.

fieldName

String

(Required) Name of the field the filter operates on.

Methods

Boolean isValid()

Returns True if all required fields are populated and the expression fields contains a valid regular expressions.If False is returned, the scripting log contains a description of the failure.

String toString()

Returns a string representation of this event.

A.2.2 FieldXform

A FieldXform object is used to normalize data values in an HVEvent object. The name, fieldName, matchExpression, and replaceExpression fields in this object are required. In addition, the matchExpression field must contain a valid regular expressions as described here:

http://java.sun.com/javase/6/docs/api/java/util/regex/Pattern.html.

The replaceExpression can contain both literal data, as well as references to captured substrings from the matchExpression. Capture references are referenced using a dollar sign ($) followed by the index of the desired capture field, starting with index 1 to indicate the first capture field. A literal dollar sign must be preceded with a backslash to indicate that it is not a capture reference. The fieldName value is normally one of standard field names described in metrics.constants Field Names. However, custom field names created with a previous FieldXform can be used. HVEvents not containing a value in the field specified by fieldName never match.

When an HVEvent is applied to a FieldXForm, the FieldXForm compares the value of the specified field with its matchExpression. If the value does not match the expression, then no changes are made to the HVEvent. The the value does match, then the replaceExpression is used to transform the value, and if specified, the caseRule is used to normalize the case of the transformed value. The resulting value is then save to the destination field, or if not specified, back to the field from which the source value was taken.

The following example for FieldXform is from the DemoMetrics.js script included in the Experience Manager installation. It is designed to identify the same page across multiple hosts, while suppressing any parameters passed to the page.

var ulx= metrics.createXform('URLKey Xform');
ulx.fieldName=metrics.constants.FN_URL;
ulx.matchExpression='http[s]?://[^/]+([^#\?]+).*';
ulx.replaceExpression='$1';
ulx.destFieldName='urlKey';
ulx.caseRule=metrics.constants.CASE_TO_LOWER;

It evaluates the URL field in the HVEvent against the match expression:

http[s]?://[^/]+([^#\?]+).*

Table A-1 lists the regular expressions, and describes how the configured matchExpression is interpreted.

Table A-1 matchExpression Interpretations

Match Characters

Interpretation

 http

Matches only the literal string http.

 [s]?

Matches 0 or one “s” in this position.

 ://

Matches only the literal string “://” in this position.

 [^/]+

Matches one or more of any character up to but not including the / character.

 ([^#\?]+)

Matches one or more of any character up to but not including # or ? characters.

The parentheses mark this section as a capture field that is referenced in replaceExpression.

 .*

Matches any number of trailing characters of any type.

Based on this match expression, the xform saves the value of the first capture field ($1), converts it to lower case, then saves it to a custom HVEvent field called urlKey. Table A-2 shows sample URL values and the resulting urlKey values produced by this xform:

Table A-2 Sample URL and resulting urlKey values for the xform of the matchExpression example

URL

UrlKey

http://www.netiq.com/products/experience-manager/

/products/experience-manager/

http://localhost:8080/Plugins/invoke.pl?op=threadDump

/plugins/invoke.pl

http://us.mc1102.mail.yahoo.com/mc/welcome?.gx=1&.tm=1250689315&.rand=3hsbmdsrkkmg6

/mc/welcome

This approach obviously does not work for all Web sites. You should come up with your own schemes for normalizing data into useful values.

Properties

Property Name

Value Type

Description

name

String

(Required) Name of the Xform.

fieldName

String

(Required) Name of the field to be read by the Xform.

matchExpression

String

(Required) Regular expression describing field values that should be transformed.

replaceExpression

String

(Required) A regular expression describing how to transform values that match the matchExpression.

destFieldName

String

Name of the field where transformed data should be written.

caseRule

Object

(Rule for changing the case of matching fields.

generalProperties

java.util.Map

Other properties for the alarm.

Methods

Boolean isValid()

Returns True if all required fields are populated and the expression fields contains a valid regular expressions.If False is returned, the scripting log contains a description of the failure.

String toString()

Returns a string representation of this event.

A.2.3 HVEvent

An HVEvent object represents a single hit by a user on a single Web page. All properties in this object are read-only. Fields in the event have undergone any transformations implemented in the preprocessor. The get() method can be used to access any custom fields produced by xforms.

Under normal circumstances, the vast majority of events received by a monitor are discarded after processing in order to conserve system resources. However, sampling data collectors capture and report a percentage of these events as HVEvent objects. Summary reports also include a reference to a single HVEvent object, provided for reference purposes.

// Calculate the median response time from sampled events
function calculateMedian(events)
{
    var median =0;
    if(events.length > 1)
    {
       var values = new Array();
       for(var i=0; i< events.length; i++)
       {
          values.push(events[i].responseTime);
       }
       values.sort(sortOrder);
       var mid = Math.floor(values.length/2);
       if((values.length % 2) == 0)
       {
         median = (values[mid-1]+values[mid])/2;
       }
       else
       {
          median = values[mid];
       }
    }
    else if(events.length == 1)
    {
       median = events[0].responseTime;
    }
    return median;
}
// ensures sorting by numeric order instead of the default alpha sort
function sortOrder(a,b)
{
   return a-b;
}

Properties

Property Name

Value Type

Description

appName

String

The appName parameter from the instrumentation script that generated this event.

clientIP

String

The IP address of the system that delivered this event to the Monitor.

downloadTime

integer

The reported interval between initialization of the current page and final rendering (in milliseconds).

timestamp

java.util.Date

The time when this event was received by the Monitor.

responseTime

integer

The downloadTime+uploadTime, or downloadTime if uploadTime is out of range. This is the value used in SummaryStats calculations.

title

String

The document title of the page that produced this event.

uploadTime

String

The reported interval between unload of previous page and current page initialization.

URL

String

The URL of the page that produced this event.

userAgent

String

The userAgent value reported by the browser that sent this event.

Methods

String get(String fieldName)

Retrieves the value of a named field.

String toString()

Returns a string representation of this event.

A.2.4 MetricAlarm

A MetricAlarm object represents an alert to be sent to a remote system. This is a general purpose mechanism and the necessary content of the alarm is based on the needs of the system receiving the alarm. (HVM does not currently support Operations Center alarms.)

metrics.onMemberRefused=handleRefused;

function handleRefused(memberData)
{    
   var alarm = metrics.createTecAlarm();
   alarm.id= memberData.id.hashCode();
   alarm.appName='HVM Group Status';
   alarm.timestamp = new java.util.Date();
   alarm.severity = metrics.constants.SEV_CRITICAL;
   alarm.description= memberData.id + ' refused control by ' + metrics.getLocalMember().id;
   metrics.sendAlarm(alarm);
}

Properties

Property Name

Value Type

Description

appName

String

(Required) Name of the application to which this alert applies.

collectorName

String

Name of the collector this alert is associated with.

timestamp

java.util.Date

(Required) Time when this alert occurred.

severity

String

(Required) Severity of the alarm (see mtrics.constants Severities).

description

String

Description of the alarm.

id

String

(Required) Identifier for this alert.

generalProperties

java.util.Map

Other properties for the alarm.

Methods

Boolean isValid()

Returns True if object contains all required data and all provided data is valid. If False is returned, the logs include details of the error.

String toString()

Returns a string representation of this event.

A.2.5 MetricsElement

A MetricsElement object represents an element on the Operations Center server under the Elements/Experience Manager_adapter/Metrics/ branch. When a MetricsElement object is received by the Experience Manager adapter on the Operations Center server, the MetricsElement data is used to create or update the Operations Center Element. The elementKeys property specifies the relative path from Elements/Experience Manager_adapter/metrics/. So, if you specify elementKeys ['Page Stats', 'Home Page'], then the MetricsElement object creates or updates Elements/Experience Manager_adapter/metrics/Page Stats/Home Page.

It is not necessary to create “Page Stats” prior to creating “Home Page”; if a nonexistent element is referenced in the element hierarchy, it is created automatically. The condition and message properties are used to update the corresponding fields on the Operations Center element.

The seriesData property is used to capture metric data that you wish to record over time. When you select the Performance tab for the Operations Center element you have created, any series data types you have populated should show in the Performance Properties panel of the display.

The properties property is used to populate the metrics properties page (right-click Properties > Metrics) for the element. After a metrics property has been added to an element, it remains there until the element has been removed, or the property is deleted. To delete a property, you can set its value to null (for example, 'elem.properties.put('somePropertyName', null);'). Alternatively, if you set isPropertySetComplete to True, then any properties not included in the MetricsElement object is removed.

 var collector = metrics.createSummaryCollector('Page Stats', 60000, processPageStats);
 collector.groupingFieldNames=[metrics.constants.FN_PAGE_TITLE];
 var targetRange = metrics.createResponseTimeRange('target', 0, 1500);
 var acceptRange = metrics.createResponseTimeRange('accept', 1500, 4000);
 var problemRange = metrics.createResponseTimeRange('problem', 4000, 60000);
 
 collector.ranges=[targetRange,acceptRange,problemRange];
 
 // ... add other collector props and deploy
 
 /*
  * Process reports generated by the Page Stats collector
  */
 function processPageStats(reports)
 {
    for(var i=0; i < reports.length;i++)
    {
       var report = reports[i];
       // create element and automatically map stats into series data.
       var elem = metrics.createMetricsElement()
       elem.elementKeys=[report.key.collectorName, report.key.groupValues[0]];
       assignConditonAndMessage(elem, report);
       elem.seriesData = createSeriesEntries(report);
       elem.properties.put('Reference URL', report.lastEvent.URL);
       elem.properties.put('Page Title', report.lastEvent.title);
       elem.properties.put('Hit Count', report.overall.count);
       // mine other properties ..
       metrics.sendMetricsElement(elem);     
    }
 }
 
 
 /*
  * calculate element condition based on relative hit count
  */
 function assignConditonAndMessage(elem,report)
 {
    var targetHits = getRangeHitCount(report,'target');
    var acceptHits = getRangeHitCount(report,'accept');
    var problemHits = getRangeHitCount(report,'problem');
    
    if(targetHits > acceptHits + problemHits)
    {
       elem.condition=metrics.constants.SEV_OK;
       elem.message = 'Performance target achieved';
    }
    else if (targetHits  > problemHits || acceptHits > problemHits)
    {
       elem.condition = metrics.constants.SEV_MINOR;
       elem.message = 'Performance acceptable';
    }
    else if (targetHits + acceptHits > problemHits)
    {
       elem.condition = metrics.constants.SEV_MAJOR;
       elem.message = 'Performance degraded';
    }
    else 
    {
       elem.condition = metrics.constants.SEV_CRITICAL;
       elem.message = 'Performance violation';
    }
    elem.message += ': T=' + targetHits + ' A='+ acceptHits + ' P=' + problemHits;
 }
 
 /*
  * Return hit count if range has data, or 0 if it does not
  */
 function getRangeHitCount(report, rangeName)
 {
    var hitCount = 0;
    var rangeStats = report.rangeStats.get(rangeName);
    if(rangeStats != null)
    {
       hitCount =  rangeStats.count;
    }
    return hitCount;
 }
 
 /*
  * Create Series entries for this report
  */
 function createSeriesEntries(report)
 {
    var seriesData = new Array();
      
    var avg=metrics.createSeriesData();
    avg.name = 'Overall:Avg';
    avg.timestamp = report.stopTime;
    avg.value = report.overall.average;
    seriesData.push(avg);
        
    seriesData.push(metrics.createSeriesData('Overall:Max',
                     report.stopTime,report.overall.high));
    seriesData.push(metrics.createSeriesData('Overall:Min',
                     report.stopTime,report.overall.low));
    seriesData.push(metrics.createSeriesData('Overall:Count',
                     report.stopTime,report.overall.count));
        
    var iterator = report.rangeStats.entrySet().iterator();
    while(iterator.hasNext())
    {
        var mapEntry = iterator.next();
        var rangeName = mapEntry.getKey();
        var rangeStats = mapEntry.getValue();
        seriesData.push(metrics.createSeriesData(rangeName +':Avg',
                           report.stopTime,rangeStats.average));
        seriesData.push(metrics.createSeriesData(rangeName +':Max',
                           report.stopTime,rangeStats.high));
        seriesData.push(metrics.createSeriesData(rangeName +':Min',
                           report.stopTime,rangeStats.low));
        seriesData.push(metrics.createSeriesData(rangeName +':Count',
                            report.stopTime,rangeStats.count));
    }
    return seriesData;
}

Properties

Property Name

Value Type

Description

elementKeys

String

(Required) The elementKeys array holds the element’s hierarchy relative to Elements/Experience Manager_adapter/metrics/.

condition

String

The condition (OK, MAJOR, CRITICAL, and so on) to assign to this element. If set, the value must one of the constants described in metrics.constants Severities.

message

String

The title bar message for this element that contains a short description.

seriesData

SeriesData[]

Array of time points to record with this element.

properties

java.util.Map

Property name/value pairs to be exposed on the element’s Properties page.

isPropertySetComplete

Boolean

True/false indicator that impacts how properties are applied to a preexisting element.

Methods

Boolean isValid()

Returns True if object contains all required data and all provided data is valid. If False is returned, the logs include details of the error.

String toString()

Returns a string representation of this event.

A.2.6 MetricsMember

A MetricsMember object refers to a Experience Manager monitor that is a member of an HVM group. Instances of this object are returned by the metrics.getLocalMember() and metrics.getAllMembers and are passed as arguments to metrics.onMemberConnect, metrics.onMemberDisconnect and metrics.onMemberRefused event-handlers.

var members = metrics.getAllMembers();
for(var i=0; i < members.length; i++)
{
   var elem = metrics.createMetricsElement();
   elem.elementKeys = ['groupStatus', members[i].id];
   elem.properties.put('Is Controller', !members[i].isRemote);
   elem.properties.put('Is Connected' , members[i].isConnected());
   elem.condition=metrics.constants.SEV_MINOR;
   elem.isPropertySetComplete=false;
   metrics.sendMetricsElement(elem);   
}

Properties

Property Name

Value Type

Description

id

String

(Read-only) MetricsMember.id is a read-only property that uniquely identifies a group member. The format of this identifier matches the format of the member in the HVMetrics.group.members property.

isRemote

Boolean

(Read-only) MetricsMember.isRemote is a read-only property that indicates whether the referenced member is the local system or a remote monitor.

Methods

Boolean isConnected()

MetricsMember.isConnected() indicates whether connectivity between the local controller and this member is established.

A.2.7 Preprocessor

Preprocessor objects are responsible for normalizing and filtering HVEvent objects before they are processed by data collectors. A deployed preprocessor is the first to handle event data coming in from the browser. First, it populates the response time field by adding the provided upload time and download time values. However, if the provided upload time is greater than the specified uploadTimeLimit, the upload time value is ignored and the response time will equal the download time.

After the deployed preprocessor populates the response time, it performs data transformations as specified by any included xforms. If multiple xforms are specified, they are applied in the sequence that they appear in the array. Following that, filters are applied. Any event matching a preprocessor filter is excluded from further processing.

// filter out local subnet to prevent skew.
 var subnetFilter= metrics.createFieldFilter(  
     'ipFilter', 
     metrics.constants.FN_CLIENT_IP, 
     '192.168.1.*');
 var ieXform = metrics.createXform(
     'IE xform', 
     metrics.constants.FN_USER_AGENT, 
     '(.*)(MSIE[^;]*)(.*)', 
     '$2',
     'browserVersion',
     metrics.constants.CASE_TO_LOWER);
 var ffXform = metrics.createXform(
     'Firefox xform', 
     metrics.constants.FN_USER_AGENT, 
     '(.*)(Firefox\\S*)(.*)', 
     '$2',
     'browserVersion',
     metrics.constants.CASE_TO_LOWER);     
 var preproc = metrics.createPreprocessor();
 preproc.uploadTimeLimit=2000;
 preproc.xforms=[ieXform,ffXform];
 preproc.filters=[subnetFilter];

Properties

Property Name

Value Type

Description

uploadTimeLimit

integer

(Recommended) Maximum uploadTime value (ms) that is included in response time calculation.

FieldXform[]

xforms

Transformers to be applied to the incoming fields. Transformations are performed in the provided order and are done after response time calculation.

FieldFilter

filter

Filters to describe any events that should be ignored. An event that matches any filter in the preprocessor is ignored.

Methods

String toString()

Returns a string description of the preprocessor.

Boolean isValid()

Returns True if all included xforms and filters are valid.

A.2.8 ReportKey

A ReportKey object is used to identify a SummaryReport or SamplingReport produced by a data collector. The report key ties the associated report to a particular collector and a particular set of grouping values within that collector. Refer to the associated report type for more information.

Properties

Property Name

Value Type

Description

collectorName

String

(Read-only) Name of the data collector that produced the report.

type

String

The type of the data collector (Sampling or Summary).

groupValues

String[]

Values of the grouping fields that provide the scope of this report.

Methods

String toString()

Returns a string representation of this object.

A.2.9 ResponseTimeRange

ResponseTimeRange objects are used to refine data collectors to track hits where the response time falls within the specified range values. Each defined response time range on a dta collector reports a discreet count, average/high/low response time of hits that fell within the range.

The following example demonstrates how one might derive series data from a report. The implementation shown here mirrors the default series data created when default series data mapping is enabled using the metrics.createMetricsElement() method.

var targetRange = metrics.createResponseTimeRange('target', 0, 1500);
var acceptRange = metrics.createResponseTimeRange('accept', 1500, 4000);
var problemRange = metrics.createResponseTimeRange('problem', 4000, 60000);

var appsCollector = metrics.createSummaryCollector();
appsCollector.ranges=[targetRange,acceptRange,problemRange];

Properties

Property Name

Value Type

Description

name

String

(Required) Name of the range. This value tracks through to the report.

lowTime

integer

(Required) Minimum response time to include in this ranges report (inclusive).

highTime

integer

(Required) Maximum response time to include in this ranges report (exclusive).

Methods

String toString()

Returns a string description of the ResponseTimeRange.

Boolean isValid()

Returns True if all values are populated and lowTime <= highTime.

A.2.10 SeriesData

A SeriesData object is used to capture a data point for historical tracking. These objects must be associated MetricsElement to be sent to Operations Center. The Operations Center server does not process updates to the same name and time stamp value on the same element. If the value should be kept for a longer of shorter period than the default retention period set in the Experience Manager Adapter properties use expiryDays to override.

function createSeriesEntries(report)
{
   var seriesData = new Array();
      
   var avg=metrics.createSeriesData();
   avg.name = 'Overall:Avg';
   avg.timestamp = report.stopTime;
   avg.value = report.overall.average;
   seriesData.push(avg);
      
   seriesData.push(metrics.createSeriesData('Overall:Max',
                    report.stopTime,report.overall.high));
   seriesData.push(metrics.createSeriesData('Overall:Min',
                    report.stopTime,report.overall.low));
   seriesData.push(metrics.createSeriesData('Overall:Count',
                    report.stopTime,report.overall.count));
      
   var iterator = report.rangeStats.entrySet().iterator();
   while(iterator.hasNext())
   {
       var mapEntry = iterator.next();
       var rangeName = mapEntry.getKey();
       var rangeStats = mapEntry.getValue();
       seriesData.push(metrics.createSeriesData(rangeName +':Avg',
                          report.stopTime,rangeStats.average));
       seriesData.push(metrics.createSeriesData(rangeName +':Max',
                          report.stopTime,rangeStats.high));
       seriesData.push(metrics.createSeriesData(rangeName +':Min',
                          report.stopTime,rangeStats.low));
       seriesData.push(metrics.createSeriesData(rangeName +':Count',
                           report.stopTime,rangeStats.count));
   }
   return seriesData;
}

Properties

Property Name

Value Type

Description

name

String

(Required) Name of the data item.

timestamp

java.util.Date

(Required) Time stamp for the data item.

Number

value

(Required) Value of the data item.

expiryDays

integer

Number of days this item should be kept in the active database for reporting.

Methods

String toString()

Returns a string description of the object.

Boolean isValid()

Returns True if all required fields are populated. If False is returned, the scripting log contains a description of the failure.

A.2.11 SummaryDataCollector

SummaryDataCollector objects are used to analyze the HVEvent stream and periodically produce summary reports describing the content of the event stream. These objects are generally created using one of the metrics.createSummaryCollector() methods and deployed in the implementation of an metrics.onload event-handler.

If the collector is deployed, every HVEvent that gets past the preprocessor is analyzed by it. First, the event is checked against inclusionFilters and exclusionFilters. If any inclusionFilters are defined, then an event must match at least one of them, or it is excluded. A match to an exclusionFilter also causes the event to be excluded. If an event passes the filters, the event is included in the next set of interval reports generated by this collector.

Collectors generate reports at the frequency specified by the intervalDuration property and delivered to the function specified by the onreport property. Separate reports are generated for each unique set of grouping field values and include all recorded activity for all HVEvent objects with the same set of grouping field values. After reports are delivered to the handler, the collector forgets that information, so if a given set of grouping field values has no activity in the next interval, no report is generated for it.

In a distributed HVM environment, identical collectors are deployed to all members of the HVM group. At the end of each interval, reports are collected from all HVM members and their content is consolidated into a single set of reports. For example, if a data collector specified page title as the sole grouping field and at the end of the interval HVMGroupMember1 reported the following statistics for the page called 'User Login':

  •      count= 293
  •      average=1372
  •      high=3599
  •      low=141

and HVMGroupMember2 reported the following for the same page:

  •      count= 311
  •      average=1821
  •      high=3801
  •      low=221

Then the report delivered to the onreport event handler can contain the following:

  •      report.key.groupValues=['User Login']
  •      report.overall.count=604
  •      report.overall.average=1603
  •      report.overall.high=3801
  •      report.overall.low=221
  •      report.reportingMonitors=[ 'HVMGroupMember1:6789', 'HVMGroupMember2:6789']

This consolidation of reports with the same key and interval values is automatic in a distributed HVM configuration. On occasion, a remote monitor can also deliver a report from a previous interval, because some transient condition prevented it from reporting when that interval’s data was processed (see Distributed High-Volume-Metrics Data Collection). In this situation, the stale report data (data from an earlier interval) can be rolled into the current interval’s data, reported to the event handler as a separate report for the old interval, or filtered out entirely. The value of the staleReportOptions property determines the behavior. Appropriate values are described in metrics.constants Stale Report Options.

var appFilter = metrics.createFieldFilter('Banking Filter', 
          metrics.constants.FN_APPLICATION_NAME, 
          'BANKING');
var devSystemFilter = metrics.createFieldFilter('Dev System Filter',
          metrics.constants.FN_URL,
          'http://DEV.*');
          
var targetRange = metrics.createResponseTimeRange('target', 0, 1500);
var acceptRange = metrics.createResponseTimeRange('accept', 1500, 4000);
var problemRange = metrics.createResponseTimeRange('problem', 4000, 60000);
var collector = metrics.createSummaryCollector();
collector.name= 'Banking';
collector.intervalDuration=60000;
collector.onreport=processBanking;
collector.groupingFieldNames=[metrics.constants.FN_PAGE_TITLE];
collector.ranges=[targetRange,acceptRange,problemRange];
collector.inclusionFilters=[appFilter];
collector.exclusionFilters=[devSystemFilter];
collector.staleReportOption=metrics.constants.SRO_PASS;

// deploy with preprocessor and other collectors.

function processBanking(reports)
{
  // do Banking application processing
}

Properties

Property Name

Value Type

Description

name

String

(Required) Name of the collector.

intervalDuration

interval

(Required) Frequency with which the collector should produce reports, specified in milliseconds.

onreport

Function

(Required) Is used to specify the event-handler to be called when the collector has reports to be processed. The expected handler signature is void yourHandlerName(SummaryReport[] reports).

groupingFieldNames

String[]

List of HVEvent field names whose unique values will produce a discrete report.

inclusionFilters

FieldFilter[]

List of filters that an HVEvent must match in order to be included in this collector’s reports.

exclusionFilters

FieldFilter[]

List of filters that an HVEvent might not match if it is to be included in this collector’s reports.

ranges

ResponseTimeRange[]

List of ranges for which a discrete set of statistics should be maintained.

staleReportOption

String[]

Instruction indicating how stale reports should be handled in a distributed metrics environment.

Methods

Boolean isValid()

Returns True if all required values are populated and all populated values are valid.

String toString()

Returns a string description of the SummaryDataCollector.

A.2.12 SummaryReport

SummaryReport objects are used to report on activity captured within a reporting interval. Deployed SummaryCollector objects generate a separate report for each unique set of grouping field values and pass them to the collector’s onreport event handler. The key.groupValues property specifies the set of unique values that define the scope of the report. If the collector does not define any grouping fields, it produces a single report per interval in which it saw activity with no specified key.groupingValues.

Each report instance captures the overall statistics, as well as statistics for any defined ranges where at least one hit fell within the range’s constraints. Report data is not generated for grouping values that saw no activity or for ResponseTimeRanges that saw no activity.

Example

The following example defines a SummaryCollector with a one-minute interval for which it reports any activity observed to the processPageStats function. This collector groups information by page title, so for each unique page title appearing in an HVEvent during the interval, the collector generates a report, with the name of the page being reported on specified in report.key.groupValues[0].

As this custom handler receives these reports, it generates metrics elements that appear on a connected Operations Center server. As this script is written, the element name matches the page title, and appears under Elements > Experience Manager_adapter > Metrics > Page Stats > page_title in the element tree. The properties page for this element then has data mined from the Summary Reports. (It can presumably also have Series data showing a history of the page performance, but that logic is omitted here for simplicity.)

This example uses custom logic for driving the condition of the element. The collector defines a set of ranges that presumably have business meaning in the context of the site being monitored. Based on the relative number of hits in each of these ranges, the script assigns an appropriate condition and message (description) for the element.

var collector = metrics.createSummaryCollector('Page Stats', 60000,
                processPageStats);
collector.groupingFieldNames=[metrics.constants.FN_PAGE_TITLE];
var targetRange = metrics.createResponseTimeRange('target', 0, 1500);
var acceptRange = metrics.createResponseTimeRange('accept', 1500, 4000);
var problemRange = metrics.createResponseTimeRange('problem', 4000, 60000);

collector.ranges=[targetRange,acceptRange,problemRange];

// ... add other collector props and deploy

function processPageStats(reports)
{
   for(var i=0; i < reports.length;i++)
   {
      var report = reports[i];
      // create element and automatically map stats into series data.
      var elem = metrics.createMetricsElement()
      elem.elementKeys=[report.key.collectorName, report.key.groupValues[0]];
      assignConditonAndMessage(elem, report);
      elem.properties.put('Reference URL', report.lastEvent.URL);
      elem.properties.put('Page Title', report.lastEvent.title);
      elem.properties.put('Hit Count', report.overall.count);
      // mine other properties ..
      metrics.sendMetricsElement(elem);
      
   }
}

/*
 * calculate element condition based on relative hit count
 */
function assignConditonAndMessage(elem,report)
{
   var targetHits = getRangeHitCount(report,'target');
   var acceptHits = getRangeHitCount(report,'accept');
   var problemHits = getRangeHitCount(report,'problem');
   
   if(targetHits > acceptHits + problemHits)
   {
      elem.condition=metrics.constants.SEV_OK;
      elem.message = 'Performance target achieved';
   }
   else if (targetHits  > problemHits || acceptHits > problemHits)
   {
      elem.condition = metrics.constants.SEV_MINOR;
      elem.message = 'Performance acceptable';
   }
   else if (targetHits + acceptHits > problemHits)
   {
      elem.condition = metrics.constants.SEV_MAJOR;
      elem.message = 'Performance degraded';
   }
   else 
   {
      elem.condition = metrics.constants.SEV_CRITICAL;
      elem.message = 'Performance violation';
   }
   elem.message += ': T=' + targetHits + ' A='+ acceptHits + ' P=' + problemHits;
}
/*
 * Return hit count if range has data, or 0 if it does not
 */
function getRangeHitCount(report, rangeName)
{
   var hitCount = 0;
   var rangeStats = report.rangeStats.get(rangeName);
   if(rangeStats != null)
   {
      hitCount =  rangeStats.count;
   }
   return hitCount;
}

Properties

Property Name

Value Type

Description

key

ReportKey

Identifier describing the scope covered by this report.

endTime

java.util.Date

End of the period covered by this report.

collector

SummaryCollector

Collector that generated this report.

lastEvent

String[]

A copy of the last event captured during the interval of this report.

overall

FieldFilter[]

Overall statistics for this report.

rangeStats

java.util.Map<String,summary_stats>

Map of SummaryStat for each range that had activity. Map key is the name of the configured ResponseTimeRange.

reportingMonitors

String[]

List of monitors that contributed to this report.

nonreportingMonitors

String[]

List of monitors in the group that could not be contacted when this report was assembled.

Methods

String toString()

Returns a string representation of this object.

A.2.13 SummaryStats

SummaryStats objects are a collection of statistics that appear in a number of contexts inside a SummaryReport or a SamplingReport. Refer to the containing report type for more information.

Properties

Property Name

Value Type

Description

count

Number

(Read-only) Number of hits in the reported scope.

high

Number

(Read-only) Highest response time (in milliseconds) in the scope.

low

Number

(Read-only) Lowest response time in the scope.

average

Number

(Read-only) Arithmetic average of the response times in the scope

Methods

String toString()

Returns a string representation of this object.

A.2.14 SyntheticAlarm

A SyntheticAlarm object represents an alarm generated by the Experience Manager Monitor test engine. All properties are read-only. SyntheticAlarm objects are reported to the testEngine.onScenarioComplete and testEngine.onTestComplete event handlers to support Synthetic Test Management functionality.

For an example, see Section A.2.18, SyntheticTestResults.

Properties

Property Name

Value Type

Description

testName

String

(Read-only) Name of the test that produced this alarm.

scenarioName

String

(Read-only) Name of the test scenario that produced this alarm.

scenarioSeqNum

Number

(Read-only) Sequence number of the originating test scenario within its enclosing test.

responseTime

Number

(Read-only) Execution time reported by the scenario. A negative number indicates an execution failure.

severity

Object

(Read-only) Severity of the alarm. Value corresponds to one of the values in testEngine.constants severities.

description

String

(Read-only) Text description of the alarm.

userNum

Number

((Read-only) Simulated user number. The value is always 1, unless SyntheticTest.userCount is greater than 1.

timestamp

java.util.Date

Time when the alarm was generated.

Methods

String toString()

Returns a string representation of this object.

Boolean isFailed()

Returns a string representation of this object.

A.2.15 SyntheticDeployment

A SyntheticDeployment object provides access to the collection of SyntheticTest objects currently deployed to the monitor. This deployment is created and managed in the Experience Manager adapter using the Operations Center console. A read-only view is exposed in the Monitor’s scripting layer to facilitate Web Operations and Synthetic Test Management functionality.

The following example shows a simple WebOps that displays the content of a requested SyntheticDeployment.

function showDeploymentOp(parmMap)
{
   var html = '<table border="2">';
   var tests = testEngine.getDeployment().getTests();
   
   for(var i=0;i< tests.length; i++)
   {
      html += addItem('Test -' + tests[i].name,testToHTML(tests[i]))
   }
   html+='</table>';     
   return html;
}


function testToHTML(test)
{
   var html = '<table border="1">';
   html += addItem('name', test.name);
   html += addItem('userCount', test.userCount);
   html += addItem('interval', test.interval);
   html += addItem('enabled', test.enabled);
   html += addItem('includeRollup', test.includeRollup);
   var scenarios = test.getScenarios();
   for(var i=0;i< scenarios.length; i++)
   {
      html+= addItem('scenario-' + scenarios[i].seqNum,scenarioToHTML(scenarios[i])); 
   }
   
   html += '</table>';
   return html;

}
function scenarioToHTML(scenario)
{
   var html = '<table>';
   html += addItem('name', scenario.name);
   html += addItem('type', scenario.type);
   html += addItem('enabled', scenario.enabled);
   html += addItem('testName', scenario.testName);
   html += addItem('seqNum', scenario.seqNum);
   html += addItem('delay', scenario.delay);
   html += addItem('timeout', scenario.timeout);
   html += addItem('retries', scenario.retries);
   html += addItem('continueOnFailure', scenario.continueOnFailure);
   html += addItem('includeRollup', scenario.includeRollup);
   html += '</table>';
   return html;
   
}
function addItem(typeName, value)
{
   return '<tr><td>' + typeName + '</td><td>' + value + '</td></tr>'; 
}

There are no properties associated with the SyntheticDeployment object.

Methods

SyntheticTest[] getTests()

Returns an array of all SyntheticTest objects currently deployed to this monitor.

SyntheticTest getTest(String name)

Returns the test in this deployment where the SyntheticTest.name is equal to the provided name. If no test has the provided name, null is returned.

String toString()

Returns a string representation of this object.

A.2.16 SyntheticScenario

A SyntheticScenario object represents a scenario in a SyntheticTest. These scenarios are created and managed in the Experience Manager adapter using the Operations Center console. A read-only view is exposed in the Monitor’s scripting layer to facilitate Web Operations and Synthetic Test Management functionality.

The following example shows a simple WebOps that displays the content of a requested SyntheticScenario.

function showScenarioOp(parmMap)
{
   var testName=parmMap.get("testName");
   var index =parmMap.get("index");
   var deployment = testEngine.getDeployment();
   var test = deployment.getTest(testName);
   if(test == null)
   {
      return 'Test ' +testName + ' not found';
   }
   var scenario = test.getScenarioBySeqNum(index);
   if(scenario == null)
   {
      return 'Scenario ' + index + ' not found in test ' + testName;
   }
   
   return scenarioToHTML(scenario);
}

function scenarioToHTML(scenario)
{
   var html = '<table>';
   html += addItem('name', scenario.name);
   html += addItem('type', scenario.type);
   html += addItem('enabled', scenario.enabled);
   html += addItem('testName', scenario.testName);
   html += addItem('seqNum', scenario.seqNum);
   html += addItem('delay', scenario.delay);
   html += addItem('timeout', scenario.timeout);
   html += addItem('retries', scenario.retries);
   html += addItem('continueOnFailure', scenario.continueOnFailure);
   html += addItem('includeRollup', scenario.includeRollup);
   html += '</table>';
   return html;
   
}
function addItem(typeName, value)
{
   return '<tr><td>' + typeName + '</td><td>' + value + '</td></tr>'; 
}

Properties

Property Name

Value Type

Description

name

String

(Read-only) Name of the scenario.

type

Object

(Read-only) Type of scenario corresponding to one of the testEngine.constants values.

enabled

Boolean

(Read-only) Sequence number of the originating test scenario within its enclosing test.

testName

String

(Read-only) Name of the test containing the scenario.

seqNum

Number

(Read-only) Sequence number of the scenario within the enclosing test.

delay

Number

((Read-only) Artificial delay (in milliseconds) inserted before the scenario executes.

timeout

Number

(Read-only) Amount of time (in milliseconds) before the scenario is marked as failed because it took too long.

retries

Number

(Read-only) Number of times to retry the scenario in the event of a failure.

continueOnFailure

Boolean

Whether the test should continue to the next scenario if this scenario fails.

includeRollup

Boolean

Whether a roll‑up alarm should be generated with this scenario with the cumulative response time since the previous roll‑up.

Methods

String toString()

Returns a string representation of this object.

A.2.17 SyntheticTest

A SyntheticTest object represents a test in a SyntheticDeployment. These tests are created and managed in the Experience Manager adapter using the Operations Center console. A read-only view is exposed in the Monitor’s scripting layer to facilitate Web Operations and Synthetic Test Management functionality.

The following example shows a simple WebOps that displays the content of a requested SyntheticTest.

function showTestOp(parmMap)
{
   var testName=parmMap.get("testName");
   var deployment = testEngine.getDeployment();
   var test = deployment.getTest(testName);
   if(test == null)
   {
      return 'Test ' +testName + ' not found';
   }
   
   return testToHTML(test);
}


function testToHTML(test)
{
   var html = '<table border="1">';
   html += addItem('name', test.name);
   html += addItem('userCount', test.userCount);
   html += addItem('interval', test.interval);
   html += addItem('enabled', test.enabled);
   html += addItem('includeRollup', test.includeRollup);
   var scenarios = test.getScenarios();
   for(var i=0;i< scenarios.length; i++)
   {
      html+= addItem('scenario-' + scenarios[i].seqNum,scenarioToHTML(scenarios[i])); 
   }
   
   html += '</table>';
   return html;

}
function scenarioToHTML(scenario)
{
   var html = '<table>';
   html += addItem('name', scenario.name);
   html += addItem('type', scenario.type);
   html += addItem('enabled', scenario.enabled);
   html += addItem('testName', scenario.testName);
   html += addItem('seqNum', scenario.seqNum);
   html += addItem('delay', scenario.delay);
   html += addItem('timeout', scenario.timeout);
   html += addItem('retries', scenario.retries);
   html += addItem('continueOnFailure', scenario.continueOnFailure);
   html += addItem('includeRollup', scenario.includeRollup);
   html += '</table>';
   return html;
   
}
function addItem(typeName, value)
{
   return '<tr><td>' + typeName + '</td><td>' + value + '</td></tr>'; 
}

Properties

Property Name

Value Type

Description

name

String

(Read-only) Name of the test.

userCount

Number

(Read-only) Number of concurrent simulated users to run for this test.

interval

Number

(Read-only) Time (in milliseconds) between executions of this test.

enabled

Boolean

(Read-only) True if the test is activated.

includeRollup

Boolean

Whether a roll‑up alarm should be generated with this test with the cumulative response time of all scenarios in the test.

Methods

String toString()

Returns a string representation of this object.

SyntheticScenario[] getScenarios()

Returns an ordered array of all scenarios in this test as SyntheticScenario objects.

SyntheticScenario getScenarioByName(String name)

Returns the scenario in this test where the SyntheticScenario.name is equal to the provided name. If no scenario has the provided name, null is returned.

SyntheticScenario getScenarioBySeqNum(Number seqNum)

Returns the scenario in this test where the SyntheticScenario.seqNum is equal to the provided value. If no scenario has the provided sequence number, null is returned.

A.2.18 SyntheticTestResults

A SyntheticTestResults object reports the results of a completed user test execution by the Experience Manager Monitor test engine. All properties are read-only. SyntheticTestResults objects are reported to the testEngine.onTestComplete event handler to support Synthetic Test Management functionality.

The following example shows how to use the SyntheticTestResults object and related objects and services to implement conditional execution of a test. The example is purposely simplified to show the core functionality without getting bogged down in details of configuration management.

/*
 * Conditional execution: execute test identified in 'conditionalTestName' once if
 * a triggerScenario in 'mainTestName' produces a Critical alarm
 */
var mainTestName='test1';
var triggerScenarios='[1][5]';
var conditionalTestName='test2';

testEngine.onTestComplete=handleTestComplete;
testEngine.onScenarioComplete=handleScenarioComplete;

function handleTestComplete(testResults)
{
   if(testResults.test.name == conditionalTestName)
   { // stop conditional test once it runs once
      testEngine.deactivateTest(conditionalTestName);
   }
}

function handleScenarioComplete(alarm)
{
   // if this is the alarm is from the right test and its critical
   if(alarm.testName == mainTestName && 
      alarm.severity == testEngine.constants.SEV_CRITICAL)
   { 
      // and its one of the trigger scenarios
      if(triggerScenarios.indexOf('['+alarm.scenarioSeqNum + ']') >=0)
      { 
         // and we did not already start the conditional test
         if(!testEngine.getDeployment().getTest(conditionalTestName).enabled)
         { 
            // then start the conditional test
            testEngine.activateTest(conditionalTestName);
         }
      }
   }
}

Properties

Property Name

Value Type

Description

test

SyntheticTest

(Read-only) The test reporting these results.

Methods

String toString()

Returns a string representation of this object.

SyntheticAlarm[] getAlarms()

Returns an ordered array of all alarms generated during the latest test execution.

Number getFailCount()

Returns the number of alarms where SyntheticAlarm.isFailed() is True.

SyntheticAlarm[] getAlarmsBySeverity(Object severity

Returns an array containing any alarms with the specified severity. Valid severity values are listed in testEngine.constants severities.