Skip to Content
Author's profile photo Vadim Klimov

Writing Log Entries to Audit Log of the Message from Custom Java Mapping Program

When utilizing custom Java mapping programs, it is a common requirement to enrich them with the tracing/logging features that would be useful for further runtime analysis and troubleshooting by bringing more transparency to executed logic at least in part of major transformation steps.

The most commonly used approach that is well documented in SAP Help and often utilized and described on SCN is usage of trace entries. Trace entries can be inserted from the custom developed mapping program to runtime trace and further accessed via NetWeaver Log Viewer from PI application traces or collected by XPI Inspector.

Technically, this is achieved by employing corresponding methods of the object AbstractTrace (like methods com.sap.aii.mapping.api.AbstractTrace.addInfo(),com.sap.aii.mapping.api.AbstractTrace.addWarning()). The AbstractTrace object is, in its turn, obtained from AbstractTransformation (by invoking method com.sap.aii.mapping.api.AbstractTransformation.getTrace()) – that is the standard class extended by the custom class implementing transformation logic of the developed mapping program.

Utilization of trace functionality has some significant drawbacks that prevent its usage for normal monitoring activities – namely:

  • Increased trace severity level can negatively impact performance of traced applications. This is especially critical in case the system is used under high volume. As an outcome of this, precise traces are normally enabled for a short period of time (for example, when reproducing or facing the error) and are switched off / reduced to a lower severity level afterwards;
  • Trace output contains lots of detailed information collected and recorded at runtime for the traced application. As a result, further manual analysis of trace output may become a time consuming and complex activity.

For more information on insertion of trace entries in application to custom developed mapping programs, please refer to following materials:

If the intention is to extend processing log of PI messages with important information on custom mapping program execution that can be used by PI monitoring team, it is more natural to interact with audit log of the processed message. The motivation of this web blog is to provide a sample code snippet that can be used in custom mapping programs in order to add necessary information to the audit log of the message.

In this approach, the backbone is usage of Audit Log Manager functionality in part of interacting with the audit log of the specific message. The whole logic that needs to be implemented can be described as a sequence of following steps:

  1. Retrieve message ID and convert it to the format that is compliant to RFC 4122;
  2. Retrieve message direction;
  3. Based on obtained message ID and direction, construct message key;
  4. For the constructed message key, add audit log entry using methods of the interface AuditAccess.

The code fragment below illustrates how this can be achieved programmatically:

// Retrieve message ID from input header (com.sap.aii.mapping.api.InputHeader)
// of transformation input (com.sap.aii.mapping.api.TransformationInput).
String msgID = arg0.getInputHeader().getMessageId();
// Convert message ID to UUID format (in compliance to RFC 4122).
// UUID format is used by Advanced Adapter Engine for identifiers of processed messages.
// For the sake of simplicity, conversion is done manually - alternatively, specific libraries can be used for this.
final String DASH = "-";
String uuidTimeLow = msgID.substring(0, 8);
String uuidTimeMid = msgID.substring(8, 12);
String uuidTimeHighAndVersion = msgID.substring(12, 16);
String uuidClockSeqAndReserved = msgID.substring(16, 18);
String uuidClockSeqLow = msgID.substring(18, 20);
String uuidNode = msgID.substring(20, 32);
String msgUUID =
     uuidTimeLow + DASH + uuidTimeMid + DASH + uuidTimeHighAndVersion + DASH
     + uuidClockSeqAndReserved + uuidClockSeqLow + DASH + uuidNode;
// Construct message key (com.sap.engine.interfaces.messaging.api.MessageKey)
// for retrieved message ID and outbound message direction (com.sap.engine.interfaces.messaging.api.MessageDirection).
MessageKey msgKey = new MessageKey(msgUUID, MessageDirection.OUTBOUND);
// Add new audit log entry with status ‘Success’ (com.sap.engine.interfaces.messaging.api.auditlog.AuditLogStatus)
// to the audit log (com.sap.aii.af.service.auditlog.Audit) for the constructed message key.
Audit.addAuditLogEntry(msgKey, AuditLogStatus.SUCCESS,
     "Demo: This is an audit log entry that have been generated by custom mapping program");

As an outcome, the respective log entry is available in the audit log of the processed message and can be displayed for example using Message Monitor in PIMON:

Message processing log.png

Please note that instead of directly accessing the object com.sap.aii.af.service.auditlog.Audit, it is also possible to have an “extended” style of retrieving message audit log accessor using public API provided in the bounds of PI. This is normally superfluous for custom mapping programs, but may be useful when accessing Messaging System of PI externally:

try {
     // Retrieve instance of audit log accessor (com.sap.engine.interfaces.messaging.api.auditlog.AuditAccess)
     // using public API access factory (com.sap.engine.interfaces.messaging.api.PublicAPIAccessFactory).
     AuditAccess msgAuditAccessor = PublicAPIAccessFactory.getPublicAPIAccess().getAuditAccess();
     // Add new audit log entry with status ‘Success’ to the audit log of the message using the constructed message key.
     msgAuditAccessor.addAuditLogEntry(msgKey, AuditLogStatus.SUCCESS,
          "Demo: This is an audit log entry that have been generated by custom mapping program");
     } catch (MessagingException e) {
          // Exception handling logic.
          e.printStackTrace();
     }

For more information on corresponding used Java objects, please refer to PI Javadocs that are available on SAP Help: http://help.sap.com/javadocs/NW73EHP1/SPS09/PI/index.html .

Assigned Tags

      14 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Wenning Gao
      Wenning Gao

      Hi Vadim,

      Nice to see the blog. I did not try this yet, but my impression audit log is more for adapter module, I wonder if you run the map in test mode(inside ESR), whether or not this will go through?

      --Wenning

      Author's profile photo Vadim Klimov
      Vadim Klimov
      Blog Post Author

      Hi Wenning,

      No, this example function will not run successfully in mapping test tool if executed in ESR since it utilizes some object attribites that are filled only at runtime: message ID, audit log are not available when you test mapping locally from ESR. Thus, it is necessary to test such functions end-to-end, with normal message flow (not as unit tests of specific pieces or steps).

      Regarding audit log of the message. The audit log of the message was and is considered as a backbone for auditing and persisting information on processing steps executed in (Advanced) Adapter Engine - thus, not only information on adapter / adapter module execution. But, historically, quite a lot of message flow steps within PI were done in ABAP stack - that's why less information was persisted in the audit log. Now, more and more scenarios are involving much more extensive set of processing steps being executed in PI components deployed in Java stack (in extreme case, think about Java-only scenarios - like those based on Integrated Configuration - where all processing steps of message flow in PI are purely executed in Java stack of PI). As a result, the task of making these steps (namely, XML validation, routing, mapping, adapter and adapter modules execution) execution more transparent for PI monitoring team by inserting more details on these steps into the audit log of the message became more important.

      Regards,

      Vadim

      Author's profile photo Former Member
      Former Member

      Hi Vadim,

      Nice blog did you perform this also in an UDF (graphical mapper) or only via javamapping? If so what archives /lib did you add on the import instructions.

      Thanks,

      Christan van Mook.

      Author's profile photo Vadim Klimov
      Vadim Klimov
      Blog Post Author

      Hello Christan,

      Thank you for your positive feedback.

      Originally, this feature was developed for usage in custom Java mapping programs - but it can be adopted for utilization in user-defined functions / function libraries as well. Precisely, in order to acquire message ID, instead of querying input header of transformation input (as it was done in custom Java mapping program), in UDF/function library, we can acquire it from mapping runtime constants:

      java.util.Map map = container.getTransformationParameters();

      String msgID = (String) map.get(StreamTransformationConstants.MESSAGE_ID);

      final String DASH = "-";

      String uuidTimeLow = msgID.substring(0, 8);

      String uuidTimeMid = msgID.substring(8, 12);

      String uuidTimeHighAndVersion = msgID.substring(12, 16);

      String uuidClockSeqAndReserved = msgID.substring(16, 18);

      String uuidClockSeqLow = msgID.substring(18, 20);

      String uuidNode = msgID.substring(20, 32);

      String msgUUID =

           uuidTimeLow + DASH + uuidTimeMid + DASH + uuidTimeHighAndVersion + DASH

           + uuidClockSeqAndReserved + uuidClockSeqLow + DASH + uuidNode;

      MessageKey msgKey = new MessageKey(msgUUID, MessageDirection.OUTBOUND);

      Audit.addAuditLogEntry(msgKey, AuditLogStatus.SUCCESS,

           "Demo: This is an audit log entry that has been generated by UDF from the graphical mapping");



      As you can see from the function implementation, following classes are used there:

      • com.sap.aii.af.service.auditlog.Audit
      • com.sap.engine.interfaces.messaging.api.MessageDirection
      • com.sap.engine.interfaces.messaging.api.MessageKey
      • com.sap.engine.interfaces.messaging.api.auditlog.AuditLogStatus

      You can find these classes in the following two libraries (both libraries are a part of Adapter Framework):

      • com.sap.aii.af.svc_api.jar
      • com.sap.aii.af.ms.ifc_api.jar

      Regards,

      Vadim

      Author's profile photo Former Member
      Former Member

      Hello Vadim,

      I got a similar scenario in SAP PI 7.31 server. I have done everything correct but could not able to get the Custom Error message in Runtime Work bench.

      My code in XSLT is as follows:

      <xsl:choose>

             <xsl:when test="$result=''">

                 <xsl:choose>

                       <xsl:when test="function-available('el:execute')">

                            <xsl:value-of select="el:execute('UNITS',$MID)"/>

                                 <xsl:message terminate="yes"/>

                       </xsl:when>

                       <xsl:otherwise>

                            <xsl:value-of select="NULL"/>

                       </xsl:otherwise>

                 </xsl:choose>

             </xsl:when>

             <xsl:otherwise>

                  <xsl:value-of select="$result"/>

             </xsl:otherwise>

      </xsl:choose>

      Java Code for execute method:

           MessageKey key = null;

         AuditAccess audit = null;

         try

         {

               audit = PublicAPIAccessFactory.getPublicAPIAccess().getAuditAccess();

               key = new MessageKey(messageid, MessageDirection.OUTBOUND);

               audit.addAuditLogEntry(key, AuditLogStatus.SUCCESS, errorMsg);

               return "Success";

         }

         catch (Exception e)

         {

               Exception me = new Exception(e);

               return "Failure";

         }

      Regards,

      Ramji Killani

      Author's profile photo Vadim Klimov
      Vadim Klimov
      Blog Post Author

      Hello Ramji,

      The question you have raised is rather for a forum thread than for blog comments - so if you post it at forum, you will likely have more chances of it beeing looked at and discussed/answered by other PI specialists.

      Regarding the issue, I would firstly recommend to check how the variable messageid is populated and what its value at runtime of the mapping execution is (e.g. by writing its value temporary to the trace or debugging the mapping) - so that we eliminate the problem of invalid message ID right at the beginning.

      Regards,

      Vadim

      Author's profile photo Former Member
      Former Member

      Hello Vadim,

      The messagId is being properly populated at runtime. So I think, no problem with the messagId.

      Regards,

      Ramji Killani

      Author's profile photo stephen xue
      stephen xue

      hi Ramanji

      the message id got from the XSLT mapping is the id without hyphen. and for some reason the AAE cannot recognise it. please add the hyphen as per in Vadim's example and try again. it should be working.

      good luck.

      Author's profile photo Former Member
      Former Member

      Hi Stephen,

      Yeah. It is working.

      Thank you.

      Ramji Killani

      Author's profile photo Former Member
      Former Member

      Hi Vadim,

      I am working for a scenario where I need to retrieve Audit logs of a message based on message key. Do we have any classes to retrieve the Audit logs based on message key.

      Thank in Advance,

      Ramanji Killani.

      Author's profile photo Vadim Klimov
      Vadim Klimov
      Blog Post Author

      Hello Ramanji,

      Depending on specific requirement, you have variety of options to retrieve audit log entries for a message by its message key:

      - AuditLogManager and AuditLogBean (see Message details and AuditLog from Java Stack using Custom WebService),

      - SOAP service AdapterMessageMonitoringVi (see Reading Messages from PI System and Michal's PO/PI tips: Audit Logs from a native WS - new feature ).

      Regards,

      Vadim

      Author's profile photo Anupam Ghosh
      Anupam Ghosh

      Hi Vadim,

      The code is not getting compiled in NWDS. Is there any external jar file required to compile this code.  The line where compiler throws an error is

      "MessageKey msgKey = new MessageKey(msgUUID, MessageDirection.OUTBOUND);"

      Regards

      Anupam

       

      Author's profile photo Vadim Klimov
      Vadim Klimov
      Blog Post Author

      Hello Anupam,

      Yes, for interfaces and classes in the package 'com.sap.engine.interfaces.messaging.api' and its subpackages (such as MessageDirection, MessageKey, PublicAPIAccessFactory, AuditAccess, AuditLogStatus, MessagingException), you need to ensure that the library com.sap.aii.af.ms.ifc_api.jar is present in the build path.

      The mentioned library can be found on PI/PO application server at /usr/sap/<SID>/<instance>/j2ee/cluster/bin/interfaces/com.sap.aii.af.ms.ifc/lib/com.sap.aii.af.ms.ifc_api.jar.

      Alternatively, it is also contained in NWDS distribution, in the library 'XPI Adapter Libraries', and is named com.sap.aii.af.ifc.filter.jar, so you shall be able to use even local NWDS libraries to overcome this dependency issue.

      Regards,

      Vadim

      Author's profile photo Anupam Ghosh
      Anupam Ghosh

      Hi Vadim,

      I think this is the best blog on the topic of logging and tracing.

      Very helpful indeed.

      Regards

      Anupam