This blog describes how to send automated notifications (after the June-10-2018 update) in case the JMS resources are critical or exhausted using an integration flow.
Automated Notification for Critical or Exhausted JMS Resources
As mentioned in the blog
'JMS Resources and Size Limits' limited resources are available on the JMS broker. To get notified as soon as the resources get critical is required to take early actions to avoid runtime issues. This blog describes how to enable the alerting using a simple integration flow.
How to use the Alert Notification Service for Alerting with the OData APIs is described in the blog
Automated Notifications via SAP Alert Notification Service for Critical or Exhausted JMS Resources.
Scenario Description
To enable the notification we use the OData APIs for JMS queue monitoring in an integration flow.. These APIs can be consumed via
https://<APIUrl>/api/v1 where <tmn> is the address of the tenant management node(Neo) or the address of the API service instance (CF). Here we will use the API for the JMS broker monitoring via
https://<APIUrl>/api/v1/JmsBrokers('Broker1') .
Overall scenario looks like this:
The flow is triggered by a timer, fetches the JMS Resource data via OData adapter, evaluates the JMS resource status in a script and send a notification mail if the resources are critical or exhausted.
Let's create the flow.
Create Integration Flow with Timer Start Event and OData Receiver
Create an integration flow with
Start Timer Event. Using
Request-Reply step call OData APIs to fetch details of the JMS broker via OData receiver channel. Below find the configuration of OData Receiver channel:
Note, that you need to use
Operation Read(Get), enter
JmsBrokers('Broker1') as
Resource Path and
$expand=QueueStates as
Query Options.
Read JMS Resources into Properties in Content Modifier
In a
Content Modifier step you now read all the JMS resources via
XPath into properties:
Create the following properties:
QueueCapacityOK:
XPath to /JmsBrokers/JmsBroker/CapacityOk
QueueCapacityError: XPath to /JmsBrokers/JmsBroker/CapacityError
QueueCapacityWarning: XPath to /JmsBrokers/JmsBroker/CapacityWarning
MaxQueues:
XPath to /JmsBrokers/JmsBroker/MaxQueueNumber
Queues:
XPath to /JmsBrokers/JmsBroker/QueueNumber
Transactions:
XPath to /JmsBrokers/JmsBroker/IsTransactedSessionsHigh
Providers:
XPath to /JmsBrokers/JmsBroker/IsProducersHigh
Consumers:
XPath to /JmsBrokers/JmsBroker/IsConsumersHigh
Capacity:
XPath to /JmsBrokers/JmsBroker/Capacity
MaxCapacity:
XPath to /JmsBrokers/JmsBroker/MaxCapacity
Evaluate Overall JMS Resource Status via Groovy Script
In a Groovy Script we now calculate the overall JMS resource status. Use the following script code:
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
def Message processData(Message message) {
// Get Properties
map = message.getProperties();
MaxCapacity = new BigDecimal(map.get("MaxCapacity"));
Capacity = new BigDecimal(map.get("Capacity"));
BigDecimal PercentCapacity = Capacity * 100 / MaxCapacity;
BigDecimal CriticalLimit = MaxCapacity / 100 * 80;
BigDecimal ExhaustedLimit = MaxCapacity / 100 * 95;
MaxQueueNumber = new BigDecimal(map.get("MaxQueues"));
QueueNumber = new BigDecimal(map.get("Queues"));
BigDecimal CriticalLimitQueues = MaxQueueNumber - 1;
if (Capacity >= ExhaustedLimit) {
CapacityStatus = "Exhausted";
}
else if (Capacity >= CriticalLimit) {
CapacityStatus = "Critical";
}
else {
CapacityStatus = "OK";
}
if (QueueNumber >= CriticalLimitQueues) {
QueueStatus = "Critical";
}
else {
QueueStatus = "OK";
}
int QueueCapacityWarning = new Integer(map.get("QueueCapacityWarning"));
int QueueCapacityError = new Integer(map.get("QueueCapacityError"));
if (QueueCapacityError >= 1) {
QueueCapacityStatus = "Exhausted";
}
else if (QueueCapacityWarning >= 1) {
QueueCapacityStatus = "Critical";
}
else {
QueueCapacityStatus = "OK";
}
int Consumers = new Integer(map.get("Consumers"));
if (Consumers == 1) {
ConsumerStatus = "Critical";
}
else {
ConsumerStatus = "OK";
}
int Providers = new Integer(map.get("Providers"));
if (Providers == 1) {
ProviderStatus = "Critical";
}
else {
ProviderStatus = "OK";
}
int Transactions = new Integer(map.get("Transactions"));
if (Transactions == 1) {
TransactionStatus = "Critical";
}
else {
TransactionStatus = "OK";
}
message.setProperty("PercentCapacity", PercentCapacity);
message.setProperty("CapacityStatus", CapacityStatus);
message.setProperty("QueueCapacityStatus", QueueCapacityStatus);
message.setProperty("QueueStatus", QueueStatus);
message.setProperty("ConsumerStatus", ConsumerStatus);
message.setProperty("ProviderStatus", ProviderStatus);
message.setProperty("TransactionStatus", TransactionStatus);
if ((CapacityStatus == "Exhausted") || (QueueCapacityStatus == "Exhausted")) {
message.setProperty("JMSStatus", "Exhausted");
}
else if ((CapacityStatus == "Critical") || (QueueCapacityStatus == "Critical") || (QueueStatus == "Critical") || (ConsumerStatus == "Critical") || (ProviderStatus == "Critical") || (TransactionStatus == "Critical")) {
message.setProperty("JMSStatus", "Critical");
}
else {
message.setProperty("JMSStatus", "OK");
}
return message;
}
Check Queue Capacity Status in Router
If you want to get additional information about dedicated message queues in case the queue capacity is critical or exhausted in a
Router step check the Queue capacity Status and route to a script doing the detailed analysis for the dedicated queues that are critical or exhausted.
Define
Non-XML Expression ${property.QueueCapacityStatus} = 'OK' for the branch going to the second
Router. Default branch is the branch to the
Filter step which is executed if the status is not 'OK'. In the
Filter you define an
XPath to the
//QueueStates to get the details for all the message queues available in the tenant. Note that you have to select
Nodelist as
Value Type.
In a
Script step evaluate the message queues and return all critical and exhausted message queues as properties
QueuesCriticalNames and
QueuesExhaustedNames,
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import groovy.xml.*;
import java.util.*;
import java.text.SimpleDateFormat;
def Message processData(Message message) {
def body = message.getBody(String.class);
def SourceMessage = new XmlParser().parseText(body);
def QueuesExhausted = "";
def QueuesCritical = "";
SourceMessage.QueueState.each {
value = it.text();
state = it.State.text()
name = it.Name.text()
if ("1".equals(state)) {
QueuesCritical = QueuesCritical +' '+ name
}
}
SourceMessage.QueueState.each {
value = it.text();
state = it.State.text()
name = it.Name.text()
if ("2".equals(state)) {
QueuesExhausted = QueuesExhausted +' '+ name
}
}
message.setProperty("QueuesCriticalNames", QueuesCritical);
message.setProperty("QueuesExhaustedNames", QueuesExhausted);
return message;
}
Check JMS Status in Router
In the second
Router step check the JMS Status and route to the mail receiver in case the JMS resources are critical or exhausted:
Define
Non-XML Expression ${property.JMSStatus} = 'OK' for the branch going to the
End event. Default branch is the branch to the
Mail receiver which is executed if the status is not 'OK'.
Configure Mail Receiver
Now we configure the
Mail receiver channel sending out the notification. Configure the mail server and authentication you want to use. In the
Mail Attributes define the mail receiver and sender mail address and the
Mail Subject and
Mail Body:
Subject:
JMS Ressources ${property.JMSStatus}
Mail Body:
The JMS Resources on the Cloud Integration tenant are ${property.JMSStatus}.
Overall Queue Capacity Status: ${property.CapacityStatus} (${property.PercentCapacity} Percent)
Capacity Status for Queues: Error: ${property.QueueCapacityError} Queues; Warning: ${property.QueueCapacityWarning} Queues; OK: ${property.QueueCapacityOK} Queues
Queues with Warnings:${property.QueuesCriticalNames}
Queues with Errors: ${property.QueuesExhaustedNames}
Queue Status: ${property.QueueStatus} (${property.Queues} / ${property.MaxQueues} )
Transactions Status: ${property.TransactionStatus}
Consumer Connections Status: ${property.ConsumerStatus}
Provider Connections Status: ${property.ProviderStatus}
Deploy and Run the Integration Flow
Configure the
Timer start event to run the flow every day or any other interval that suits your requirements. Deploy the integration flow.
Now you will get a Email as soon as the JMS resources get critical.