Skip to Content

In my introduction to this blog series I laid out my objectives. I’ll restate them here to make sure we’re all on the same page: in this series we are going to build a lightweight proof-of-concept dashboard that displays SAP technical performance data in an interesting and visually stimulating way.

As you know by now I’m adhering to the following structure:

  1. Picking the Visualization  – introducing D3.js and the concept of data joins;
  2. Introduction to the SAPUI5 Shell ‘bootstrap’ environment and how to integrate components;
  3. Description of the SAP SMON functions and how to creating a new service in the SAP ICF (you are here);
  4. Bringing it all together – this is the installment that I’ll use to describe each of the individual steps

SICF

So what is the SAP Internet Connection Framework?

I’ll leave that to DJ Adams who defines the ICF technology as:

”a collection of configuration, interfaces, classes and a core set of processes that allow us to build HTTP applications directly inside SAP

This is epic! It means we have a full blown web server within SAP. ‘So what?’ I hear the cynics out there cry. Well it means we have a stack of functions that can receive Hyper Text Transfer Protocol requests from ‘the internet’ and invoke ABAP functions on the SAP back-end server, this logic can collect data and package it up as a RESTful reponse. What, we can call ABAP functions via HTTP, why did nobody tell me! What do I have to do to get this … nothing!?! Are you freaking kidding me! Tell me more.

The ICF can be called via SAP transaction SICF:

SICF.png                   

You will find a list of services that can be invoked:

SICF List.png

Once active, each can be invoked via the following address pattern:

A service looks like this:

SICF Example.png

Each service calls (at least) one Handler Class – that’s where we put the ABAP logic in a service we’ll create, see the next section for an introduction. And yes, each service can be configured for secure access. There are a number of security options but in the interests of keeping your attention I’m not going into those here, try this link for more, if you need it.

The Handler

SICF -> <path to your service> -> Handler List

  Handler List.png

The ‘handler’ is a class, that means object-orientated ABAP. Not a problem, you can create a new class in SAP transaction SE24 (or from SE80), be sure to implement the IF_HTTP_EXTENSION interface and add your own code into the method (don’t worry, all will be explained).

Here is the code we will deploy via our service to access the SAP performance functions to return the Memory consumption, CPU and Network data.

METHOD if_http_extension~handle_request.

  DATA: name         TYPE string.

  DATA: l_tf_mem_all    TYPE TABLE OF mem_all,

         l_tf_cpu_all    TYPE TABLE OF cpu_all,

         l_tf_lan_single TYPE TABLE OF lan_single,

         s_mem_all       LIKE LINE OF l_tf_mem_all,

         s_cpu_all       LIKE LINE OF l_tf_cpu_all,

         s_lan_single    LIKE LINE OF l_tf_lan_single,

         l_free_mem      TYPE n LENGTH 8,

         l_phys_mem      TYPE n LENGTH 8,

         l_swap_free     TYPE n LENGTH 8,

         l_swap_max      TYPE n LENGTH 8,

         l_free_mem_pc   TYPE n LENGTH 8,

         l_swap_free_pc  TYPE n LENGTH 8,

         l_lastcollwrt   TYPE char25,

         l_idle_total    TYPE n LENGTH 8,

         l_packets       TYPE n LENGTH 8,

         json_string     TYPE string.

  CALL FUNCTION ‘FILL_SNAPSHOT_DATA’

*     EXPORTING

*       LOCAL_REMOTE                         = ‘LOCAL’

*       LOGICAL_DESTINATION                  =

*       SYSTEM_ID                            = 0

     IMPORTING

*       F_CPU_ALL_READ                       =

*       F_MEM_ALL_READ                       =

*       F_DISK_SINGLE_READ                   =

*       F_LAN_SINGLE_READ                    =

*       F_TOP_SINGLE_READ                    =

*       TAB_TYPE                             =

*       ACTIVEFLAG                           =

*       INTERVAL                             =

*       DETAILSCOLL                          =

*       DETAILSREQI                          =

*       DETAILSMODE                          =

       lastcollwrt                          = l_lastcollwrt

*       LASTCOLLINT                          =

*       NORMCOLLINT                          =

*       F_POOL_ALL_READ                      =

*       F_SPAG_ALL_READ                      =

*       F_STOR_ALL_READ                      =

*       F_CPU_SINGLE_READ                    =

*       F_POOL_SINGLE_READ                   =

*       F_CPU_VIRT_AIX_READ                  =

   TABLES

     tf_cpu_all                           = l_tf_cpu_all

     tf_mem_all                           = l_tf_mem_all

*       TF_DISK_SINGLE                       =

     tf_lan_single                        = l_tf_lan_single

*       TF_TOP_SINGLE                        =

*       TF_POOL_ALL                          =

*       TF_SPAG_ALL                          =

*       TF_STOR_ALL                          =

*       TF_CPU_SINGLE                        =

*       TF_POOL_SINGLE                       =

*       TF_CPU_VIRT_AIX                      =

*     EXCEPTIONS

*       INTERNAL_ERROR_ADRESS_FAILED         = 1

*       INTERNAL_ERROR_DIFFERENT_FIELD       = 2

*       INTERNAL_ERROR_NO_NEW_LINE           = 3

*       COLLECTOR_NOT_RUNNING                = 4

*       SHARED_MEMORY_NOT_AVAILABLE          = 5

*       COLLECTOR_BUSY                       = 6

*       VERSION_CONFLICT                     = 7

*       NO_NETWORK_COLLECTOR_RUNNING         = 8

*       SYSTEM_FAILURE                       = 9

*       COMMUNICATION_FAILURE                = 10

*       OTHERS                               = 11

            .

  IF sy-subrc <> 0.

*     MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO

*             WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.

  ENDIF.

*Get Timestamp

  CONCATENATE json_string

              ‘{“Timestamp”: “‘

              l_lastcollwrt(24)

              ‘”, ‘

    INTO json_string.

* Get Memory Data

  LOOP AT l_tf_mem_all INTO s_mem_all.

    l_free_mem = s_mem_all-free_mem.

    l_phys_mem = s_mem_all-phys_mem.

    l_swap_free = s_mem_all-swap_free.

    l_swap_max = s_mem_all-swap_max.

    l_free_mem_pc = l_free_mem  / l_phys_mem * 100.

    SHIFT l_free_mem_pc LEFT DELETING LEADING ‘0’.

    l_swap_free_pc = l_swap_free / l_swap_max * 100.

    SHIFT l_swap_free_pc LEFT DELETING LEADING ‘0’.

    CONCATENATE json_string

                ‘”free_mem_pc”: “‘

                l_free_mem_pc

                ‘”, ‘

        INTO json_string.

  ENDLOOP.

* Get CPU data

  LOOP AT l_tf_cpu_all INTO s_cpu_all.

    l_idle_total = s_cpu_all-idle_total.

    SHIFT l_idle_total LEFT DELETING LEADING ‘0’.

    CONCATENATE json_string

                ‘”idle_total”: “‘

                l_idle_total

                ‘”, ‘

        INTO json_string.

  ENDLOOP.

* Get Network data (currently only ‘lo’)

  LOOP AT l_tf_lan_single INTO s_lan_single

    WHERE lanname = ‘lo’.

    l_packets = s_lan_single-packets.

    SHIFT l_packets LEFT DELETING LEADING ‘0’.

    CONCATENATE json_string

                ‘”packets”: “‘

                l_packets

                ‘”}’

        INTO json_string.

  ENDLOOP.

* Enable this service to be available to other sites

*

  server->response->set_header_field( name = ‘Access-Control-Allow-Origin’ value = ‘*’ ).

*

* Return the results in a JSON string

*

  server->response->set_cdata( data = json_string ).

  1. ENDMETHOD.

SMON

I’ve been looking at the SMON package and a couple of the function modules SMON contains for a while now. I have previously put together a Flash widget that calls these functions, but that was before Flash ‘crashed’ (see what I did there).

These functions are used to access the SAP server performance data that is collected from the operating system by the SAPOSCOL service.

I decided to call the ‘FILL_SNAPSHOT_DATA’ function module because it’s the one that combines the various component functions to deliver a range of performance metrics.

Have a look at the earlier code snippet for a preview of the final solution which I’ll describe in the final post, coming up next.

The Same Origin Policy and SAP SICF

Before I ring off, a word of warning: when we deploy our mini-application on our local web server we will be calling functions from JavaScript that is sitting on a different domain. This is considered a security risk and a potential loophole that is closed by default.

We can however open up the policy on our SAP server, usually you would do this in an appropriate way, but we’ll use the following ‘*’ setting in our POC:

server->response->set_header_field( name = ‘Access-Control-Allow-Origin’ value = ‘*’ ).

As you can see from the code listing earlier we simply add this at an appropriate point on the handler method to allow cross-domain access (I struggled to understand this at first, so drop me a comment if its not clear to you too).

Well that’s all for this section. In the next and final instalment (the one you’ve probably been waiting for) I’ll go through each of these activities step-by-step to finalise the finished product. It may be a long weekend … and I may only begin after the Springboks have beaten the reigning rugby world champions in their antipodean back garden, let’s see how that goes … 😉

Andrew

To report this post you need to login first.

3 Comments

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

    1. Andrew Jabbitt Post author

      Hi Andy, many thanks for the feedback. Worry not, I’m motivated to deliver on my promise too.

      Andrew

      PS Being RSA based, the only team I was ever able to support in the Premiership was ‘the overseas Currie Cup side’: Saracens 😉

      (0) 

Leave a Reply