The following sections walk you through the sections of code from the Alerts Notification gadget Alerts Notification gadget and the Alerts Notification gadget KPI Subscriber gadget.
The Alerts Notification gadget is coded for a server that is secured. The user is prompted for a username and password at the time of their first REST service call. If security is not enabled, the user must set the following cookie on all XmlHttpRequest objects after xhr.open(...) and before xhr.send(...): xhr.setRequestHeader("Cookie", "com.ibm.wbimonitor.UserName="+username+";").
//Create the object
var xhr = new XMLHttpRequest();
//Create the url which is to be called
var url = "";
/**
* Initialize the xhr object.
* The first parameter is the HTTP Protocol method
* The second parameter is the url to be called
* The third parameter is whether or not to perform the call asynchronously
* An optional fourth parameter is the username
* An optional fifth parameter is the user's password
**/
xhr.open("GET", url, true);
//Set the callback function to be called once the request is completed
xhr.onreadystatechange = function() {
if (xhr.readyState==4 && xhr.status==200) {
//WORK WITH xhr.responseText HERE
}
}
//Perform the actual request
xhr_.send();
var xhr = new XMLHttpRequest();
var url = "http://localhost:9080/rest/bpm/monitor/alerts/dashboardalerts";
xhr.open("GET", url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState==4 && xhr.status==200) {
//An arbitrary method to process the returned JSON data
processAlertData(xhr.responseText);
}
}
xhr_.send();
{
"Dashboard Alert Array": [
{
"ID":"ABC123",
"Subject":"Order received",
"Acknowledged":true,
"Model ID":"Model1",
"Context ID":"ABC123",
"Instance ID":"123456",
"Creation Timestamp":"2007-02-02T15:15:10"
"Creation Timestamp Localized":"Feb. 2, 2007 3:15:10PM",
}
],
"Record Count":50,
"Page Size":1,
"Page Number":1
}
var dataObject = json.parse(xhr.responseText);
var recordCount = dataObject["Record Count"];
var alertArray = dataObject["Dashboard Alert Array"];
for(each in alertArray){
if(!alertArray[each]["Acknowledged"]){
alert("This alert is unread! ID:"+alertArray[each]["ID"]);
}
}
var xhr = new XMLHttpRequest();
//The same URL that was previously called, however we need to append the Alert instance ID
var url = "http://localhost:9080/rest/bpm/monitor/alerts/dashboardalerts/ABC123";
xhr.open("GET", url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState==4 && xhr.status==200) {
processAlertInstanceData(xhr.responseText);
/*
* An arbitrary method to process the returned JSON data
* that now is in the form of
* {
* "ID":"ABC123",
* "Subject":"Order greater than 5000 received",
* "Acknowledged":false,
* "Model ID":"Model1",
* "Context ID":"Context1",
* "Instance ID":"ABC123",
* "Context Def":"ABC123",
* "Creation Timestamp":"2007-02-02T15:15:10",
* "Creation Timestamp Localized":"Feb. 2, 2007 3:15:10PM",
* "Body":"An order was received for 50000",
* "Event":"TheEvent",
* "CBE":"TheCBE"
* }
*/
}
}
xhr_.send();
var data = [{"ID":"ABC123","Acknowledged":true},{"ID":"DEF456","Acknowledged":false}];
var xhr = new XMLHttpRequest();
var url = "http://localhost:9080/rest/bpm/monitor/alerts/dashboardalerts";
xhr.open("POST", url, true);
//The following line tells the REST service to use the PUT method instead of the POST method. This is
//an architectural implementation due to the limits of clients supporting GET and POST methods, but
//not necessarily PUT and DELETE methods.
xhr.setRequestHeader("X-Method-Override","PUT");
xhr.onreadystatechange = function() {
if (xhr.readyState==4 && xhr.status==200) {
//check for an error message contained in the REST response.
//If xhr.responseText is blank, update was successful.
}
}
xhr.send(json.stringify(data));
var data = [{"ID":"DEF456"}];
var xhr = new XMLHttpRequest();
var url = "http://localhost:9080/rest/bpm/monitor/alerts/dashboardalerts";
xhr.open("POST", url, true);
//The following line tells the REST service to use the DELETE method instead of the POST method. This is
//an architectural implementation due to the limits of clients supporting GET and POST methods, but
//not necessarily PUT and DELETE methods.
xhr.setRequestHeader("X-Method-Override","DELETE");
xhr.onreadystatechange = function() {
if (xhr.readyState==4 && xhr.status==200) {
//check for an error message contained in the REST response.
//If xhr.responseText is blank, update was successful.
}
}
xhr.send (json.stringify(data));
var xhr = new XMLHttpRequest();
var url = "http://localhost:9080/rest/bpm/monitor/alerts/subscriptions";
xhr.open("GET", url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState==4 && xhr.status==200) {
processAlertSubscriptions(xhr.responseText);
/*
* An arbitrary method to process the returned JSON data
* that now is in the form of
* {
* "Alert Subscription Array":
* [
* {
* "Binding ID":"ABC123",
* "Name":"Test Situation Binding",
* "Description":"Binding for testing",
* "Category":"Test",
* "Creation Timestamp":"2007-02-02T15:15:10",
* "Creation Timestamp Localized":"Feb. 2, 2007 3:15:10PM",
* "Dashboard": true,
* "Cell": false,
* "E-mail": false,
* "Pager": false
* }
* ],
* "Record Count":1,
* "Page Size":10,
* "Page Number":1
* }
*/
}
}
xhr.send();
var data = [{"Binding ID":"ABC123", "Dashboard": false, "Cell": false, "E-mail": true, "Pager": false}];
var xhr = new XMLHttpRequest();
var url = "http://localhost:9080/rest/bpm/monitor/alerts/subscriptions";
xhr.open("POST", url, true);
//The following line tells the REST service to use the PUT method instead of the POST method. This is
//an architectural implementation due to the limits of clients supporting GET and POST methods, but
//not necessarily PUT and DELETE methods.
xhr.setRequestHeader("X-Method-Override","PUT");
xhr.onreadystatechange = function() {
if (xhr.readyState==4 && xhr.status==200) {
//check for an error message contained in the REST response.
//If xhr.responseText is blank, update was successful.
}
}
xhr.send(json.stringify(data));
Dashboard alerts:
- on open, issue a GET call to /alerts/dashboardalerts
- on a successful response, parse the JSON object and iterate over the alert list and add alerts to a UI list
- on double-click of an alert instance in the UI list, issue a GET call to /alerts/dashboardalerts/ALERT_ID to get alert details
- on double-click of an alert instance in the UI list, issue a POST/PUT call to /alerts/dashboardalerts to mark the alert as read
- on a successful response, parse the JSON object and display an alert instance details dialog
- on forward button click, gather the desired target username and issue a POST call to /alerts/dashboardalerts to forward the alerts to the desired user
- on delete button click, gather the selected alerts and issue a POST/DELETE call to /alerts/dashboardalerts to delete the selected alerts
The KPI Subscriber gadget is coded for a server that is secured. The user is prompted for a username and password at the time of their first REST service call. If security is not enabled, all KPIs will be returned to the user, regardless of the owner. It would then be up to the client application to perform any desired user filtering.
The Alerts Notification gadget code review covered how to make calls to the WebSphere Business Monitor REST services for Alerts® data. The following examples show how to use KPI data using the same REST services. For a more detailed explanation of the Javascript capabilities, see the Alerts Notification gadget code review.
var xhr = new XMLHttpRequest();
var url = "http://localhost:9080/rest/bpm/monitor/models";
xhr.open("GET", url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState==4 && xhr.status==200) {
/**
* Download was successful. The data returned is in the format
* [
* {
* "Model ID":"model_id1",
* "Versions":[
* {"Display Name":"display name1","Version":"20070101000000"},
* {"Display Name":"display name2","Version":"20080101000000"},
* ]
* }
* ]
**/
}
}
xhr_.send();
How the client application displays the models and versions is application dependent, but you generally only need to display KPIs from the most recent version of the model that has been deployed. The following examples use a model id of "model_id1" and a version of "20080101000000" for all KPI queries and actions. After you have the model and version information, you can query the KPI data that returns a list of digest information for all KPIs defined in the model version. You can then make a subsequent call once you have obtained the KPI ID. The following example shows the query necessary to retrieve a list of all KPIs in a monitor model version.
var xhr_ = new XMLHttpRequest();
var url = "http://localhost:9080/rest/bpm/monitor/models/model_id1/versions/20080101000000/kpis"
xhr_.open("GET", url, true);
xhr_.onreadystatechange = function() {
if (xhr.readyState==4 && xhr.status==200) {
/**
* Download was successful. The data returned is in the format:
* [
* {
* "KPI ID": "kpi_id1",
* "Model ID": "model_id1",
* "Version": "20080101000000",
* "KPI Display Name": "kpi name",
* "KPI Origin": "modeled",
* "User ID": "user 1",
* "KPI Context ID": "context id1",
* "KPI Description": "sample KPI Data",
* "KPI Data Type": "duration",
* "Target": 60000,
* "Target Localized": "1 m 0 s",
* "KPI Calc Method": "aggregated",
* "Aggregated Metric ID": "metric ID",
* "Aggregated Metric Name": "metric name 1",
* "Aggregated Function": "avg",
* "Version Aggregation": "allVersions",
* "View Access": "public",
* }
* ]
**/
}
}
xhr_.send();
This service call returns all the metadata for the KPI that is required to make any further requests. This metadata contains the KPI ID for making REST service calls, the place where the KPI was created (either in the WebSphere Business Monitor Toolkit or the WebSphere Business Monitor Dashboards), the owner of the KPI (if one is assigned), a description of the KPI that makes it easier to determine what the KPI represents, the type of KPI data (whether it is representing a decimal or duration), and the desired value of the KPI is available in the Target field. This information is all that is needed to display a list of KPIs that you can select from to view the actual KPI values. To retrieve KPI data with the current KPI value, make the following REST call providing a model ID, version number, and KPI ID.
var xhr = new XMLHttpRequest();
var url = "http://localhost:9080/rest/bpm/monitor/models/model_id1/versions/20080101000000/kpis/value/kpi_id1?locale=en_US";
xhr.open("GET", url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState==4 && xhr.status==200) {
/**
* Download was successful. The data returned is in the format:
{
"KPI ID":"kpi_id1",
"Model ID":"model_id1",
"Version":20080101000000,
"Locale": "en_US",
"Model Display Name":"sample model1",
"KPI Context ID":"context id1",
"KPI Context Name":"context name1",
"KPI Display Name":"kpi name1",
"KPI Description":"sample kpi data",
"KPI Origin":"modeled", //Possible values are either: modeled or runtime
"KPI Data Type":"duration", //Possible values are either: decimal or duration
"Target":200801010000008, // if duration KPI, in milliseconds
"Target Localized":"xxxxxxx", // "xxxxxxx" is localized Target
"KPI Range Type":"actualValue", // Possible values are either: actualValue or percentage
"KPI Calc Method":"aggregated", // Possible values are either: aggregated or calculated
"Aggregated Metric ID":"metric id1",
"Aggregated Metric Name":"matric name1",
"Aggregated Metric Type":"STRING", // "STRING", "BOOLEAN", "DECIMAL", "INTEGER", "DATE", "TIME", "DATETIME", "DURATION", "COUNTER", "STOPWATCH-A", "STOPWATCH-NA"
"Aggregated Metric MC ID":"metric mc id1",
"Aggregated Metric MC Name":"metric mc name1",
"Aggregated Function":"avg", // Possible values include: avg, sum, min, max, or count
"Version Aggregation":"allVersions", // Possible values are either: singleVersion or allVersions
"Time Period Metric ID":"time period metric id1",
"Time Period Metric Name":"time period metric name1",
"Time Period Method":"rollingPeriod", //Possible values include: repeatingPeriod, rollingPeriod, or fixedPeriod
"Repeating Period Duration":"", // Possible values include: yearly, quarterly, monthly, weekly, daily, hourly, or minutely
"Repeating Period Basis":"", // Possible values include: previousPeriod or periodInProgress
"Repeating Period Timezone":"", // java/ICU timezone identifier
"Rolling Period Duration":"years", // Possible values include: years, months, days, hours, or minutes
"Rolling Period Quantity":123,
"Fixed Period Start":"", // Valid formats are '2007-01-01' or '2007-01-01T00:00:00'
"Fixed Period End":"", // Valid formats are '2007-01-01' or '2007-01-01T00:00:00'
"Fixed Period Timezone":"", // java timezone identifier
"Calculated KPI Expression":"expression1",
"User ID":"user 1",
"View Access":"public", // Possible values are either: public or personal
"Format Decimal Precision":2,
"Format Currency":"USD", // ISO4217.Currency identifier
"Format Percentage":true, // Possible values are either: false or true
"KPI Value":"90",
"KPI Value Localized":"xxx", // "xxx" is localized KPI value
"KPI Metric Filter Array":[
{
"KPI Metric Filter ID":"filter id1"
"Filter Metric ID":"filter metric id1"
"Filter Metric Name":""
"Filter Metric Type":"STRING"
"Filter Operator":"lessThan" // Possible values include: equals, lessThan, lessThanOrEquals, greaterThan, greaterThanOrEquals, notEquals, in, notIn, isNull, isNotNull, like, notLike
"Filter Operator Case Sensitive":false // Possible values are either: false or true
"Filter Value":"filter value1"
}
],
"KPI Range Array":[
{
"KPI Range ID":"range1"
"KPI Range Display Name":"range name1"
"KPI Range Start Value":75 // if duration KPI, and if rangeType is actualValue, in milliseconds
"KPI Range Start Value Localized":"xxxxxx" // "xxxxxx" is localized range start
"KPI Range End Value":200 // if duration KPI, and if rangeType is actualValue, in milliseconds
"KPI Range End Value Localized":"xxxxxx" // "xxxxxx" is localized range start
"KPI Range Color":"" // #000000 - #FFFFFF (omit the # sign)
"KPI Range Icon":"images/kpi/monitorIcons/IBM_down_red.gif"
}
]
}
**/
}
}
xhr_.send();
From this result set, you can extract the business data from the KPIs. The JSON object now contains the current KPI value, any defined time filters, any defined metric data filters, and any defined KPI ranges. Now we will use the locale query parameter. This parameter is in the form of xx_YY, where xx is the language code and YY is the country code. Supplying this locale parameter formats the KPI values, range values, targets, and so on with a localized value in the supplied locale. When working with business data in mathematical calculations, you can use the KPI Value field. However, when displaying values to users, you can use the KPI Value Localized field.
Next, if there is a non-null KPI value, determine the current status of the KPI. To determine the status, iterate over the ranges array and compare the KPI Value to each range's KPI Start Value and KPI End Value. If the KPI value falls within this range, you can display the KPI Range Display Name as the current status.
If the KPI Range Color is not null, you can mark up the interface with the current range's color.
If the KPI Range Icon is not null, you can display the range icon which the you previously selected. The value of the KPI range icon is a URL relative to the REST service. In the preceding example, the value of images/kpi/monitorIcons/IBM_down_red.gif is relative to the value of http://localhost:9080/rest/. The complete URL of the status icon is then http://localhost:9080/rest/images/kpi/monitorIcons/IBM_down_red.gif. These icons can either be downloaded during development and packaged with your client applications, or if your platform/language supports dynamic remote image loading (similar to a browser loading a remote image), you can simply create the URL on the fly and point to the source of the image. The REST service located at http://localhost:9080/rest/bpm/monitor/icons/kpi returns a list of all available status icons to the user.
The general flow of a KPI viewing application is described in the following pseudocode:
KPI Selection displayed in a gauge format:
- on open, issue a GET call to /monitor/models and update UI with model and versions
- on model and version selection, issue a GET call to /monitor/models/MODELID/version/VERSION/kpis and update UI with available KPIs
- on KPI selection, issue a GET call to /monitor/models/MODELID/version/VERSION/kpis/value/KPIID
- on successful KPI response, parse JSON data object and step through the necessary UI updates
- if ranges are defined, sort the range list and determine the minimum and maximum values
- if ranges are not defined, determine an auto-generated minimum and maximum based on available kpi value or target
- display range widgets as pie pieces in gauge
- if value is defined, determine rotation of value arrow based on comparison of value to minimum and maximum of ranges
- if target is defined, determine rotation of target arrow based on comparison of value to minimum and maximum of ranges
Although it is outside the scope of the previous examples, it is worth noting that the KPI services also enable writing KPI data, much the same way the alerts data is writable. A POST/DELETE service call to the URL of http://localhost:9080/rest/bpm/monitor/models/MODELID/versions/VERSION/kpis/config/KPIID deletes the KPI if the KPI was created in the dashboards and the user has delete authority. A new KPI can also be created or an existing KPI can be updated. Calling the URL http://localhost:9080/rest/bpm/monitor/models/MODELID/versions/VERSION/kpis/config with a POST method creates a new KPI. Calling the same URL with a POST/PUT method call updates an existing KPI. To create a new KPI or edit an existing KPI, a JSON object containing the desired data is required to be posted. The exact format of this JSON object is defined in the Business Monitor REST API reference.
References: