Use case – As part of debugging/monitoring, commonly used approach is sending mail alert in exception sub process to the application maintenance team (here in refer as AM Team). Also, sending a success execution summary mail with relevant interface details is send across to AM team or user depending on business requirement.
Challenge – Tracer logs data for 10mins and at near real-time. In cases where AM team needs more data for debugging post runtime execution, info level data in the monitoring log is not adequate for debugging. In complex interfaces with modular flows and process directs, tracing the flow execution gets consuming.
Approach – Keeping above points in thought, below is solution which I have applied in my design which is reusable. It is combination of below –
groovy scriptcustom headercontent modifier
Implementation –Β
1. Content Modifier – Set a variable with a custom text message according to your iflow logic. Key is to – set a logical text message which assist the Developer or AM Team to understand – which logic checkpoint is cleared or failed and why. This text message will appear in custom header and also in mail. One can set Content Modifier in Router branches, LIP, Exception subprocess, Multicast branches, before/after request reply call etc. as seem suited.
I am using variable – ‘FlowExecutionStatusMsg’ in Content modifier and Groovy scriptΒ
2. Below is the reusable Groovy Script which you can place in script collection or use locally in iflow. This needs to be placed in Exception Subprocess for Mail Alert and also at end of iflow for Interface Execution Summary Mail (optional). It captures the camel exception and runtime properties, headers and payload along with the custom text message set in the flow at the runtime.
/* Title – GS_InterfaceExecutionSummary.groovyscript. Objective – Groovy Script For Interface Execution Summary Mail ; captures runtime error, headers, properties and payload.
*/
import com.sap.gateway.ip.core.customdev.util.Message
//import groovy.json.JsonOutput
import java.text.SimpleDateFormat
Message processData(Message message) {
def messageLog = messageLogFactory.getMessageLog(message)
ββββββ
ββββββ//get message components
ββββββdef body = message.getBody(String)
def headers = message.getHeaders()
def properties = message.getProperties()
// Sort headers and properties alphabetically
def sortedHeaders = headers.sort { it.key }
def sortedProperties = properties.sort { it.key }
// Get timestamp in system timezone (runtime)
def sdf = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss z”)
def currentTimestamp = sdf.format(new Date())
//for attachment file
def label = “FlowLog_” + currentTimestamp.replace(” “, “_”).replace(“:”, “-“)
ββββββ// get custom logger details from flow
ββββββdef FlowExecutionStatusMsg = properties.get(“FlowExecutionStatusMsg”) ?: “Not Set”
def Iflow_Name = properties.get(“Iflow_Name”) ?: “Not Set”
def MPL_id = properties.get(“SAP_MessageProcessingLogID”) ?: “Not Set”
// Exception
def exceptionRaw = properties.get(“CamelExceptionCaught”)
def exceptionDetails = “”
if (exceptionRaw)
ββββββ{
def exMsg = exceptionRaw.getMessage() ?: exceptionRaw.toString()
def exType = exceptionRaw.getClass().getSimpleName()
exceptionDetails = “””
Exception Type: ${exType}
Message : ${exMsg}
Stack Trace:
${exceptionRaw.toString()}
“””
} else {
exceptionDetails = “— NO Exception Captured —“
}
// Start of Build HTML body
def html = new StringBuilder()
html.append(“<html><body>”)
html.append(“<p><strong>Hello Team,</strong></p>”)
html.append(“<p><strong>Kindly find Interface Execution Summary below :</strong></p>”)
//summary table startβ
ββββββhtml.append(“<table border=’1′ cellpadding=’5′ cellspacing=’0′>”)
ββββββhtml.append(“<tr><td><b>Flow Name: </b></td><td> ${Iflow_Name}</td></tr>”)
ββββββhtml.append(“<tr><td><b>Flow Execution CustomLogMessage :</b></td><td> ${FlowExecutionStatusMsg}</td></tr>”)
ββββββhtml.append(“<tr><td><b>MPL ID :</b></td><td> ${MPL_id}</td></tr>”)
ββββββhtml.append(“<tr><td><b>Timestamp:</b></td><td> ${currentTimestamp}</td></tr>”)
html.append(“<tr><td><b>Refer to Attachment in SAP IS Monitoring : FileName – </b></td><td> ${label}</td></tr>”)
ββββββhtml.append(“<tr><td><b>Exception Details : </b></td><td> ${exceptionDetails} </td></tr>”)
ββββββhtml.append(“<tr><td><b>Message Payload Body At Runtime Step: </b></td><td> ${body} </td></tr>”)
ββββββhtml.append(“</table><br>”)
//summary table end
//start of properties table
html.append(“<h4>Exchange Properties</h4>”)
html.append(“<table border=’1′ cellpadding=’5′ cellspacing=’0′>”)
html.append(“<tr><th>Property Name</th><th>Value</th></tr>”)
sortedProperties.each
ββββββ{ k, v ->
html.append(“<tr><td>${k}</td><td>${v}</td></tr>”)
}
html.append(“</table><br>”)
//end of properties table
//headers start table
html.append(“<h4>Message Headers</h4>”)
html.append(“<table border=’1′ cellpadding=’5′ cellspacing=’0′>”)
html.append(“<tr><th>Header Name</th><th>Value</th></tr>”)
sortedHeaders.each
ββββββ{ k, v ->
html.append(“<tr><td>${k}</td><td>${v}</td></tr>”)
}
html.append(“</table><br>”)
//headers end table
html.append(“<p>Kindly Do Not Reply to this auto-generated mail.Please contact SAP-Integration Support Team for further investigation.</p>”)
html.append(“<p>Regards,<br> SAP CPI Admin</p>”)
html.append(“</body></html>”)
// Note – Set Mail Adapter MIME type to “text/html”
def logMessage = html.toString()
message.setBody(logMessage)
// Log Attachment + Custom Header Property
if (messageLog != null)
{
messageLog.addAttachmentAsString(label, logMessage, “text/html”)
messageLog.addCustomHeaderProperty(“FlowExecutionStatusMsg”, FlowExecutionStatusMsg)
}
message.setProperty(“MailLogBody”, logMessage)
return message
}
Below are steps/code snippets and configuration need to be done in the interface –
Add Custom text message (logically for your debugging/monitoring) as per the Interface flow.Β
Add Iflow name which acts as identifier in complex mutliple flows development and will be displayed in mail too.
Mail configuration: I have used externalization for ease of code transport.Β
Configure From, To, Subject with specific details.
Mail body has the value set by the groovy output, which would be visible in the outlook mail.
In Monitoring tab, Custom Header below will reflect the custom text message set in the content modifier.
The attachment Flow log with the timestamp is set by the groovy script and would be visible in Monitoring tab for later debugging. It would have the runtime execution details.
The Mail body would consist of below details – Summary table, Properties and Headers. (I have scrubbed data for usage)Β
This can be altered in the groovy script as per one’s use case requirement.Β
Hope this assist you in smoother debugging.Β
P.S – This is my first blog despite spending a decade in Integration space, hope to invest time and effort consciously in blogging henceforth after project implementations going forth. Thanks.
Β
Β
βΒ Use case – As part of debugging/monitoring, commonly used approach is sending mail alert in exception sub process to the application maintenance team (here in refer as AM Team). Also, sending a success execution summary mail with relevant interface details is send across to AM team or user depending on business requirement.Challenge – Tracer logs data for 10mins and at near real-time. In cases where AM team needs more data for debugging post runtime execution, info level data in the monitoring log is not adequate for debugging. In complex interfaces with modular flows and process directs, tracing the flow execution gets consuming.Approach – Keeping above points in thought, below is solution which I have applied in my design which is reusable. It is combination of below -groovy scriptcustom headercontent modifierImplementation –Β 1. Content Modifier – Set a variable with a custom text message according to your iflow logic. Key is to – set a logical text message which assist the Developer or AM Team to understand – which logic checkpoint is cleared or failed and why. This text message will appear in custom header and also in mail. One can set Content Modifier in Router branches, LIP, Exception subprocess, Multicast branches, before/after request reply call etc. as seem suited.I am using variable – ‘FlowExecutionStatusMsg’ in Content modifier and Groovy scriptΒ 2. Below is the reusable Groovy Script which you can place in script collection or use locally in iflow. This needs to be placed in Exception Subprocess for Mail Alert and also at end of iflow for Interface Execution Summary Mail (optional). It captures the camel exception and runtime properties, headers and payload along with the custom text message set in the flow at the runtime./* Title – GS_InterfaceExecutionSummary.groovyscript. Objective – Groovy Script For Interface Execution Summary Mail ; captures runtime error, headers, properties and payload.
*/
import com.sap.gateway.ip.core.customdev.util.Message
//import groovy.json.JsonOutput
import java.text.SimpleDateFormat
Message processData(Message message) {
def messageLog = messageLogFactory.getMessageLog(message)
ββββββ
ββββββ//get message components
ββββββdef body = message.getBody(String)
def headers = message.getHeaders()
def properties = message.getProperties()
// Sort headers and properties alphabetically
def sortedHeaders = headers.sort { it.key }
def sortedProperties = properties.sort { it.key }
// Get timestamp in system timezone (runtime)
def sdf = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss z”)
def currentTimestamp = sdf.format(new Date())
//for attachment file
def label = “FlowLog_” + currentTimestamp.replace(” “, “_”).replace(“:”, “-“)
ββββββ// get custom logger details from flow
ββββββdef FlowExecutionStatusMsg = properties.get(“FlowExecutionStatusMsg”) ?: “Not Set”
def Iflow_Name = properties.get(“Iflow_Name”) ?: “Not Set”
def MPL_id = properties.get(“SAP_MessageProcessingLogID”) ?: “Not Set”
// Exception
def exceptionRaw = properties.get(“CamelExceptionCaught”)
def exceptionDetails = “”
if (exceptionRaw)
ββββββ{
def exMsg = exceptionRaw.getMessage() ?: exceptionRaw.toString()
def exType = exceptionRaw.getClass().getSimpleName()
exceptionDetails = “””
Exception Type: ${exType}
Message : ${exMsg}
Stack Trace:
${exceptionRaw.toString()}
“””
} else {
exceptionDetails = “— NO Exception Captured —“
}
// Start of Build HTML body
def html = new StringBuilder()
html.append(“<html><body>”)
html.append(“<p><strong>Hello Team,</strong></p>”)
html.append(“<p><strong>Kindly find Interface Execution Summary below :</strong></p>”)
//summary table startβ
ββββββhtml.append(“<table border=’1′ cellpadding=’5′ cellspacing=’0′>”)
ββββββhtml.append(“<tr><td><b>Flow Name: </b></td><td> ${Iflow_Name}</td></tr>”)
ββββββhtml.append(“<tr><td><b>Flow Execution CustomLogMessage :</b></td><td> ${FlowExecutionStatusMsg}</td></tr>”)
ββββββhtml.append(“<tr><td><b>MPL ID :</b></td><td> ${MPL_id}</td></tr>”)
ββββββhtml.append(“<tr><td><b>Timestamp:</b></td><td> ${currentTimestamp}</td></tr>”)
html.append(“<tr><td><b>Refer to Attachment in SAP IS Monitoring : FileName – </b></td><td> ${label}</td></tr>”)
ββββββhtml.append(“<tr><td><b>Exception Details : </b></td><td> ${exceptionDetails} </td></tr>”)
ββββββhtml.append(“<tr><td><b>Message Payload Body At Runtime Step: </b></td><td> ${body} </td></tr>”)
ββββββhtml.append(“</table><br>”)
//summary table end
//start of properties table
html.append(“<h4>Exchange Properties</h4>”)
html.append(“<table border=’1′ cellpadding=’5′ cellspacing=’0′>”)
html.append(“<tr><th>Property Name</th><th>Value</th></tr>”)
sortedProperties.each
ββββββ{ k, v ->
html.append(“<tr><td>${k}</td><td>${v}</td></tr>”)
}
html.append(“</table><br>”)
//end of properties table
//headers start table
html.append(“<h4>Message Headers</h4>”)
html.append(“<table border=’1′ cellpadding=’5′ cellspacing=’0′>”)
html.append(“<tr><th>Header Name</th><th>Value</th></tr>”)
sortedHeaders.each
ββββββ{ k, v ->
html.append(“<tr><td>${k}</td><td>${v}</td></tr>”)
}
html.append(“</table><br>”)
//headers end table
html.append(“<p>Kindly Do Not Reply to this auto-generated mail.Please contact SAP-Integration Support Team for further investigation.</p>”)
html.append(“<p>Regards,<br> SAP CPI Admin</p>”)
html.append(“</body></html>”)
// Note – Set Mail Adapter MIME type to “text/html”
def logMessage = html.toString()
message.setBody(logMessage)
// Log Attachment + Custom Header Property
if (messageLog != null)
{
messageLog.addAttachmentAsString(label, logMessage, “text/html”)
messageLog.addCustomHeaderProperty(“FlowExecutionStatusMsg”, FlowExecutionStatusMsg)
}
message.setProperty(“MailLogBody”, logMessage)
return message
}Below are steps/code snippets and configuration need to be done in the interface -Add Custom text message (logically for your debugging/monitoring) as per the Interface flow.Β Add Iflow name which acts as identifier in complex mutliple flows development and will be displayed in mail too.Mail configuration: I have used externalization for ease of code transport.Β Configure From, To, Subject with specific details.Mail body has the value set by the groovy output, which would be visible in the outlook mail.In Monitoring tab, Custom Header below will reflect the custom text message set in the content modifier.The attachment Flow log with the timestamp is set by the groovy script and would be visible in Monitoring tab for later debugging. It would have the runtime execution details.The Mail body would consist of below details – Summary table, Properties and Headers. (I have scrubbed data for usage)Β This can be altered in the groovy script as per one’s use case requirement.Β Hope this assist you in smoother debugging.Β P.S – This is my first blog despite spending a decade in Integration space, hope to invest time and effort consciously in blogging henceforth after project implementations going forth. Thanks.Β Β Β Β Read MoreΒ Technology Blog Posts by Members articlesΒ
#SAP
#SAPTechnologyblog