Application Development Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 

Is there a standard tool to quickly display and search ABAP Usage Data (SUSG)?

Sandra_Rossi
Active Contributor

Hello experts

In transaction SCMON, there is the button Display Data which allows filtering and displaying data from the tables SCMON*.

In transaction SUSG, I can't find a similar feature to query the tables SUSG* (which contain same kind of data but much older data):

Do you know if there's such a standard feature somewhere? (hidden button, ABAP program or whatever)

Or should I develop it? (quite easy)

Thanks!

I'm using ABAP 7.57 SP 0.

1 ACCEPTED SOLUTION

BaerbelWinkler
Active Contributor

sandra.rossi

Hi Sandra,

as far as I know there is still no standard program yet to read the SUSG-data (no clue why, really). There is however this snippet in bfeeb8ed7fa64a7d95efc21f74a8c135's e-Bite "Migrating Custom Code to SAP S/4HANA"

Per SAP, “You cannot display the aggregated usage data (neither in SUSG nor in SCMON or /SDF/SCMON). A remote enabled API is provided to read the aggregated usage data which you can use to implement your own display or extractor.”

Paul then also provides some sample code for such a program and I used that as a starting point to create our own version which provides some more details about the programs executed. Paul has kindly made his code publicly available in his Github repository: https://github.com/hardyp/S4HANA-ABAP-Code-Conversion (Thanks, Paul!)

So, you could use that as a starting point.

Please let me know if you'd like to get more information from the SUSG like I did and I can share the details of what I added to Paul's logic (like information about not just the main program but also each process block).

Hope this helps!

Cheers

Bärbel

6 REPLIES 6

BaerbelWinkler
Active Contributor

sandra.rossi

Hi Sandra,

as far as I know there is still no standard program yet to read the SUSG-data (no clue why, really). There is however this snippet in bfeeb8ed7fa64a7d95efc21f74a8c135's e-Bite "Migrating Custom Code to SAP S/4HANA"

Per SAP, “You cannot display the aggregated usage data (neither in SUSG nor in SCMON or /SDF/SCMON). A remote enabled API is provided to read the aggregated usage data which you can use to implement your own display or extractor.”

Paul then also provides some sample code for such a program and I used that as a starting point to create our own version which provides some more details about the programs executed. Paul has kindly made his code publicly available in his Github repository: https://github.com/hardyp/S4HANA-ABAP-Code-Conversion (Thanks, Paul!)

So, you could use that as a starting point.

Please let me know if you'd like to get more information from the SUSG like I did and I can share the details of what I added to Paul's logic (like information about not just the main program but also each process block).

Hope this helps!

Cheers

Bärbel

Hi Bärbel, nice, thanks a lot!

I'll try to extend Paul program in the next few days, to add more filter criteria in the selection screen, to make it look like SCMON data display, and I'll post it here.

Thanks for proposing your help. In fact I know better the SUSG tables than the SCMON tables, but of course they are somewhat 95% identical, so I guess it should be fine.

Regards

Sandra

Hi Sandra,

happy to help!

I added a bit to the selection-screen to be able to also get the called routines:

If checked, the output will contain more details:

I also added the logic to open the code in the editor.

I'm looking forward to what you come up with!

Cheers

Bärbel

0 Kudos

For information of other people, here are the screenshots from Paul original program:

Sandra_Rossi
Active Contributor

Here's a program. Note that it was compiled with ABAP 7.57 and S/4HANA 2022.

Feel free to improve it and publish your improvements and fixes.

Column heading "Start Date" is wrong, it's "Last used".

*&---------------------------------------------------------------------*
*&
*& Credits: inspired from Paul Hardy's program ZUSED_Z_CODE_REPORT at https://github.com/hardyp/S4HANA-ABAP-Code-Conversion :
*&          https://raw.githubusercontent.com/hardyp/S4HANA-ABAP-Code-Conversion/master/src/zused_z_code_report....
*&
*&---------------------------------------------------------------------*
REPORT z_view_susg.

*&---------------------------------------------------------------------*
*& Report ZUSED_Z_CODE_REPORT
*&---------------------------------------------------------------------*
* There is no standard SAP Program to analyze the results of SCMON/SUSG
* You have to write your own as described in Section 2.2.2
* This is the most basic program I could write to display the data.
* You could add all sorts of bells and whistles, such as automatically
* reclassifying unused objects to a shadow "unused" package hierarchy
*&---------------------------------------------------------------------*
*REPORT zused_z_code_report.

*--------------------------------------------------------------------*
* Seelection Screen
*--------------------------------------------------------------------*
DATA: BEGIN OF dummy_select_options_for,
        devclass   TYPE tadir-devclass,
        usage_kind TYPE susg_admin-kind,
        usgid      TYPE susg_admin-usgid,
        interval   TYPE scmon_date4interval,
        roottype   TYPE scmon_vdata_view-roottype,
        rootname   TYPE scmon_vdata_view-rootname,
        objtype    TYPE scmon_vdata_view-object,
        objname    TYPE scmon_vdata_view-obj_name,
        progname   TYPE scmon_vdata_view-progname,
        proctype   TYPE scmon_vdata_view-proctype,
        procname   TYPE scmon_vdata_view-procname,
        class      TYPE scmon_vdata_view-classname,
      END OF dummy_select_options_for.

"===================
" Package + USGID
"===================
SELECTION-SCREEN BEGIN OF BLOCK frame_miscellaneous WITH FRAME TITLE ft99.
  SELECT-OPTIONS s_devc FOR dummy_select_options_for-devclass OBLIGATORY DEFAULT 'Z*' SIGN I OPTION CP.
  SELECT-OPTIONS s_kind FOR dummy_select_options_for-usage_kind DEFAULT 'L'.
  SELECT-OPTIONS s_usgid FOR dummy_select_options_for-usgid.
SELECTION-SCREEN END OF BLOCK frame_miscellaneous.

"===================
" Calling request entry points
"===================
SELECTION-SCREEN BEGIN OF BLOCK frame_request WITH FRAME TITLE ft01.

  SELECTION-SCREEN BEGIN OF LINE.
    SELECTION-SCREEN COMMENT (28) txt_rtyp FOR FIELD so_rtype.
    SELECT-OPTIONS so_rtype FOR dummy_select_options_for-roottype.
  SELECTION-SCREEN END OF LINE.

  SELECTION-SCREEN BEGIN OF LINE.
    SELECTION-SCREEN COMMENT (28) txt_rnam FOR FIELD so_rname.
    SELECT-OPTIONS so_rname FOR dummy_select_options_for-rootname.
  SELECTION-SCREEN END OF LINE.

SELECTION-SCREEN END OF BLOCK frame_request.


"===================
" Called objects
"===================
SELECTION-SCREEN BEGIN OF BLOCK frame_object WITH FRAME TITLE ft02.

  SELECTION-SCREEN BEGIN OF LINE.
    SELECTION-SCREEN COMMENT (28) txt_otyp FOR FIELD so_otype.
    SELECT-OPTIONS so_otype FOR dummy_select_options_for-objtype.
  SELECTION-SCREEN END OF LINE.

  SELECTION-SCREEN BEGIN OF LINE.
    SELECTION-SCREEN COMMENT (28) txt_onam FOR FIELD so_oname.
    SELECT-OPTIONS so_oname FOR dummy_select_options_for-objname.
  SELECTION-SCREEN END OF LINE.

  SELECTION-SCREEN BEGIN OF LINE.
    SELECTION-SCREEN COMMENT (28) txt_prog FOR FIELD so_prog.
    SELECT-OPTIONS so_prog  FOR dummy_select_options_for-progname.
  SELECTION-SCREEN END OF LINE.

SELECTION-SCREEN END OF BLOCK frame_object.

"===================
" Called procedures
"===================
SELECTION-SCREEN BEGIN OF BLOCK frame_procedure WITH FRAME TITLE ft03.

  SELECTION-SCREEN BEGIN OF LINE.
    SELECTION-SCREEN COMMENT (28) txt_ptyp FOR FIELD so_ptype.
    SELECT-OPTIONS so_ptype FOR dummy_select_options_for-proctype.
  SELECTION-SCREEN END OF LINE.

  SELECTION-SCREEN BEGIN OF LINE.
    SELECTION-SCREEN COMMENT (28) txt_pnam FOR FIELD so_pname.
    SELECT-OPTIONS so_pname FOR dummy_select_options_for-procname.
  SELECTION-SCREEN END OF LINE.

  SELECTION-SCREEN BEGIN OF LINE.
    SELECTION-SCREEN COMMENT (28) txt_clas FOR FIELD so_class.
    SELECT-OPTIONS so_class FOR dummy_select_options_for-class.
  SELECTION-SCREEN END OF LINE.

SELECTION-SCREEN END OF BLOCK frame_procedure.

LOAD-OF-PROGRAM.
  CLASS lcl_controller DEFINITION DEFERRED.
  DATA controller TYPE REF TO lcl_controller.
  CREATE OBJECT controller TYPE ('LCL_CONTROLLER').

*--------------------------------------------------------------------*
* Initialization
*--------------------------------------------------------------------*
INITIALIZATION.
  CALL METHOD controller->('INITIALIZATION').

*--------------------------------------------------------------------*
* Start-of-Selection
*--------------------------------------------------------------------*
START-OF-SELECTION.
  CALL METHOD controller->('MAIN').

*--------------------------------------------------------------------*
* Class Defintions
*--------------------------------------------------------------------*
CLASS lcl_persistency_layer DEFINITION ##class_final.

  PUBLIC SECTION.

    TYPES: BEGIN OF g_typ_alv_output,
             " Calling object
             roottype   TYPE scmon_roottype, "scmon_vdata_view-roottype, "susg_sub-roottype,
             rootname   TYPE susg_sub-rootname,
             " Called object
             progname   TYPE susg_prog-progname,
             obj_type   TYPE susg_prog-obj_type,
             obj_name   TYPE susg_prog-obj_name,
             devclass   TYPE tadir-devclass,
             ddtext     TYPE char80,
             " Called procedure
             sub_type   TYPE susg_proc-sub_type,
             sub_name   TYPE susg_proc-sub_name,
             counter    TYPE susg_data-counter,
             last_used  TYPE susg_data-last_used,
             last_used2 TYPE /sapapo/opt_exp_start_date, " Timestamp TYPE P with conversion routine into Date
           END OF   g_typ_alv_output.

    TYPES: g_tt_alv_output TYPE STANDARD TABLE OF g_typ_alv_output WITH EMPTY KEY.

    METHODS derive_all_objects  RETURNING VALUE(result)   TYPE g_tt_alv_output.
    METHODS text_name           IMPORTING id_obj_type           TYPE tadir-object
                                          id_obj_name           TYPE tadir-obj_name
                                RETURNING VALUE(rd_description) TYPE char80.
    METHODS is_an_include       IMPORTING id_obj_name         TYPE tadir-obj_name
                                RETURNING VALUE(rf_yes_it_is) TYPE abap_bool.

ENDCLASS.

CLASS lcl_model DEFINITION  ##class_final.
  PUBLIC SECTION.
    DATA: mt_output            TYPE lcl_persistency_layer=>g_tt_alv_output,
          mo_persistency_layer TYPE REF TO lcl_persistency_layer.

    METHODS constructor.
    METHODS derive_data.

ENDCLASS.

CLASS lcl_view DEFINITION  ##class_final.
  PUBLIC SECTION.
    METHODS display IMPORTING it_output TYPE lcl_persistency_layer=>g_tt_alv_output.

ENDCLASS.

CLASS lcl_controller DEFINITION ##class_final.
  PUBLIC SECTION.
    METHODS initialization.
    METHODS main.
  PRIVATE SECTION.
    "! Sets frame titles
    METHODS set_frame_titles.
    METHODS set_field_texts.
ENDCLASS.

*--------------------------------------------------------------------*
* Class Implementations
*--------------------------------------------------------------------*
CLASS lcl_persistency_layer IMPLEMENTATION.

  METHOD derive_all_objects.

    SELECT FROM susg_admin
      INNER JOIN susg_data
        ON susg_data~usgid = susg_admin~usgid
      INNER JOIN susg_proc
        ON  susg_proc~usgid = susg_data~usgid
        AND susg_proc~trigid = susg_data~trigid
      INNER JOIN susg_prog
        ON  susg_prog~usgid = susg_proc~usgid
        AND susg_prog~progid = susg_proc~progid
      INNER JOIN susg_sub
        ON  susg_sub~usgid = susg_data~usgid
        AND susg_sub~subid = susg_data~subid
      INNER JOIN tadir
        ON  tadir~pgmid    = 'R3TR'
        AND tadir~object   = susg_prog~obj_type
        AND tadir~obj_name = susg_prog~obj_name
      LEFT OUTER JOIN trdirt
        ON  trdirt~name  = susg_prog~obj_name
        AND trdirt~sprsl = @sy-langu
        AND susg_prog~obj_type EQ 'PROG'
      LEFT OUTER JOIN tlibt
        ON  tlibt~spras EQ @sy-langu
        AND tlibt~area  EQ susg_prog~obj_name
        AND susg_prog~obj_type IN ('FUGR','FUGS')
      LEFT OUTER JOIN seoclasstx
        ON  seoclasstx~langu   EQ @sy-langu
        AND seoclasstx~clsname EQ susg_prog~obj_name
        AND susg_prog~obj_type EQ 'CLAS'
      FIELDS DISTINCT susg_sub~roottype, susg_sub~rootname,
                      susg_prog~progname, susg_prog~obj_type, susg_prog~obj_name,
                      concat( concat( coalesce( trdirt~text , ' ' ) , coalesce( tlibt~areat , ' ' ) ) , coalesce( seoclasstx~descript , ' ' ) ) AS ddtext,
                      susg_proc~sub_type, susg_proc~sub_name,
                      tadir~devclass,
                      susg_data~counter, susg_data~last_used AS last_used
      WHERE tadir~devclass     IN @s_devc
        AND susg_admin~usgid   IN @s_usgid
        AND susg_admin~kind    IN @s_kind
        AND susg_prog~progname IN @s_devc
        AND susg_prog~obj_type IN @so_otype
        AND susg_prog~obj_name IN @so_oname
        " Called procedures
        AND susg_proc~sub_type IN @so_ptype
        AND susg_proc~sub_name IN @so_pname
        AND susg_prog~obj_name IN @so_class
        AND susg_sub~roottype  IN @so_rtype
        AND susg_sub~rootname  IN @so_rname
      INTO CORRESPONDING FIELDS OF TABLE @result.

    IF sy-subrc NE 0.
      CLEAR result.
    ENDIF.

    LOOP AT result REFERENCE INTO DATA(line).
      CONVERT DATE line->last_used TIME '000000' INTO TIME STAMP line->last_used2 TIME ZONE '      '.
    ENDLOOP.

  ENDMETHOD.

  METHOD text_name.
  ENDMETHOD.

  METHOD is_an_include.

    SELECT SINGLE subc FROM trdir
        INTO  @DATA(program_type)
        WHERE name  = @id_obj_name.

    IF sy-subrc EQ 0 AND program_type = 'I'.
      rf_yes_it_is = abap_true.
    ENDIF.

  ENDMETHOD.

ENDCLASS.                    "lcl_persistency_layer

CLASS lcl_model IMPLEMENTATION.

  METHOD constructor.

    CREATE OBJECT mo_persistency_layer.

  ENDMETHOD.

  METHOD derive_data.

    mt_output[] = mo_persistency_layer->derive_all_objects( ).

  ENDMETHOD.

ENDCLASS.

CLASS lcl_view IMPLEMENTATION.

  METHOD display.
    DATA(output_table) = it_output."Need copy due to CHANGING parameter

    TRY.
        cl_salv_table=>factory(
          IMPORTING
            r_salv_table = DATA(lo_alv_grid)
          CHANGING
            t_table      = output_table ).
      CATCH cx_salv_msg INTO DATA(salv_error).
        DATA(error_message) = salv_error->get_text( ).
        MESSAGE error_message TYPE 'E'.
    ENDTRY.

    DATA(lo_columns) = lo_alv_grid->get_columns( ).
    lo_columns->set_optimize( if_salv_c_bool_sap=>true ).

    lo_alv_grid->get_functions( )->set_all( ).

    TRY.

        DATA(lo_column) = lo_columns->get_column( 'DDTEXT' ).
        lo_column->set_long_text( 'Object Description'(005) ).
        lo_column->set_short_text( 'Text Name'(004) ).

        lo_columns->get_column( 'LAST_USED' )->set_technical( if_salv_c_bool_sap=>true ).

        lo_alv_grid->get_sorts( )->add_sort( columnname = 'ROOTTYPE' position = 1 ).
        lo_alv_grid->get_sorts( )->add_sort( columnname = 'ROOTNAME' position = 2 ).
        lo_alv_grid->get_sorts( )->add_sort( columnname = 'PROGNAME' position = 3 ).
        lo_alv_grid->get_sorts( )->add_sort( columnname = 'OBJ_TYPE' position = 4 ).
        lo_alv_grid->get_sorts( )->add_sort( columnname = 'OBJ_NAME' position = 5 ).
        lo_alv_grid->get_sorts( )->add_sort( columnname = 'DEVCLASS' position = 6 subtotal = 'X' ).
        lo_alv_grid->get_sorts( )->add_sort( columnname = 'DDTEXT  ' position = 7 ).
        lo_alv_grid->get_sorts( )->add_sort( columnname = 'SUB_TYPE' position = 8 ).
        lo_alv_grid->get_sorts( )->add_sort( columnname = 'SUB_NAME' position = 9 ).

        lo_alv_grid->get_aggregations( )->add_aggregation(
            columnname  = 'COUNTER'
            aggregation = if_salv_c_aggregation=>total ).
        lo_alv_grid->get_aggregations( )->add_aggregation(
            columnname  = 'LAST_USED2'
            aggregation = if_salv_c_aggregation=>maximum ).

      CATCH cx_salv_error INTO DATA(error).
        MESSAGE error TYPE 'E'.
    ENDTRY.

    lo_alv_grid->display( ).

  ENDMETHOD.

ENDCLASS.


CLASS lcl_controller IMPLEMENTATION.

  METHOD initialization.

    set_field_texts( ).
    set_frame_titles( ).

  ENDMETHOD.


  METHOD main.

    DATA(lo_model) = NEW lcl_model( ).
    DATA(lo_view)  = NEW lcl_view( ).

    lo_model->derive_data( ).
    lo_view->display( lo_model->mt_output ).

  ENDMETHOD.


  METHOD set_frame_titles.

    ft99 = 'Selection Options'(f99).
    ft01 = 'Calling Request Entry Points'(f01).
    ft02 = 'Called Objects'(f02).
    ft03 = 'Called Procedures'(f03).

  ENDMETHOD.


  METHOD set_field_texts.

    txt_rtyp = 'Type'(rty).
    txt_rnam = 'Name'(rna).
    txt_otyp = 'Type'(oty).
    txt_onam = 'Name'(ona).
    txt_prog = 'Program'(pro).
    txt_ptyp = 'Type'(typ).
    txt_pnam = 'Name'(pna).
    txt_clas = 'Called Class Name'(cla).

  ENDMETHOD.

ENDCLASS.

Sandra_Rossi
Active Contributor
0 Kudos

An alternative is to use Solution Manager, SCMON (and/or UPL) data can be aggregated into SolMan infocubes, and there's one BW query to view the data.

Here is how the BW query looks like:

Source: the screenshot is taken from the page 75 of the guide named "Custom Code Management Navigate through your “Custom Code City”", subtitle "CCLM – Custom Code Lifecycle Management (based on SAP Solution Manager 7.2 SP12)"), chapter "PART II Now let's have a look at your "Custom Code City" > CCLM - How to work with the library > Main User Interface > Check Data Availability – Usage Logging".

This guide is obtained from SAP Solution Manager WIKI - Custom Code Management - Solution Manager - Support Wiki, there's a "Watch me" link in the section "CCLM 7.2 SP12+: Custom Code Management in Solution Manager 7.2 SP12 and higher":