AIOps

AIOps

Join this online group to communicate across IBM product users and experts by sharing advice and best practices with peers and staying up to date regarding product enhancements.


#ITAutomation
#AIOps
#CloudPakforAIOps
#AIOps

 View Only

Cloud Pak for AIOps 4 tips: Metric Anomaly Detection custom integrations

By Zane Bray posted Mon March 02, 2026 05:07 AM

  
image
Metric Anomaly Detection (MAD) is a capability in IBM Cloud Pak for AIOps (AIOps) that ingests time-series metric data, automatically creates baselines against that data, then monitors the incoming metric streams, keeping watch for anomalous readings. If an anomalous reading is detected, MAD generates an alert into AIOps that can then be correlated with other alerts happening in the same time window. MAD alerts could be an early indication of a potential developing problem and so enable operations teams to be proactive in the management of their environments.
AIOps comes with a number of out-of-the-box MAD integrations into MAD - for example: Instana, New Relic, and Dynatrace - and can be set up quickly and easily by entering the relevant connection details. There are many cases however where you wants to integration something for which there isn't an off-the-shelf integration available, or where you have a proprietary system that you want to monitor metric data from.
This blog outlines a simple method to create a custom integration into MAD and includes:
  • A method to inject business-as-usual metric data points
  • A method to pre-train MAD with historic data
  • A method to inject an anomalous reading for demonstration purposes (optional)

The examples given in this blog use Netcool/Impact (Impact) to do the above tasks, but similar could be achieved using shell scripts and curl, for example. Netcool/Impact is part of the AIOps portfolio and entitlement to use comes with your AIOps license.

More information about using the MAD API can be found in the documentation.

--

STEP 1 OF 3: SET UP BAU INJECTION

The scenario this example uses is where we will monitor three metric streams on a Cisco switch: packets received, packets sent, and chassis temperature.

The first policy in the set injects three different metric data points: one for each of the monitored metrics. The sample policy is simply injecting the same metric values each time however the policy could easily be adapted to instead include a section that fetches the values from a target system.

Here is the sample Impact policy to inject the sample metric data points:

////////////////////////////////////////////////////////////////////////
//
// Run Metric Anomaly Detection
//
// Created by: Z. Bray (zane) 27/01/2026
//
// The purpose of this policy is to inject MAD data points.
// It should be run by a Policy Activator every 5 minutes.
// 
////////////////////////////////////////////////////////////////////////

// DEFINE METRIC ANOMALY DETECTION CONNECTION PARAMETERS

HTTPHost="cpd-aiops.apps.aiops-4.cp.fyre.ibm.com";
HTTPPort=443;
Protocol="https";
ChannelKey="";
FilesToSend=null; 
FormParameters=null;
Method="POST";
AuthHandlerActionTreeName=null; 

HeadersToSend = NewObject();
// HeadersToSend['Accept']='application/json';
HeadersToSend['Content-Type']='application/json';
HeadersToSend['X-TenantID']='cfd95b7e-3bc7-4006-a4a8-a73a79c71255';
HeadersToSend['Authorization']='ZenApiKey 1234567890abcdefghijk==';

HttpProperties=NewObject();
HttpProperties.AlwaysSendAuth=true;
HttpProperties.TrustCertificate=true;

Path = "/aiops/api/app/metric-api/v1/metrics";

Log("METRIC: Inject BAU values into MAD...");

// GET CURRENT TIME
CurrentDate = GetDate();

Log("METRIC: current time: " + String(CurrentDate));

// CREATE PAYLOAD1 FOR INTERFACE PACKETS
Payload1 = '{"groups": [{"timestamp": "' + CurrentDate + '000' + 
            '", "resourceID": "cisco1000' +
            '", "metrics": {"Receive": 150500, "Send": 150500}, "attributes": {"group": "network", "node": "cisco1000", "interface": "slot1"}}]}';

Log("METRIC: Payload1: " + Payload1);

// SET PAYLOAD1 FOR METRIC ANOMALY DETECTION DATA POINT
HttpProperties.Content=Payload1;

// SEND PAYLOAD1 TO METRIC ANOMALY DETECTION API
y=GetHTTP(HTTPHost, HTTPPort, Protocol, Path, ChannelKey, Method, AuthHandlerActionTreeName, FormParameters, FilesToSend, HeadersToSend, HttpProperties);

Log("METRIC: Payload1: " + ErrorReason);
Log("METRIC: Payload1: " + ResultCode);

// CREATE PAYLOAD2 FOR TEMPERATURE READING
Payload2 = '{"groups": [{"timestamp": "' + CurrentDate + '000' + 
            '", "resourceID": "cisco1000' +
            '", "metrics": {"ChassisTemp": 32}, "attributes": {"group": "network", "node": "cisco1000"}}]}';

// Log("METRIC: Payload2: " + Payload2);

// SET PAYLOAD2 FOR METRIC ANOMALY DETECTION DATA POINT
HttpProperties.Content=Payload2;

// SEND PAYLOAD2 TO METRIC ANOMALY DETECTION API
y=GetHTTP(HTTPHost, HTTPPort, Protocol, Path, ChannelKey, Method, AuthHandlerActionTreeName, FormParameters, FilesToSend, HeadersToSend, HttpProperties);

Log("METRIC: Payload2: " + ErrorReason);
Log("METRIC: Payload2: " + ResultCode);

NOTES:

  • This implementation uses the Impact function GetHTTP to interact with remote APIs, and can use a variety of methods including GET and POST.
  • This implementation requires you to follow these steps to first create an API key in AIOps and generate a "ZenApiKey".
  • Examples of the format for the JSON payload required by the MAD API are documented in the AIOps documentation.
  • If you were retrieving the data points from a target system first, the function ParseJSON is very useful for unpacking the retrieved payload.
  • This policy should be run under a Policy Activator Service in Impact, with an Activation Interval of 300 seconds.

--

STEP 2 OF 3: INJECT HISTORIC TRAINING DATA

MAD training is configured under the AI model management section within AIOps. It works by processing the data sets that have been ingested and building analytics models which are then used to monitor the incoming metric data streams.

This section provides a sample Impact policy that can be used as a framework for injecting training data into your MAD system. The source data may be available via a third-party API, or stored in a database. In any case, Impact is very well suited for pulling large sets of data from source systems, transforming it into a MAD-compatible format, then injecting it into MAD.

Here is the sample Impact policy to inject the metric training data into MAD:

////////////////////////////////////////////////////////////////////////
//
// Train Metric Anomaly Detection
//
// The purpose of this policy is to inject MAD training data.
// It will push data points at 5-minute intervals over the past 2 weeks.
// 
////////////////////////////////////////////////////////////////////////

// DEFINE METRIC ANOMALY DETECTION CONNECTION PARAMETERS
HTTPHost="cpd-aiops.apps.aiops-4.cp.fyre.ibm.com";
HTTPPort=443;
Protocol="https";
ChannelKey="";
FilesToSend=null; 
FormParameters=null;
Method="POST";
AuthHandlerActionTreeName=null; 

HeadersToSend = NewObject();
HeadersToSend['Content-Type']='application/json';
HeadersToSend['X-TenantID']='cfd95b7e-3bc7-4006-a4a8-a73a79c71255';
HeadersToSend['Authorization']='ZenApiKey 1234567890abcdefghijk==';

HttpProperties=NewObject();
HttpProperties.AlwaysSendAuth=true;
HttpProperties.TrustCertificate=true;

Path = "/aiops/api/app/metric-api/v1/metrics";

Log("METRIC: Training MAD...");

// SET INTERVAL AND COUNTER
MyInterval = 300;
j = 0;

Log("METRIC: interval: " + String(MyInterval));

// GET CURRENT TIME
CurrentDate = GetDate();

Log("METRIC: current time stamp: " + String(CurrentDate));

// SET START TIME FOR 2 WEEKS AGO
t1 = CurrentDate - (14 * 86400);

Log("METRIC: start time: " + String(t1));

// ITERATE OVER PERIOD
while (t1 < CurrentDate) {

// LOG EVERY 100TH DATA POINT     if (j % 100 == 0) { Log("METRIC: j: " + String(j)); } // CREATE PAYLOAD1 FOR INTERFACE PACKETS Payload1 = '{"groups": [{"timestamp": "' + t1 + '000' + '", "resourceID": "cisco1000' + '", "metrics": {"Receive": 150500, "Send": 150500}, "attributes": {"group": "network", "node": "cisco1000", "interface": "slot1"}}]}'; // SET PAYLOAD1 FOR METRIC ANOMALY DETECTION DATA POINT HttpProperties.Content=Payload1; // SEND PAYLOAD1 TO METRIC ANOMALY DETECTION API y=GetHTTP(HTTPHost, HTTPPort, Protocol, Path, ChannelKey, Method, AuthHandlerActionTreeName, FormParameters, FilesToSend, HeadersToSend, HttpProperties); // LOG EVERY 100TH DATA POINT    if (j % 100 == 0) { Log("METRIC: Payload1: " + ErrorReason); Log("METRIC: Payload1: " + ResultCode); } // CREATE PAYLOAD2 FOR TEMPERATURE READING Payload2 = '{"groups": [{"timestamp": "' + t1 + '000' + '", "resourceID": "cisco1000' + '", "metrics": {"ChassisTemp": 32}, "attributes": {"group": "network", "node": "cisco1000"}}]}';    // SET PAYLOAD2 FOR METRIC ANOMALY DETECTION DATA POINT HttpProperties.Content=Payload2; // SEND PAYLOAD2 TO METRIC ANOMALY DETECTION API y=GetHTTP(HTTPHost, HTTPPort, Protocol, Path, ChannelKey, Method, AuthHandlerActionTreeName, FormParameters, FilesToSend, HeadersToSend, HttpProperties); // LOG EVERY 100TH DATA POINT    if (j % 100 == 0) { Log("METRIC: Payload2: " + ErrorReason); Log("METRIC: Payload2: " + ResultCode); } // INCREMENT INTERVAL AND COUNTER    t1 = t1 + MyInterval; j = j + 1; } Log("METRIC: total number of metrics sets injected: " + String(j));

NOTE: After training data ingestion, you will need to run Metric Anomaly Detection training via the AIOps UI, under "AI model management" section.

--

STEP 3 OF 3: INJECT ANOMALOUS READING (OPTIONAL)

Once training data has been ingested and training has run at least once, your system should begin actively monitoring the metric data streams you have configured. At this point, you can inject a deliberately anomalous reading to provoke a MAD detection and alert. This can be useful for testing and demonstration purposes. The method to do this is the same as step 1: inject a metric data point that has a value you know is well outside the expected range observed so far.

Here is a sample Impact policy to inject an anomalous metric data point into MAD:

////////////////////////////////////////////////////////////////////////
//
// Inject anomaly into Metric Anomaly Detection
//
// Created by: Z. Bray (zane) 27/01/2026
//
// The purpose of this policy is to inject an anomalous value into MAD.
// 
////////////////////////////////////////////////////////////////////////

// DEFINE METRIC ANOMALY DETECTION CONNECTION PARAMETERS

HTTPHost="cpd-aiops.apps.aiops-4.cp.fyre.ibm.com";
HTTPPort=443;
Protocol="https";
ChannelKey="";
FilesToSend=null; 
FormParameters=null;
Method="POST";
AuthHandlerActionTreeName=null; 

HeadersToSend = NewObject();
// HeadersToSend['Accept']='application/json';
HeadersToSend['Content-Type']='application/json';
HeadersToSend['X-TenantID']='cfd95b7e-3bc7-4006-a4a8-a73a79c71255';
HeadersToSend['Authorization']='ZenApiKey 1234567890abcdefghijk==';

HttpProperties=NewObject();
HttpProperties.AlwaysSendAuth=true;
HttpProperties.TrustCertificate=true;

Path = "/aiops/api/app/metric-api/v1/metrics";

Log("METRIC: Inject anomalous values into MAD...");

// GET CURRENT TIME
CurrentDate = GetDate();

Log("METRIC: current time: " + String(CurrentDate));

// CREATE PAYLOAD1 FOR INTERFACE PACKETS
Payload1 = '{"groups": [{"timestamp": "' + CurrentDate + '000' + 
            '", "resourceID": "cisco1000' +
            '", "metrics": {"Receive": 300500, "Send": 300500}, "attributes": {"group": "network", "node": "cisco1000", "interface": "slot1"}}]}';

Log("METRIC: Payload1: " + Payload1);

// SET PAYLOAD1 FOR METRIC ANOMALY DETECTION DATA POINT
HttpProperties.Content=Payload1;

// SEND PAYLOAD1 TO METRIC ANOMALY DETECTION API
y=GetHTTP(HTTPHost, HTTPPort, Protocol, Path, ChannelKey, Method, AuthHandlerActionTreeName, FormParameters, FilesToSend, HeadersToSend, HttpProperties);

Log("METRIC: Payload1: " + ErrorReason);
Log("METRIC: Payload1: " + ResultCode);

// CREATE PAYLOAD2 FOR TEMPERATURE READING
Payload2 = '{"groups": [{"timestamp": "' + CurrentDate + '000' + 
            '", "resourceID": "cisco1000' +
            '", "metrics": {"ChassisTemp": 52}, "attributes": {"group": "network", "node": "cisco1000"}}]}';

Log("METRIC: Payload2: " + Payload2);

// SET PAYLOAD2 FOR METRIC ANOMALY DETECTION DATA POINT
HttpProperties.Content=Payload2;

// SEND PAYLOAD2 TO METRIC ANOMALY DETECTION API
y=GetHTTP(HTTPHost, HTTPPort, Protocol, Path, ChannelKey, Method, AuthHandlerActionTreeName, FormParameters, FilesToSend, HeadersToSend, HttpProperties);

Log("METRIC: Payload2: " + ErrorReason);
Log("METRIC: Payload2: " + ResultCode);

--

See the IT & Network Automation Tiger Team website for more tips-and-tricks blogs on AIOps and Netcool.

0 comments
32 views

Permalink