Skip to Content

Does this ring a bell?

Have you heard this from business “We need details of  application error occurred for synchronous interface related to application “xyz” or based on other parameter like business system….during specific time periods etc.. ?,

Last week, I was asked similar question but in slight different way

Production support team wants to know out of 76000 application error messages (mainly sync faults) occurred yesterday what are the error code or description and how many of them are repeating to which interface, business system  & application name within SAP CRM for ex.

They want to know error descriptions, their number, service & operation Names,  so that they can prioritize which one to pick up first & also to track most common/ repeating error codes coming in last 1 month.

that’s how this blog started………………

General views:

Cost of logging synchronous logging in PRODUCTION environment is very high, especially when response times really matter so we generally prefer to turn off logging for synch messages in PI & ABAP. By default, PI & ABAP logs errors messages for synchronous. But when it comes to Faults messages, these are handled slightly differently, PI treats Application faults as success hence not logged, whereas ABAP logs application errors coming using Fault structures. Proxy framework looks specifically value of messageclass, if value is ApplicationError then treats message as Application Error.

<sap:MessageClass>ApplicationError</sap:MessageClass>

As message is logged in ABAP stack, no choice but can use sxmb_moni to see what it is and take action but trouble starts when there are few hundreds or thousands fault messages returned back to ABAP stack? or write custom solutions to extract what we need from standard tables.

Custom developments on ABAP to get error information is nothing new, there are very good blogs on SDN how to build it & which tables to look into, steps mainly are (Different requirements can have different steps so please ignore if you find 4 steps too much)

Step 1: From table SXMSPMAST, get all message ID’s for record where field value of MSGSTATE is 024— Application Error

Step 2: From SXMSPEMAS for interface names.

Step 3:  From SXMSPERROR for error details.

Step 4:  Finally open payload if needed to check fault message structures from cluster tables sxmsclur and sxmxclup.

Reason for more than 1 step is we don’t get all information required from single table, in that sense PI JAVA stack is better, most of the information is present in BC_MSG

Problem Description:

Scenario: Suppose you have 4000 faults messages and you run 40 synchronous interfaces, called by 4 different applications/programs.

As first step, 

Step1: I want to simply know different fault error description or codes and number of interfaces having  same error, after this information I then decide to see payload.

Step2: Group them by application wise or program name wise who has called etc.…….

End of the day, I simply want to get fault message overview based on ApplicationID + Fault Codes + Error Description, similar to message overview but top hierarchy should be error code or descriptions or any other parameter that customer wants.

Current Use Case:

Customer landscape has 20+ million synchronous calls from SAP CRM to various legacy systems via 3 PI systems, daily we might have few thousands fault messages, this could be various reasons, incorrect data, something wrong in legacy side which is returned as application faults….etc.

Production support team had simple requirement,

out of all application errors, group based on error codes, error descriptions (these values are present in each fault structures) of faults and how many of them are from which applicationID’s so that priority can be given based on type of errors.

 

Here comes the Saviour…………

Out of all the tables in SAP ABAP stack related to sxmb_moni, table SXMSPERROR is life savior, this tables turns out to be key in simplifying things.

Let’s run below statement from SXMSPERROR table.

“select distinct ERRCAT as ERRCAT, ERRCODE as ERRCODE, count(1) as recordCount from sxmsperro2 group by ERRCAT,ERRCODE;”

 

Output has 74k faults messages, we still don’t know the error grouping in each

SAP stores Error category and error codes, for Synchronous faults the default value are

ERRCAT—- SOAP

ERRCODE—- APPLICATION_ERROR (<sap:MessageClass>ApplicationError</sap:MessageClass> )

There is another field which is THE PLACE to hold what we need is “ERRTXT”.

Desired Output from SXMSPERROR table

 

Dive into Technical Details:

SXMSPERROR is life savior only when we use it in proper way. Before using it in proper way, let’s see how it works by default.

Below is the picture of normal fault message which might look like below one, the field values are mapped to sxmxperror table fields to get idea how this is linked.

 

 

Question is what influences values of these 3 fields, how does the text “Applications errors have orrcured” appeared in AdditionalText? Why not some other text?

 Lets take step back into PI and recollect Fault structures.

AS per SOAP foramt typical Fault Structure looks like below (from w3schools)

 

SAP PI doesn’t allow changes to field  <faultcodes>, <faultstring>, <faultactor> fields even though they are in SOAP Body, only field which we have control is inside <detail>

Reason is faultsCode and FaultString when genereated by webservice host, this should be sent unaltered to clients, there is no logical reason to change this.

If webservice host sends FaultString in SOAP fault body, this field value will gointo AdditonalText field (sxmxperror-errtxt field), if faultstring is empty then “Application errors have occurred” text is inserted by Proxy frame work.

 

Below picture gives the link between SOAP 1.1 BODY which has fault to ABAP tables:

 

Since in this case SOAP 1.1/1.2 fault message is converted to XI 3.0 message format, we have bit control to overwrite AdditionalText field which gets stored into ERRTEXT CLOB field in table SXMXPERROR.

Possible Solution Details:

All we have to do it so overwrite values in ERRCAR, ERRCODE & ERRTXT fields as per our needs then its lot easier we will be able to get overview In any order we want to group, before we think of passing values, let’s check the field length of ERRCAT, ERRCODE as shown in below picture, its

 

ERRCAT:    60 Byte (cannot be more than 60bytes, so interface name if long doesn’t fit)

ERRCODE: 90 Byte (cannot be more than 90bytes, so interface name if long doesn’t fit)

ERRTXT: CLOB (this is the place I have full control to pass what we need)

Note:

Assuming Deletion switch is enabled in CRM, table name will be

Container1: sxmsperror

Container2: sxmxperro2 (This name is bit strange but this is what it is in 7.5 version)

Our Solution:

We choose following values into SXMSPERROR table

  1. ERRCAT = ApplicationID (Which application in SAP CRM error belongs to)
  2. ERROCODE = “CFault”(Just to indicate this is custom fault, helps in extraction)
  3. ERRTXT = “InterfaceName:OperationName:ErroCode:ErrorDescription”

You can just run simple query to get overview:

“select ERRCAT, distinct dbms_lob.substr( ERRTXT, 1000,1 ) from sxmsperror where ERRCODE=’CFault’ group by ERRCAT, distinct dbms_lob.substr( ERRTXT, 1000,1 ) “

Above 3 fields could be used based on specific requirements, this gives developers lot of flexibility in getting basic information out without opening payloads, once we have this certainly we can open payload if you want to investigate further.

SAP PI changes to make overwrite information in SXMXPERROR table fields.

We need an adapter module which will update structure called <sap:Error></sap:Error> in XI3.0 message format.

I am just pasting the relevant part of the code  in adapter module.

InterfaceName, operationName & errorText you can get it either from payload or put in some dynamic configuration from fault mappings…….

Currently, the way I have implemented is that, all required values for ERRTXT field is extracted using dynamic configuration variable, these variables are created from fault mappings.

public ModuleData process(ModuleContext moduleContext, ModuleData inputModuleData) throws ModuleException {
String appID = "Get it from fault mappings or dynamic configurations variables"
ismessageFault = msg.getMessageClass().toString();
if(ismessageFault.equals("ApplicationError")) {					
com.sap.engine.interfaces.messaging.api.ErrorInfo errorInfo = msg.createErrorInfo();
errorInfo.setAttribute("ErrorCode",appID);
errorInfo.setAttribute("ErrorArea","cFault");
errorInfo.setAttribute("P1", "http://www.faultTesting/soap/body/fault/message");
errorInfo.setAttribute("P2", ""); 
errorInfo.setAttribute("ErrorCategory","Application");
errorInfo.setAttribute("AdditionalErrorText",additionalText);
errorInfo.setAttribute("ApplicationFaultInterface", "Fault_FM");
errorInfo.setAttribute("ApplicationFaultInterfaceNamespace", "urn:faultsTesting:crm:common");
msg.setErrorInfo(errorInfo);
}		

inputModuleData.setPrincipalData(msg);
return inputModuleData;

}

Channel Configuration:

This option gives us lot of flexibility to get error information’s we need, down side is its quite a change for interfaces which are already running in production which doesn’t have fault messages defined, might be for new ones we can follow this approach……., we definitely need flexibility to not only track error but track in the way we want to based on organization needs, said that there could be other better ways to do it so any comments or criticism is most welcome.

To report this post you need to login first.

1 Comment

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

Leave a Reply