Skip to Content
Technical Articles

Modify Notifications from SAP CPI to SAP Cloud Platform Alert Notification

Introduction

In the great blog by Kiril Receive Notifications for Failed SAP Cloud Platform Integration Flows via Any Channel with Alert Notification you could learn how to send notifications for failed iFlows from CPI to SAP ANS. It helped me a lot in my development and implementation however I faced some problems due to lack of flexibility when it comes to notification payload. I managed to work it out however and in this blog I’ll show you how.

I’ll describe how you can change the standard SAP iFlow in a way it’ll send more information to ANS. I’ll also present how you can run more than one at the same time and tell the difference between them in ANS.

The iFlow

As described in the blog by Kiril the standard iFlow you will be using is “Send notifications for failed Message Processing LogsMessage” from the SAP package “SAP Cloud Platform Integration with SAP Cloud Platform Alert Notification”.

In order to be able to modify it you will need to create a new package and copy it there. In my case it looks like this:

So far so good! Now let’s take a look how it works. We’ll be interested in two parts of the flow.

1. OData adapter

When you look at the configuration you’ll notice that Query Options narrows down the query to IntegrationArtifact node. We don’t want that!

Look at the example (taken from SAP API Business Hub):

      {
        "MessageGuid": "AFq478Bblxi4wCjBcDb_G0vAGGZG",
        "CorrelationId": "AFq478Bmn-aPieAWVy0mMGPLWsjx",
        "ApplicationMessageId": 0000000123,
        "ApplicationMessageType": null,
        "LogStart": "/Date(1522069440003)/",
        "LogEnd": "/Date(1522069440200)/",
        "Sender": null,
        "Receiver": null,
        "IntegrationFlowName": "IntegrationFlow_AdapterData_FAILED_PROCESSING",
        "Status": "FAILED",
        "AlternateWebLink": "https://sandbox.api.sap.com:443:443/itspaces/shell/monitoring/MessageDetails/%7B%22messageGuid%22%3A%22AFq478Bblxi4wCjBcDb_G0vAGGZG%22%7D",
        "IntegrationArtifact": {
          "Id": "IntegrationFlow_AdapterData_FAILED_PROCESSING",
          "Name": "Integration Flow with Adapter Data - FAILED PROCESSING",
          "Type": "INTEGRATION_FLOW"
        },
        "LogLevel": "INFO",
        "CustomStatus": "FAILED",
        "TransactionId": "636260297acc487198a65955d3648c49",
        "PreviousComponentName": "CPI_cpisbsa1",
        "LocalComponentName": "CPI_cpisbsa1",
        "OriginComponentName": null,
        "CustomHeaderProperties": {
          "__deferred": {
            "uri": "https://sandbox.api.sap.com:443:443/cpi/api/v1/MessageProcessingLogs('AFq478Bblxi4wCjBcDb_G0vAGGZG')/CustomHeaderProperties"
          }
        },
        "MessageStoreEntries": {
          "__deferred": {
            "uri": "https://sandbox.api.sap.com:443:443/cpi/api/v1/MessageProcessingLogs('AFq478Bblxi4wCjBcDb_G0vAGGZG')/MessageStoreEntries"
          }
        },
        "ErrorInformation": {
          "__deferred": {
            "uri": "https://sandbox.api.sap.com:443:443/cpi/api/v1/MessageProcessingLogs('AFq478Bblxi4wCjBcDb_G0vAGGZG')/ErrorInformation"
          }
        },
        "AdapterAttributes": {
          "__deferred": {
            "uri": "https://sandbox.api.sap.com:443:443/cpi/api/v1/MessageProcessingLogs('AFq478Bblxi4wCjBcDb_G0vAGGZG')/AdapterAttributes"
          }
        },
        "Attachments": {
          "__deferred": {
            "uri": "https://sandbox.api.sap.com:443:443/cpi/api/v1/MessageProcessingLogs('AFq478Bblxi4wCjBcDb_G0vAGGZG')/Attachments"
          }
        },
        "Runs": {
          "__deferred": {
            "uri": "https://sandbox.api.sap.com:443:443/cpi/api/v1/MessageProcessingLogs('AFq478Bblxi4wCjBcDb_G0vAGGZG')/Runs"
          }
        }
      }

If we narrowed it down only to “IntegrationArtifact” we would loose quite a bit of details. My requirement was to present MessageGuids and ApplicationMessageIds as these were idoc numbers pretty relevant for identifying the issue.

In a summary – remove

&$select=IntegrationArtifact

from the query (if you need these details, I did).

2. Map Message Process Logs to Service Notifications

The second part is more interesting – we’ll need to groovy a little bit. The above script is responsible for sending the notification to ANS service. We would like to modify it a little bit. The below is my proposition:

Event toNotification(String flowId, def messages, Message message) {

	String flowName = messages[0].IntegrationArtifact.Name.toString()
	String flowType = messages[0].IntegrationArtifact.Type.toString()
	String currentTimeFrameStart = getStringHeader(message, CURRENT_TIME_FRAME_START_HEADER_NAME)
	String currentTimeFrameEnd = getStringHeader(message, CURRENT_TIME_FRAME_END_HEADER_NAME)
    
    //Added --------------
    //The flow sends aggregated results therefore all failed guids/idocs will need to be aggregated as well
    StringBuilder applicationMessageIds = new StringBuilder("")
	//Loop through messages and get the details
	for(mess in messages) {
	    if(mess.ApplicationMessageId.toString()){
	        applicationMessageIds.append(";" + mess.ApplicationMessageId.toString())
	    } else {
	        applicationMessageIds.append(";" + mess.MessageGuid.toString())
	    }
	} 
    //Added --------------
    
	return new Event(
           //You can modify eventType too!
			eventType: "CPIIntegrationFlowExecutionFailure",
			resource: new Resource(
					resourceName: flowName,
					resourceType: flowType
			),
			severity: "INFO",
			category: "NOTIFICATION",
			subject: "CPI Integration Flow '${flowName}': Execution Failure",
			body: "There were '${messages.size()}' failures for the '${flowName}' integration flow within the time frame starting from '${currentTimeFrameStart}' and ending at '${currentTimeFrameEnd}'. ",
			tags: [
					'cpi:IntegrationArtifact.Id': flowId,
                    //Added --------
					'Details': applicationMessageIds.toString()
					//Added --------
			]
	)

}

With the above sneaky move we can send the exact messages that failed to ANS. You can add as many tags as you want, this was the best place and way to send more information than standard SAP flow allowed me to. I also tried to be smart and change class Event:

class Event {
	String eventType
	Resource resource
	String severity
	String category
	String subject
	String body
	Map tags
}

But ANS failed at this point so I would suggest operating only on tags.

Parallel ANS iFlows

If you were cautious you noticed in the coding above that modifying eventType is also allowed. With such flexibility you could run more than one with different eventType to be able to differentiate them in ANS. In my case it was a different severenity of raised incidents in a webhook across day and night. Therefore I created two flows, one for night and one for day with different eventTypes and in ANS I was able to tell what severity I want (it was supposed to be lower at night).

Alert Notification Service

On the ANS side when notifications are received you can get new nodes exactly as you would with standard ones. In my case:

{tags.Details}

Summary

In the above blog I described a way to modify the standard SAP iFlow to send notifications to ANS. As you have already noticed if you dig deep enough you can extract pretty much information from CPI.

What I described is only a proposition what can be achieved. I’m sure you will be able to figure out a solution tailored to your needs with some research and grooving. I hope the above post will give you a good starting point to do so.

2 Comments
You must be Logged on to comment or reply to a post.