SAP Process Orchestration, ABAP Development, SAP Process Integration

View PIPO Monitoring logs from a SAP ABAP program

PO (Process Orchestration) message monitoring could be time consuming, annoying and difficult-to-do for most SAP users, especially as PO runs on JAVA stack and there is no ABAP stack to view message logs anymore. Therefore, most users may find it difficult to access the message monitor available on the JAVA stack and also it may be very confusing to read and understand. However, it is important to monitor PO messages, to identify issues that occur during data transfers between SAP to SAP, SAP to Non-SAP and Non-SAP to Non-SAP applications, with the help of SAP PO as a middleware.

Read More: SAP PO Certification Preparation Guide

The following blog will take you through a process, to implement an ABAP program that will enable you to get the required message monitoring details from SAP PO. This program will enable SAP users to simply enter a t-code, where they will be able to view all PO success and error logs in a detailed manner.

Two API’s provided by SAP PO, a SOAP API to get the list of error messages/detailed error messages and another REST API to get the number of success, failed and scheduled messages on SAP PO.

Given below are some of the information that the program will provide you.

  1. Number of failed, success and scheduled messages per day.
  2. Detailed log on all success and error messaged logged on SAP PO.
  3. Reason for error.
  4. Time and date.
  5. For File and IDOC scenarios, the file name and IDOC number.
  6. PO message monitoring ID.
  7. Sender/Receiver Details.

Now let’s see as to how we could implement the above process, with the help of the two API’s given by SAP PO.

Step 1 – View list of Actions available in the SOAP API

1. Open the WS Navigator to view and test web services available on PO. The WS Navigator allows you to test a Web service without a client. Use the following URL to get into WS Navigator.

http:// <host>:<port>/wsnavigator

2. Click radio button Provider System and select “Local Java AS” from the given drop down. And enter “AdapterMessageMonitoringVi” in the search bar.

Figure 1

Once searched, select the AdapterMessageMonitoringVi interface and click “Next”.

3. The next page will display a list of Operations/Methods that we could use in the API to get the monitoring details we need.

Here, we will be using Methods getMessageList and getLogEntries to demonstrate as to how we could retrieve PO monitoring data from an outside third party application.

Figure 2

Figure 3

Step 2 – Implementation of the SOAP API

1. Standard SAP has a default proxy that is provided to get the above data from PO’s Enterprise Service Builder. Enter T-code SPROXY and find the below namespace.

Under objects, you will be able to see the following service consumer.

Figure 5

2. However, the proxy class under this standard service consumer object will not give you the methods I have mentioned above (getMessageList, getLogEntries). Therefore, we need to create a new proxy using the standard SOAP API provided by SAP, to create a new service consumer (Same objects as above). Given below is the WSDL URL to create the service consumer.

http://<host>:<port>/AdapterMessageMonitoring/basic?wsdl&mode=ws_policy&style=document

Implementation of the above service consumer will enable the two proxy methods I have mentioned earlier.

Step 3 – Implementation of the REST API

We will be consuming the REST API with the help of SAP PO itself. Given below are the steps to configure the REST API on SAP PO with the help of the REST adapter.

1. First we need to build the ESR objects to consume the REST API. For this we need to know the request and response message structure for the REST API. Given below is the link for the XSD to import the request and response structures.

http://<host>:<port>/mdt/messageoverviewqueryservlet?componen

Once imported, the external definition should look like this.

Figure 6

2. Now create an inbound service interface for the receiver with the help of the above external definition. The service interface should be as follows.

Figure 7

3. Our next step would be to create objects for SAP, who will be the sender for the request and also the receiver of the response from the REST API.

Figure 8

Figure 9

Similar to the previous step, we need to create an outbound service interface for the sender, but for the sender we need to create a message type in addition.

Figure 10

4. Now we should map the request message and response message as follows.

Figure 11

Figure 12

Here I have implemented the following UDF (Figure 14) to get value from the component. There are seven components (Figure 13) return from the API, which will be as follows under node . Component values can be accessed from 1 to 7.

Figure 13

Figure 14

5. Now create the operation mapping for the request and response message mapping.

Figure 15

6. Now let’s consume the REST API from the integration builder. Here we will be using the SR_ENTRY_OVERVIEW_XPI view to get the required data.

The component name will be different from system to system. It can be viewed using the following URL.

http://<host>:<port>/mdt/messageovervi
  • R_ENTRY_VIEW_XPI – Message sorted by Receiver.
  • S_ENTRY_VIEW_XPI – Message sorted by Sender.
  • SR_ENTRY_VIEW_XP – Detail Message sorted by sender and Receiver.
  • SR_ENTRY_OVERVIEW_XPI – Overview Message sorted by Sender and Receiver.

The URL for the REST API is as follows.

http://<host>:<port>/mdt/messageoverviewqueryservlet?component=<XIComponentName>&view=SR_ENTRY_OVERVIEW_XPI&begin={begin}&end={end}

7. Now let’s create the receiver communication channel for the REST API.

Figure 16

As visible above, the REST API URL should be inserted under the REST URL tab. Then the Pattern Variable Replacement should be entered as shown above.

NOTE: The XPath Expression should be same as the request element given in the message mapping.

Figure 17

Next, the rest operation should be set to GET.

Figure 18

Finally, enter the PO username and password for basic authentication.

Figure 19

8. Rest of the steps would be similar to a normal scenario where a SOAP communication channel needs to be created for the receiver (SAP) and integration configuration needs to be created to link all objects.

Step 4 – Consuming both API’s from ABAP

The ABAP program will consume both APIs and create the following internal table using deep structures. As you see below, it will show the number of error, success and still processing messages in the PO monitor. It also gives the sender, receiver details.

Figure 20

The “DETAIL_MESSAGE” deep structure will provide the PI message ID and the file name/IDOC number respectively.

Figure 21

The “SUB_MESSAGE” deep structure will contain log details, if there are any errors logged in.

Figure 22

Attached below is the ABAP code I have written to consume results from both API’s, into ABAP internal tables.

class lcl_pimoni definition final.
  public section.

    constants: gc_error      type char1             value 'E',
               gc_success    type char1             value 'S',
               gc_ricef_id   type zvariable_name    value 'PI_MONI_INTERFACE',
               gc_maxcount   type int4              value 999999999,
               gc_filteridoc type string            value 'Processing IDoc document with number' ##NO_TEXT,
               gc_filterfile type string            value 'FILE_SUC_029' ##NO_TEXT,
               gc_proxy      type srt_lp_proxyclass value 'ZCO_ADAPTER_MESSAGE_MONITORING'.

    methods:
      constructor importing iv_fdate type sydats
                            iv_tdate type sydats.
  private section.

    types: begin of ty_log,
             sender_interface type zmessage_interface,
             message_key      type string,
             message_id       type string,
             sender_name      type string,
             receiver_name    type string,
           end of ty_log.

    methods:
      prepare_data importing iv_fdate       type sydats
                             iv_tdate       type sydats
                   returning value(re_data) type zget_message_list_in_doc,
      get_message_count importing iv_fdate           type sydats
                                  iv_tdate           type sydats
                        returning value(re_logcount) type zmt_moni_message_count_res,
      get_date  importing iv_date        type sydats
                returning value(re_date) type xsddatetime_z,
      determine_idoc_file importing it_log          type zaudit_log_entry_data_tab
                                    iv_messageid    type string
                          returning value(re_msgid) type string,
      conver_time_stamp importing iv_timestamp   type xsddatetime_z
                        returning value(re_time) type syst_uzeit.

endclass.
class lcl_pimoni implementation.

  method constructor.

    data: is_out        type zmt_monitor_log_out,
          lt_maindata   type table of ty_log,
          lt_outputdata type zdt_monitor_log_out_detail_tab.

    "Get Sender Interface names from Parameter table
    zcl_nka_util=>get_ricef_variables(  exporting iv_ricef    = gc_ricef_id
                                        importing et_db_vars  = data(lt_interface) ).

    try.
        "Retrive logical port name to get list of messages
        data(proxy) = cl_srt_wsp_ws_admin_manager=>get_mapping_targetlp_valuehelp( i_target_proxy = gc_proxy
                                                                                   i_mapping_name = gc_proxy ).
        "Instantiate new object to get list of messages
        data(lo_monilog) = new zco_adapter_message_monitoring( logical_port_name = value #( proxy[ 1 ]-lp_name optional ) ).
    
        "Retrieve all Error message details from PI, between from date and to date
        lo_monilog->get_message_list(  exporting input  = prepare_data( iv_fdate = iv_fdate
                                                                        iv_tdate = iv_tdate )
                                       importing output = data(lt_data) ).
        "Get only required elements for message processing
        lt_maindata = corresponding #( lt_data-response-list-adapter_framework_data ).

        if lt_maindata is initial.
          message text-003 type gc_success.
          return.
        endif.

        "Get log count details from PI, between from date and to date
        loop at get_message_count( iv_fdate = iv_fdate
                                   iv_tdate = iv_tdate )-mt_moni_message_count_res-row_data assigning field-symbol(<lfs_logcount>).

          loop at lt_maindata assigning field-symbol(<lfs_data>) where sender_interface-name  = <lfs_logcount>-interface
                                                                   and receiver_name          = <lfs_logcount>-receiver_component
                                                                   and sender_name            = <lfs_logcount>-sender_component.

            "Get details message for each message
            lo_monilog->get_log_entries( exporting input  = value zget_log_entries_in_doc( message_key  = <lfs_data>-message_key
                                                                                           archive      = space
                                                                                           older_than   = get_date( iv_tdate ) )
                                         importing output = data(lt_log) ).

            "$. Region Filter only error messages and remove duplicate messages
            sort   lt_log-response-audit_log_entry_data ascending by text_key.
            delete adjacent duplicates from lt_log-response-audit_log_entry_data comparing text_key.
            "$. Endregion Filter only error messages and remove duplicate messages

            "Add details error message to internal table, to be passed as a deep structure
            append value zdt_monitor_log_out_detail_mes(  msg_key     = <lfs_data>-message_id
                                                          uid         = determine_idoc_file(  it_log        = lt_log-response-audit_log_entry_data
                                                                                              iv_messageid  = <lfs_data>-message_id )
                                                          sub_message = value zdt_monitor_log_out_sub_me_tab( for ls_output in lt_log-response-audit_log_entry_data
                                                                        where ( status    = gc_error )
                                                                              ( textkey   = ls_output-text_key
                                                                                msg_type  = ls_output-status
                                                                                msg_text  = ls_output-localized_text
                                                                                date      = iv_fdate
                                                                                time      = conver_time_stamp( ls_output-time_stamp ) ) ) ) to lt_outputdata.
          endloop.

          "Add final data to outbound structure
          append value zdt_monitor_log_out_monitorlog( interface_id   = value #( lt_interface[ val1 =  conv zselection_val1( <lfs_logcount>-interface ) ]-val2 optional )
                                                       sender         = <lfs_logcount>-sender_component
                                                       receiver       = <lfs_logcount>-receiver_component
                                                       si_name        = <lfs_logcount>-interface
                                                       error          = <lfs_logcount>-error
                                                       success        = <lfs_logcount>-successfull
                                                       schedule       = <lfs_logcount>-scheduled
                                                       detail_message = lt_outputdata ) to is_out-mt_monitor_log_out-monitorlog.
          refresh: lt_outputdata.
        endloop.

      catch cx_ai_system_fault into data(lv_exc).
        message lv_exc->get_text( ) type gc_success.
    endtry.

  endmethod.

  method determine_idoc_file.

    "Retrieve IDOC number
    loop at it_log assigning field-symbol(<lfs_log>) where text_key cs gc_filteridoc.
      re_msgid = <lfs_log>-text_key+37(16).
      return.
    endloop.

    "Retrive File name in file scenario
    loop at it_log assigning <lfs_log> where text_key cs gc_filterfile.
      re_msgid = <lfs_log>-localized_text+18(40).
      return.
    endloop.

    "If IDOC number or File Name not available, return PI message ID
    if re_msgid is initial.
      re_msgid = iv_messageid.
    endif.

  endmethod.

  method prepare_data.

    "Preperation of input parameters to get message list
    re_data = value zget_message_list_in_doc( filter-archive              = abap_false
                                              filter-date_type            = 4
                                              filter-node_id1             = 0
                                              filter-only_faulty_messages = abap_false
                                              filter-retries              = 0
                                              filter-retry_interval       = 0
                                              filter-times_failed         = 0
                                              filter-was_edited           = abap_false
                                              max_messages                = gc_maxcount
                                              filter-from_time            = get_date( iv_fdate )
                                              filter-to_time              = get_date( iv_tdate ) ).
  endmethod.

  method get_date.

    call function 'CACS_DATE_GET_TIMESTAMP'
      exporting
        i_date                   = iv_date
      importing
        e_timestamp              = re_date
      exceptions
        date_not_filled_but_time = 1
        date_has_no_valid_format = 2
        others                   = 3.
    if sy-subrc <> 0 ##NEEDED.
      "This is unlikely to occur.
    endif.

  endmethod.

  method get_message_count.

    try .
        data(lo_rest)    = new zco_si_moni_message_count_out( ).
        "Get Error, Success and Schedule message count from PI server
        lo_rest->si_moni_message_count_out( exporting output = value zmt_moni_message_count_out( mt_moni_message_count_out-start_time_stamp  = iv_fdate
                                                                                                 mt_moni_message_count_out-end_time_stamp    = iv_tdate )
                                            importing input  = re_logcount ).
      catch cx_ai_system_fault into data(lv_error).
        message lv_error->get_text( ) type gc_success.
    endtry.

  endmethod.

  method conver_time_stamp.

    convert time stamp iv_timestamp time zone sy-zonlo
            into time re_time.

  endmethod.

endclass.

By looking at the above SAP ABAP and SAP PO Integration API’s, we can see how easily we could develop a simple but detailed custom PI Monitoring log. Both API’s could also be called by an external system where an external application will have access to SAP PO message monitoring.

Leave a Reply

Your email address will not be published. Required fields are marked *