This is a test message to test the length of the message box.
Login
ABAP Cloud Logging
Erstellt von Software-Heroes

ABAP Cloud - Logging

373

Lass uns in diesem Artikel einmal das Thema Logging anschauen und wie es unter ABAP Cloud funktioniert, dabei werden wir auf die Unterschiede und Gemeinsamkeiten eingehen.

Werbung


Logging von Meldungen und Fehlerzuständen ist in ABAP ein wichtiger Bestandteil in der Entwicklung, vor allem wenn die Verarbeitung im Hintergrund läuft und der User in die Protokolle schauen möchte. Dafür gibt es seit langer Zeit das Application Log im System. In diesem Artikel schauen wir uns die Gemeinsamkeiten und Unterschiede an, wenn es um die Entwicklung in ABAP Cloud geht.

 

Einleitung

ABAP Cloud ist das neue Entwicklungsmodell für Clean Core und Cloud Ready Anwendungen und verzichtet auf viele obsolete Dinge in der Programmiersprache ABAP. Das bedeutet für den Entwickler noch einmal viele Dinge neu zu lernen und sich an den freigegebenen APIs der SAP zu halten. In diesem Artikel schauen wir uns das Logging im System einmal näher an und wie es unter ABAP Cloud funktioniert. Möchtest du eine Entwicklung in TIER-1 erstellen, die ein Logging und Speichern von Nachrichten benötigt, dann werden die folgenden Abschnitte für dich wichtig werden.

 

Classic ABAP

Noch einmal zur Erinnerung wie es in der klassischen ABAP Entwicklung abläuft und was wir dort an Objekten verwenden. Grundsätzlich nutzt man die beiden Transaktionen SLG0 für die Konfiguration und SLG1, um das Log auszuwerten. Dabei wird die Konfiguration durch das System transportiert, um das Log auch in Test und Produktion zur Verfügung zu stellen.

Möchtest du Meldungen auch auf der Datenbank ablegen, benötigst du ein Objekt und Subobjekt fürs Logging. Im Anschluss erzeugst du dir mit BAL_LOG_CREATE ein Handle, welches du verwendest, um mit BAL_LOG_MSG_ADD Nachrichten zu übernehmen und am Ende mit BAL_DB_SAVE die Nachrichten auf die Datenbank zu schreiben. Bei den genannten Funktionen handelt es sich um die klassischen Funktionsbausteine.

 

Anlage

In den folgenden Unterabschnitten beschreiben wir die neue Anlage über ADT, aber auch den alten Weg über die ABAP API, wenn zum Beispiel noch das Release auf einem alten Stand ist und die passenden ADT APIs nicht verfügbar sind.

 

ABAP Development Tools

Die erste Neuerung ist die Anlage des Log Objekts im Editor, dafür brauchen wir die ABAP Development Tools. Und legen ein neues Objekt an. Dazu im Project Explorer auf das Paket gehen und über das Kontextmenü "New -> Other ABAP Repository Object" wählen. Dann können wir nach Log suchen, solltest du hier keinen Eintrag finden, kannst du mit dem Schritt "API" weitermachen.

 

Im nächsten Schritt musst du dem Objekt einen Namen und eine Beschreibung geben. Entsprechend im nächsten Schritt bestätigen und das neue Objekt einem Transportauftrag zuweisen.

 

Im letzten Schritt landen wir im Editor für das Application Log, hier kannst du über den "Add..." Button ein oder mehrere Unterobjekte für das Logging übernehmen.

 

In einer älteren Version war der Editor eine JSON Datei und nicht ganz so übersichtlich zu pflegen. Je nach Release könnte der Editor mal mehr oder weniger ähnlich aussehen.

 

API

Die Anlage über die API ist recht einfach und mit einem bzw. zwei Aufrufen machbar. Dazu benötigst du die Klasse CL_BALI_OBJECT_HANDLER um darüber eine Instanz zur erzeugen und die Klasse mit den nötigen Informationen zu versorgen. Das gleiche Objekt wie oben, erzeugt dieser Aufruf:

DATA(lo_ohandler) = cl_bali_object_handler=>get_instance( ).

lo_ohandler->create_object( iv_object            = 'ZBS_DEMO_LOG_OBJECT'
                            iv_object_text       = 'Demo Log Object'
                            it_subobjects        = VALUE #(
                                ( subobject = 'TEST' subobject_text = 'Subobject for Logging' ) )
                            iv_package           = 'ZBS_DEMO_LOGGING'
                            iv_transport_request = '<TRANSPORT_REQUEST>' ).

 

Hinweis: Ist weder die Anlage über ADT noch über die API möglich, hat dein System wahrscheinlich einen zu alten Stand. Du benötigst mindestens eine S/4 System dafür.

 

Logging

Möchtest du wissen welche Nachfolger es für die BAL Objekte gibt, dann kannst du dies über unseren Cloudification Repository Viewer machen, dort werden dir die passenden Nachfolger angezeigt.

 

Log erzeugen

Für die Arbeit mit dem Log benötigen wir die Klasse CL_BALI_LOG, um uns über die CREATE Methode eine Instanz zu erzeugen. Dazu einmal das folgende Beispiel:

" Create log object
DATA(lo_log) = cl_bali_log=>create( ).

" Create and set header
DATA(lo_header) = cl_bali_header_setter=>create( object      = 'ZBS_DEMO_LOG_OBJECT'
                                                 subobject   = 'TEST'
                                                 external_id = cl_system_uuid=>create_uuid_c32_static( )
)->set_expiry( expiry_date       = CONV d( cl_abap_context_info=>get_system_date( ) + 7 )
               keep_until_expiry = abap_true ).
lo_log->set_header( lo_header ).

 

Zuerst erzeugen wir uns eine Instanz des Logs, im Anschluss erzeugen wir einen Header mit der notwendigen Konfiguration (Objekt, Unterobjekt, Externe ID). Im Beispiel oben setzen wir das Ablaufdatum auf Heute und addieren eine Woche. Zum Abschluss übergeben wir den Header an die Log Instanz.

 

Nachricht übernehmen

Als nächsten Schritt wollen wir nun Nachrichten an die API übergeben. Dafür stehen verschiedene Objekte zur Verfügung:

  • CL_BALI_MESSAGE_SETTER - Übernahme von Nachrichten
  • CL_BALI_FREE_TEXT_SETTER - Übernahme von einfachen Texten
  • CL_BALI_EXCEPTION_SETTER - Übernahme von Ausnahmen

 

Im Beispiel findest du die verschiedenen Arten, wie Nachrichten an das Log übergeben werden können:

  1. Nachricht aus den Systemvariablen
  2. Freitext
  3. Ausnahme
  4. Klassische Nachricht
  5. BAPI Meldungen
" System message
MESSAGE s001(zbs_demo_log) INTO DATA(ld_message).
lo_log->add_item( cl_bali_message_setter=>create_from_sy( ) ).

" Free text
DATA(lo_free) = cl_bali_free_text_setter=>create( severity = if_bali_constants=>c_severity_warning
                                                  text     = 'Execution terminated, dataset not found' ).
lo_log->add_item( lo_free ).

" Exception
DATA(lo_exc) = cl_bali_exception_setter=>create( severity  = if_bali_constants=>c_severity_error
                                                 exception = NEW cx_sy_zerodivide( ) ).
lo_log->add_item( lo_exc ).

" Classic Message
DATA(lo_msg) = cl_bali_message_setter=>create(
    severity   = if_bali_constants=>c_severity_status
    id         = 'ZBS_DEMO_LOG'
    number     = '002'
    variable_1 = CONV #( cl_abap_context_info=>get_user_business_partner_id( ) ) ).
lo_log->add_item( lo_msg ).

" BAPIRET2
DATA(lo_bapi) = cl_bali_message_setter=>create_from_bapiret2( VALUE #( type       = 'E'
                                                                       id         = 'ZBS_DEMO_LOG'
                                                                       number     = '002'
                                                                       message_v1 = 'Dummy' ) )
lo_log->add_item( lo_bapi ).

 

Log speichern

Zum Abschluss muss das Log nur noch gespeichert werden, dazu benötigen wir die Schnittstelle zur Datenbank mit der Klasse CL_BALI_LOG_DB und übergeben unsere Log Instanz. Das Handle bekommen wir über die entsprechende Methode des Logs.

" Save logs
cl_bali_log_db=>get_instance( )->save_log( lo_log ).

" Get the handle
rd_result = lo_log->get_handle( ).

 

Nachrichten lesen

Um die Nachrichten aus dem Log zu lesen, können wir wieder die Datenbankschnittstelle verwenden. Dazu benötigen wir das Handle aus dem Prozess davor.

DATA(lo_log_db) = cl_bali_log_db=>get_instance( ).
DATA(lo_log) = lo_log_db->load_log( id_id ).
DATA(lt_items) = lo_log->get_all_items( ).

 

Zu guter Letzt geben wir die Texte in die Konsole aus, dazu der folgende Quellcode:

LOOP AT lt_items INTO DATA(ls_item).
  out->write( ls_item-item->get_message_text( ) ).
ENDLOOP.

 

Hinweis: Zum Lesen der Nachrichten aus dem Log, werden die passenden Berechtigungen über das Berechtigungsobjekt S_APPL_LOG benötigt. In ABAP Cloud sollte dies über eine IAM App geschehen. Diese dann an einen Business Catalog hängen, über die App "Maintain Business Roles" aufnehmen und zuweisen. 

 

Konstanten

Über das Interface IF_BALI_CONSTANTS stehen dir verschiedene Konstanten zur Verfügung, um die Klassifizierung der Nachrichten vorzunehmen. Unter C_SEVERITY_* findest du die verschiedenen Typen von Meldungen und kannst diese bei der Erstellung der Nachrichten verwenden.

 

ABAP Environment / Public Cloud

Wie sieht es eigentlich mit der generischen Auswertung der Logs im System aus? Hier werden wir leider etwas enttäuscht sein, da es im Moment keine Auswertung für Z-Logs, wie die Transaktion SLG1, gibt. Wir können die Logs speichern, können diese an Application Jobs hängen oder über die Standard API in unserer Fiori Anwendung auswerten. Vielleicht liefert SAP hier noch in Zukunft nach und erlaubt eine allgemeine Auswertung aller Application Logs im System, die Infrastruktur wäre da.

 

On-Premise / Private Cloud

Im klassischen System, wo wir auch Zugriff auf die SAP GUI haben, können wir noch über die klassische Transaktion SLG0 die Konfiguration unseres Logging Objekts einsehen. Die Besonderheit ist hier, dass das Objekt nur auf Anzeige steht und die eigentlichen Änderungen über ADT gemacht werden müssen:

 

Genau so können wir über das Application Log (Transaktion SLG1) auswerten und uns die erzeugten Meldungen ansehen. Die Funktionalität im Hintergrund ist also gleichgeblieben:

 

Vollständiges Beispiel

Zum Abschluss noch einmal das vollständige Coding aus dem heutigen Artikel zur Anlage und zum Lesen der Nachrichten aus dem Application Log:

CLASS zcl_bs_demo_handle_messages DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.

  PRIVATE SECTION.
    METHODS create_log_entries
      RETURNING VALUE(rd_result) TYPE if_bali_log=>ty_handle
      RAISING   cx_static_check.

    METHODS read_log_entries
      IMPORTING id_id            TYPE if_bali_log=>ty_handle
      RETURNING VALUE(rt_result) TYPE if_bali_log=>ty_item_table
      RAISING   cx_static_check.
ENDCLASS.


CLASS zcl_bs_demo_handle_messages IMPLEMENTATION.
  METHOD if_oo_adt_classrun~main.
    TRY.
        " Log messages and get handle
        DATA(ld_id) = create_log_entries( ).
        out->write( |Log created: { ld_id }| ).

        " Read messages from handle
        DATA(lt_items) = read_log_entries( ld_id ).
        LOOP AT lt_items INTO DATA(ls_item).
          out->write( ls_item-item->get_message_text( ) ).
        ENDLOOP.

      CATCH cx_root INTO DATA(lo_err).
        out->write( lo_err->get_longtext( ) ).
    ENDTRY.
  ENDMETHOD.


  METHOD create_log_entries.
    " Create log object
    DATA(lo_log) = cl_bali_log=>create( ).

    " Create and set header
    DATA(lo_header) = cl_bali_header_setter=>create( object      = 'ZBS_DEMO_LOG_OBJECT'
                                                     subobject   = 'TEST'
                                                     external_id = cl_system_uuid=>create_uuid_c32_static( )
    )->set_expiry( expiry_date       = CONV d( cl_abap_context_info=>get_system_date( ) + 7 )
                   keep_until_expiry = abap_true ).
    lo_log->set_header( lo_header ).

    " System message
    MESSAGE s001(zbs_demo_log) INTO DATA(ld_message).
    lo_log->add_item( cl_bali_message_setter=>create_from_sy( ) ).

    " Free text
    DATA(lo_free) = cl_bali_free_text_setter=>create( severity = if_bali_constants=>c_severity_warning
                                                      text     = 'Execution terminated, dataset not found' ).
    lo_log->add_item( lo_free ).

    " Exception
    DATA(lo_exc) = cl_bali_exception_setter=>create( severity  = if_bali_constants=>c_severity_error
                                                     exception = NEW cx_sy_zerodivide( ) ).
    lo_log->add_item( lo_exc ).

    " Classic Message
    DATA(lo_msg) = cl_bali_message_setter=>create(
        severity   = if_bali_constants=>c_severity_status
        id         = 'ZBS_DEMO_LOG'
        number     = '002'
        variable_1 = CONV #( cl_abap_context_info=>get_user_business_partner_id( ) ) ).
    lo_log->add_item( lo_msg ).

    " BAPIRET2
    DATA(lo_bapi) = cl_bali_message_setter=>create_from_bapiret2( VALUE #( type       = 'E'
                                                                           id         = 'ZBS_DEMO_LOG'
                                                                           number     = '002'
                                                                           message_v1 = 'Dummy' ) ).
    lo_log->add_item( lo_bapi ).

    " Save logs
    cl_bali_log_db=>get_instance( )->save_log( lo_log ).

    " Get the handle
    rd_result = lo_log->get_handle( ).
  ENDMETHOD.


  METHOD read_log_entries.
    DATA(lo_log_db) = cl_bali_log_db=>get_instance( ).

    DATA(lo_log) = lo_log_db->load_log( id_id ).

    rt_result = lo_log->get_all_items( ).
  ENDMETHOD.
ENDCLASS.

 

Fazit

Logging in ABAP Cloud baut auf den gleichen Objekten und Techniken auf, gibt dem Ganzen aber in Form der Klassen ein modernes Gewand. Wenn es um die Auswertung der Nachrichten geht, sollte die Cloud noch etwas an Funktionalität zulegen, um die gleichen Möglichkeiten wie On-Premise zu ermöglichen.


Enthaltene Themen:
ABAP CloudABAPApplication LogLog
Kommentare (0)



Und weiter ...

Bist du zufrieden mit dem Inhalt des Artikels? Wir posten jeden Freitag neuen Content im Bereich ABAP und unregelmäßig in allen anderen Bereichen. Schaue bei unseren Tools und Apps vorbei, diese stellen wir kostenlos zur Verfügung.


ABAP Cloud - Clean Core (Szenarien)

Kategorie - ABAP

Lass uns in diesem Artikel noch einmal die Clean Core Architektur mit ABAP Cloud anschauen, wo diese eingesetzt wird und wo du deine Anwendungen bauen kannst.

10.01.2025

ABAP Cloud - Programmiermodell

Kategorie - ABAP

Welches Programmiermodell kommt mit ABAP Cloud zum Einsatz und was können wir aus dem Vorgänger lernen? Mehr Details im Artikel.

03.01.2025

ABAP Cloud - ADT Bäume (Übersicht)

Kategorie - ABAP

Welchen Hilfen und Übersichten stehen dir in den ABAP Development Tools zur Verfügung, um dein Leben mit ABAP Cloud zu vereinfachen?

17.12.2024

ABAP Cloud - Relevante Objekte

Kategorie - ABAP

Welche Objekte sind in der ABAP Entwicklung eigentlich noch relevant und welche kannst du so langsam in die Mottenkiste packen? Hier erfährst du mehr.

19.11.2024

ABAP Cloud - Sperren

Kategorie - ABAP

Für was musst du Sperren setzen und wie kannst du das leicht in ABAP Cloud machen? In diesem Artikel schauen wir uns den Prozess im Detail an.

08.11.2024