Variante 1 (cf_reca_message_list)
* Kapselt im Paket RE_CA_BC die FuBas der Funktionsgruppe SBAL (Paket SZAL)
* BAL-Message-Collector Objekt anlegen
* id_object: BAL-Objekttyp (SLG0, SLG1)
* id_subobject: BAL-Unterobjekttyp (SLG0, SLG1)
* id_extnumber: Freitext für spätere Suche in der SLG1, i.d.R. Belegnummern
* id_deldate: Verfallsdatum der Lognachricht (i.d.R. 30 Tage)
DATA(o_msg_list) = cf_reca_message_list=>create( id_object = 'Z_TEST_LOG'
id_subobject = 'Z_TEST_LOG_U1'
id_extnumber = 'Identifier_01234'
id_deldate = CONV #( sy-datum + 30 ) ).
* Log-Eintrag dem Message-Objekt hinzufügen
o_msg_list->add( EXPORTING id_msgty = 'I'
id_msgid = 'OO'
id_msgno = '000'
id_msgv1 = 'Text1'
id_msgv2 = 'Text2'
id_msgv3 = ''
id_msgv4 = '' ).
TRY.
* Division durch Null provozieren
DATA(lv_div) = 1 / 0.
CATCH cx_root INTO DATA(e_txt).
* Log-Eintrag dem Message-Objekt hinzufügen
o_msg_list->add_from_exception( e_txt ).
ENDTRY.
* Message-Liste im BAL speichern
o_msg_list->store( ).
* Protokoll als Applikation bzw. Popup anzeigen
CALL FUNCTION 'RECA_GUI_MSGLIST_POPUP'
EXPORTING
io_msglist = o_msg_list.
Variante 2 (BAL_LOG_CREATE)
* Paket: SZAL
* Demo: SBAL_DEMO_*
* Vorteil: vollständige Parametrierung über bal_s_log (Externe Identifikation, Verfallsdatum...)
* Link: https://wiki.scn.sap.com/wiki/display/Snippets/Using+Application+Log
CLASS lcl_applog DEFINITION.
PUBLIC SECTION.
TYPES:
BEGIN OF ty_s_msgtext,
msgv1 TYPE symsgv,
msgv2 TYPE symsgv,
msgv3 TYPE symsgv,
msgv4 TYPE symsgv,
END OF ty_s_msgtext .
* Message-Typen
CONSTANTS: co_msg_type_error TYPE symsgty VALUE 'E'.
CONSTANTS: co_msg_type_warning TYPE symsgty VALUE 'W'.
CONSTANTS: co_msg_type_info TYPE symsgty VALUE 'I'.
* Problemklassen (Domäne BALPROBCL)
* 1 sehr wichtig
* 2 wichtig
* 3 mittel
* 4 Zusatzinformationen
* Sonstiges
CONSTANTS: co_problem_class_high TYPE balprobcl VALUE '1'.
CONSTANTS: co_problem_class_medium TYPE balprobcl VALUE '2'.
CONSTANTS: co_problem_class_low TYPE balprobcl VALUE '3'.
CONSTANTS: co_problem_class_info TYPE balprobcl VALUE '4'.
CONSTANTS: co_problem_class_other TYPE balprobcl VALUE ' '.
CLASS-METHODS:
create
IMPORTING
i_bal_s_log TYPE bal_s_log
RETURNING VALUE(rv_ok) TYPE abap_bool.
CLASS-METHODS:
add_message
IMPORTING
i_probclass TYPE balprobcl DEFAULT co_problem_class_info
i_msgtype TYPE symsgty DEFAULT co_msg_type_error
i_msgid TYPE symsgid DEFAULT '01' " Verwendung der generische Nachrichtenklasse mit & & & &
i_msgno TYPE symsgno DEFAULT '319' " Verwendung der generische Nachrichtenklasse mit & & & &
i_msgv1 TYPE symsgv OPTIONAL
i_msgv2 TYPE symsgv OPTIONAL
i_msgv3 TYPE symsgv OPTIONAL
i_msgv4 TYPE symsgv OPTIONAL
RETURNING VALUE(rv_ok) TYPE abap_bool.
CLASS-METHODS:
add_string
IMPORTING
i_probclass TYPE balprobcl DEFAULT co_problem_class_info
i_msgtype TYPE symsgty DEFAULT co_msg_type_error
i_msgid TYPE symsgid DEFAULT '01' " Verwendung der generische Nachrichtenklasse mit & & & &
i_msgno TYPE symsgno DEFAULT '319' " Verwendung der generische Nachrichtenklasse mit & & & &
i_msg_text TYPE string
RETURNING VALUE(rv_ok) TYPE abap_bool.
CLASS-METHODS:
add_exception
IMPORTING
i_probclass TYPE balprobcl DEFAULT co_problem_class_info
i_msgtype TYPE symsgty DEFAULT co_msg_type_error
i_exception TYPE REF TO cx_root
RETURNING VALUE(rv_ok) TYPE abap_bool.
CLASS-METHODS:
save
RETURNING VALUE(rv_ok) TYPE abap_bool.
CLASS-METHODS:
delete
RETURNING VALUE(rv_ok) TYPE abap_bool.
CLASS-METHODS:
display_current
IMPORTING
i_title TYPE baltitle OPTIONAL
i_it_balnri TYPE ehsky_balnri.
CLASS-METHODS:
display
IMPORTING
iv_object TYPE balhdr-object DEFAULT space
iv_subobject TYPE balhdr-subobject DEFAULT space
iv_external_number TYPE balhdr-extnumber DEFAULT space
iv_object_attribute TYPE i DEFAULT 0
iv_subobject_attribute TYPE i DEFAULT 0
iv_external_number_attribute TYPE i DEFAULT 0
iv_date_from TYPE balhdr-aldate DEFAULT sy-datum
iv_time_from TYPE balhdr-altime DEFAULT '000000'
iv_date_to TYPE balhdr-aldate DEFAULT sy-datum
iv_time_to TYPE balhdr-altime DEFAULT sy-uzeit
iv_suppress_selection_dialog TYPE abap_bool DEFAULT abap_false
iv_title_selection_screen TYPE char255 DEFAULT space
iv_title_list_screen TYPE char255 DEFAULT space.
CLASS-METHODS:
has_data
RETURNING VALUE(rv_has) TYPE abap_bool.
PRIVATE SECTION.
CLASS-DATA:
gv_log_handle TYPE balloghndl.
ENDCLASS.
CLASS lcl_applog IMPLEMENTATION.
* Log erzeugen und Log-Handle ermitteln
METHOD create.
rv_ok = abap_false.
CALL FUNCTION 'BAL_LOG_CREATE'
EXPORTING
i_s_log = i_bal_s_log
IMPORTING
e_log_handle = gv_log_handle
EXCEPTIONS
log_header_inconsistent = 1
OTHERS = 2.
IF sy-subrc = 0.
rv_ok = abap_true.
ENDIF.
ENDMETHOD.
* Log-Message hinzufügen
* Achtung: Die Stringlänge für die Parameter i_msgv1, i_msgv2, i_msgv3 und i_msgv4 ist jeweils max. 50 Zeichen!
METHOD add_message.
rv_ok = abap_false.
DATA(lv_msg) = VALUE bal_s_msg( probclass = i_probclass
msgty = i_msgtype
msgid = i_msgid
msgno = i_msgno
msgv1 = i_msgv1
msgv2 = i_msgv2
msgv3 = i_msgv3
msgv4 = i_msgv4 ).
CALL FUNCTION 'BAL_LOG_MSG_ADD'
EXPORTING
i_log_handle = gv_log_handle
i_s_msg = lv_msg
EXCEPTIONS
log_not_found = 1
msg_inconsistent = 2
log_is_full = 3
OTHERS = 4.
IF sy-subrc = 0.
rv_ok = abap_true.
ENDIF.
ENDMETHOD.
METHOD add_string.
rv_ok = abap_false.
* String (max. 200 Zeichen) -> TY_S_MSGTEXT (msgv1 ... msgv4) (max. 4 x 50 Zeichen) wandeln
DATA(lv_msg_text) = CONV ty_s_msgtext( i_msg_text ).
DATA(lv_msg) = VALUE bal_s_msg( probclass = i_probclass
msgty = i_msgtype
msgid = i_msgid
msgno = i_msgno
msgv1 = lv_msg_text-msgv1
msgv2 = lv_msg_text-msgv2
msgv3 = lv_msg_text-msgv3
msgv4 = lv_msg_text-msgv4 ).
* altenativ: Verwendung von FuBa BAL_LOG_MSG_ADD_FREE_TEXT
CALL FUNCTION 'BAL_LOG_MSG_ADD'
EXPORTING
i_log_handle = gv_log_handle
i_s_msg = lv_msg
EXCEPTIONS
log_not_found = 1
msg_inconsistent = 2
log_is_full = 3
OTHERS = 4.
IF sy-subrc = 0.
rv_ok = abap_true.
ENDIF.
ENDMETHOD.
* Log-Message anhand einer Exception hinzufügen
METHOD add_exception.
rv_ok = abap_false.
DATA(lv_ex) = VALUE bal_s_exc( probclass = i_probclass
msgty = i_msgtype
exception = i_exception ).
CALL FUNCTION 'BAL_LOG_EXCEPTION_ADD'
EXPORTING
i_log_handle = gv_log_handle
i_s_exc = lv_ex
EXCEPTIONS
log_not_found = 1
msg_inconsistent = 2
log_is_full = 3
OTHERS = 4.
IF sy-subrc = 0.
rv_ok = abap_true.
ENDIF.
ENDMETHOD.
* akt. Log auf der Datenbank speichern
METHOD save.
rv_ok = abap_false.
DATA: it_log_handle TYPE bal_t_logh.
APPEND gv_log_handle TO it_log_handle.
* alternativ: Verwendung von FuBa APPL_LOG_WRITE_DB
CALL FUNCTION 'BAL_DB_SAVE'
EXPORTING
i_t_log_handle = it_log_handle
EXCEPTIONS
log_not_found = 1
save_not_allowed = 2
numbering_error = 3
OTHERS = 4.
IF sy-subrc = 0.
rv_ok = abap_true.
ENDIF.
ENDMETHOD.
* Log-Messages löschen
METHOD delete.
rv_ok = abap_false.
CALL FUNCTION 'BAL_LOG_MSG_DELETE_ALL'
EXPORTING
i_log_handle = gv_log_handle
EXCEPTIONS
log_not_found = 1
OTHERS = 2.
IF sy-subrc = 0.
rv_ok = abap_true.
ENDIF.
ENDMETHOD.
* akt. Log anhand Lognumber anzeigen
METHOD display_current.
IF sy-batch IS INITIAL.
DATA: lv_bal_s_prof TYPE bal_s_prof.
CALL FUNCTION 'BAL_DSP_PROFILE_STANDARD_GET'
IMPORTING
e_s_display_profile = lv_bal_s_prof
EXCEPTIONS
OTHERS = 1.
lv_bal_s_prof-show_all = abap_true.
lv_bal_s_prof-cwidth_opt = abap_true.
DATA(it_lognumbers) = VALUE szal_lognumbers( FOR <l> IN i_it_balnri
(
item = <l>-lognumber
)
).
CALL FUNCTION 'APPL_LOG_DISPLAY_WITH_LOGNO'
EXPORTING
title_list_screen = i_title
i_s_display_profile = lv_bal_s_prof
TABLES
lognumbers = it_lognumbers
EXCEPTIONS
no_authority = 1
OTHERS = 2.
ENDIF.
ENDMETHOD.
* SLG1 aufrufen: gesamtes Appl. Log anhand von Suchkriterien anzeigen
METHOD display.
CALL FUNCTION 'APPL_LOG_DISPLAY'
EXPORTING
object = iv_object
subobject = iv_subobject
external_number = iv_external_number
object_attribute = iv_object_attribute
subobject_attribute = iv_subobject_attribute
external_number_attribute = iv_external_number_attribute
date_from = iv_date_from
time_from = iv_time_from
date_to = iv_date_to
time_to = iv_time_to
title_selection_screen = iv_title_selection_screen
title_list_screen = iv_title_list_screen
* COLUMN_SELECTION = '11112221122 '
suppress_selection_dialog = iv_suppress_selection_dialog
* COLUMN_SELECTION_MSG_JUMP = '1'
* EXTERNAL_NUMBER_DISPLAY_LENGTH = 20
* I_S_DISPLAY_PROFILE =
* I_VARIANT_REPORT = ' '
* I_SRT_BY_TIMSTMP = ' '
* IMPORTING
* NUMBER_OF_PROTOCOLS =
EXCEPTIONS
no_authority = 1
OTHERS = 2.
ENDMETHOD.
* sind für das akt. Log Daten verfügbar
METHOD has_data.
rv_has = abap_false.
DATA: lv_statistics TYPE bal_s_scnt.
CALL FUNCTION 'BAL_LOG_HDR_READ'
EXPORTING
i_log_handle = gv_log_handle
IMPORTING
e_statistics = lv_statistics
EXCEPTIONS
log_not_found = 1
OTHERS = 2.
IF sy-subrc = 0.
CLEAR: lv_statistics-msg_max_pc.
IF NOT lv_statistics IS INITIAL.
rv_has = abap_true.
ENDIF.
ENDIF.
ENDMETHOD.
ENDCLASS.
**********************************************************************
*
* PARAMETERS
*
**********************************************************************
PARAMETERS: p_show AS CHECKBOX DEFAULT abap_false.
**********************************************************************
*
* START-OF-SELECTION
*
**********************************************************************
START-OF-SELECTION.
IF abap_false = p_show.
* Log-Objekte und Subobjekte definieren -> Transaktion SLG0 --> es werden Transportaufträge generiert
* extnumber: Freitext für spätere Suche in der SLG1, i.d.R. Belegnummern
* aldate_del: Verfallsdatum der Lognachricht (i.d.R. 30 Tage)
DATA(lv_bal_log) = VALUE bal_s_log( object = 'Z_TEST_LOG'
subobject = 'Z_TEST_LOG_U1'
extnumber = 'Identifier_01234'
aldate_del = sy-datum + 30
).
* Legt eine Protokoll-Instanz an
* Log-Objekte werden in der Transaktion SLG0 definiert -> es werden Transportaufträge generiert
* Anlegen der Objekte erfolgt in den Tabellen
* BALOBJ (Anwendungs-Log: Objekte)
* BALSUB (Anwendungs-Log: Unterobjekte)
IF abap_true = lcl_applog=>create( i_bal_s_log = lv_bal_log ).
* Protokolleinträge hinzufügen -> Nachrichten werden in der Transaktion SE91 gefplegt
* Beispiel: Verwendung der vordefinierten Nachrichtenklasse 'S_AUT', Nr. '128'
lcl_applog=>add_message( i_probclass = lcl_applog=>co_problem_class_info
i_msgtype = lcl_applog=>co_msg_type_info
i_msgid = 'S_AUT'
i_msgno = '128' ).
* Beispiel: Verwendung der generische Nachrichtenklasse mit & & & & für die Parameter msgv1 - msgv4
lcl_applog=>add_message( i_probclass = lcl_applog=>co_problem_class_info
i_msgtype = lcl_applog=>co_msg_type_warning
i_msgv1 = 'Test1'
i_msgv2 = 'Test2'
i_msgv3 = 'Test3'
i_msgv4 = 'Test4' ).
* Beispiel: Verwendung der generische Nachrichtenklasse mit & & & &
lcl_applog=>add_string( i_probclass = lcl_applog=>co_problem_class_medium
i_msgtype = lcl_applog=>co_msg_type_error
i_msg_text = 'Testeintrag' ).
TRY.
* Ausnahme auslösen
DATA(result) = 1 / 0.
CATCH cx_root INTO DATA(e_txt).
* Fügt eine Ausnahme hinzu, wobei
* i_probclass: 1 - sehr wichtig
* 2 - wichtig
* 3 - mittel
* 4 - Zusatzinformationen
lcl_applog=>add_exception( i_probclass = lcl_applog=>co_problem_class_high
i_msgtype = lcl_applog=>co_msg_type_error
i_exception = e_txt ).
ENDTRY.
* Schließt und persistiert (speichert) das Protokoll
* Protokoll kann auch in der Transaktion SLG1 angeschaut werden
* Speicherung der Log-Daten erfolgt in den Tabellen
* BALHDR (Anwendungs-Log: Protokollkopf)
* BALDAT (Anwendungs-Log: Daten eines Protokolls)
DATA: it_balnri TYPE ehsky_balnri.
* Log speichern
IF abap_true = lcl_applog=>save( ).
* Beispiel: Verwendung der generische Nachrichtenklasse mit & & & &
lcl_applog=>add_string( i_probclass = lcl_applog=>co_problem_class_other
i_msgtype = lcl_applog=>co_msg_type_warning
i_msg_text = 'Testeintrag warning' ).
* Log speichern
IF abap_true = lcl_applog=>save( ).
* Existieren Meldungen?
IF abap_true = lcl_applog=>has_data( ).
* Protokoll anzeigen
lcl_applog=>display_current( i_title = 'Application-Log'
i_it_balnri = it_balnri ).
ELSE.
WRITE: / 'Keine Statistik verfügbar.'.
ENDIF.
ELSE.
WRITE: / 'Fehler beim Speichern des Logs.'.
ENDIF.
ELSE.
WRITE: / 'Fehler beim Speichern des Logs.'.
ENDIF.
ELSE.
WRITE: / 'Fehler beim Erzeugen des Logs.'.
ENDIF.
ELSE.
* SLG1 aufrufen
lcl_applog=>display( iv_object = 'Z_TEST_LOG'
iv_subobject = 'Z_TEST_LOG_U1' ).
ENDIF.