Application Logging in ABAP

Whether you are working with integration or a critical application or a complex report, logging becomes an obvious choice and activity. 
Traditionally, Abapers have been logging information using a custom DB table defined specifically for a particular application.
While useful, The approach has some flaws,
    - Every application needs to have its own logging table
    - Record purging/archiving needs to be set up in order to make sure old records are either deleted 
      or archived.
    - There is no reusability of either the setup or the logic to log.

With the introduction of Application Logging from SAP, the traditional approach can be left out. 
In this post, I will be talking about how we can leverage the SAP application Logging Library to make logging easy.

What is an application log?

An application log is a rich type log. It contains information like User, Time, Expiry date of the log along with the actual message raised by the application. You can categorise between success, error, and warning or provide extra information in a form of a structure of no more than 255 characters. Each application log is tied to an application object/subobject which defines the application activity/subactivity.

There are three main tcodes to Application Logging:
1. SLG0: - Defining the object/subobject.
2. SLG1: - Viewing the logs
3. SLG2: - Deleting the logs.

Let's start with defining an Object.

Creating ABAP application Log object in SLG0

Click on New Entries and Add a new Object:

Creating ABAP application Log object in SLG0

Add a sub-object(Optional):

Creating ABAP application Log sub object in SLG0


Now our application code needs to start logging in to this new object and subobject.

Starting the log:
You open the log Using Function Module BAL_LOG_CREATE. You can pass the log header data to this function module in the importing parameter I_S_LOG_HEADER with the structure BAL_S_LOG. 

The function module returns the log handle which is a GUID and identifies a log uniquely. This log handle can be used either to change the log header data later or to put messages in the log.
Simple Example:
DATA:
s_log TYPE bal_s_log.
s_log-object = 'Z_BAL_TST'.
s_log-subobject = 'TEST_SOBJ'.
s_log-aldate = syst-datum.
s_log-altime = syst-uzeit.
s_log-aluser = syst-uname.
CALL FUNCTION 'BAL_LOG_CREATE'
EXPORTING
i_s_log = s_log
IMPORTING
e_log_handle = v_log_handle
EXCEPTIONS
log_header_inconsistent = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE e000(db) with 'Error Initiating Log'.
ENDIF.

Adding Messages to Logs:

You can add messages to your newly created log header identified by its handle.
The message data is provided in the function module BAL_LOG_MSG_ADD by the importing parameter I_S_MSG (structure BAL_S_MSG). This data is mostly the T100 information (message type, work area, message number, the 4 message variables). You can also pass other information, e.g. application-specific data (context), parameters for a long text and a callback routine. Simple Example:
DATA:
v_log_handle TYPE bal_s_log,
s_msg TYPE bal_s_msg.
" Information
s_msg-msgty = 'I'."<- Information
s_msg-msgid = 'DB'.
s_msg-msgno = '000'.
s_msg-msgv1 = 'Fetching 100 records from table'.
CALL FUNCTION 'BAL_LOG_MSG_ADD'
EXPORTING
i_log_handle = v_log_handle
i_s_msg = s_msg
EXCEPTIONS
log_not_found = 1
msg_inconsistent = 2
log_is_full = 3
OTHERS = 4.
IF sy-subrc <> 0.
MESSAGE e000(db) with 'Error while adding message to Log'.
ENDIF.

Saving the Log to DB.
You can save the log to the database using the function module: BAL_DB_SAVE  by providing the log handle.
Example:
DATA:
t_log_handle TYPE bal_t_logh.
INSERT v_log_handle INTO t_log_handle INDEX 1.
CALL FUNCTION 'BAL_DB_SAVE'
EXPORTING
i_client = syst-mandt
i_save_all = ' '
i_t_log_handle = t_log_handle
IMPORTING
e_new_lognumbers = t_log_num
EXCEPTIONS
log_not_found = 1
save_not_allowed = 2
numbering_error = 3
OTHERS = 4.
IF sy-subrc <> 0.
MESSAGE e000(db) with 'Error while Saving Log to DB'.
ELSE.
MESSAGE s000(db) with 'Log Generated'.
ENDIF.

Viewing the Log:
You can view the log in SLG1 Tcode.
Input screen:
Viewing logs in SLG1 input screen

Here is the Output:
Viewing logs in SLG1 output screen

Below is the code snippet that generated the above log with all three components explained earlier.
REPORT sy-repid.
DATA:
s_log TYPE bal_s_log,
s_msg TYPE bal_s_msg,
s_lognum TYPE bal_s_lgnm.
DATA:
v_log_handle TYPE balloghndl,
v_vbeln TYPE vbeln_va.
DATA:
t_log_handle TYPE bal_t_logh,
t_log_num TYPE bal_t_lgnm,
t_msg TYPE STANDARD TABLE OF bal_s_msg,
t_vbap TYPE STANDARD TABLE OF vbap.
DATA:
o_salv TYPE REF TO cl_salv_table.
SELECT-OPTIONS:
s_vbeln FOR v_vbeln.
INITIALIZATION.
* Create the Log
s_log-object = 'Z_BAL_TST'.
s_log-subobject = 'TEST_SOBJ'.
s_log-aldate = syst-datum.
s_log-altime = syst-uzeit.
s_log-aluser = syst-uname.
CALL FUNCTION 'BAL_LOG_CREATE'
EXPORTING
i_s_log = s_log
IMPORTING
e_log_handle = v_log_handle
EXCEPTIONS
log_header_inconsistent = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE s000(db) WITH 'Error Initiating Log' DISPLAY LIKE 'E'.
ENDIF.
START-OF-SELECTION.
CLEAR s_msg.
s_msg-msgty = 'I'.
s_msg-msgid = 'DB'.
s_msg-msgno = '000'.
s_msg-msgv1 = 'Fetching first 100 records from VBAp'.
APPEND s_msg TO t_msg.
SELECT *
FROM vbap
INTO TABLE t_vbap
UP TO 100 ROWS
WHERE vbeln IN s_vbeln.
IF syst-subrc <> 0.
CLEAR s_msg.
s_msg-msgty = 'E'.
s_msg-msgid = 'DB'.
s_msg-msgno = '000'.
s_msg-msgv1 = 'No Data found for Input'.
s_msg-msgv2 = s_vbeln-low.
s_msg-msgv3 = s_vbeln-high.
CALL FUNCTION 'BAL_LOG_MSG_ADD'
EXPORTING
i_log_handle = v_log_handle
i_s_msg = s_msg
EXCEPTIONS
log_not_found = 1
msg_inconsistent = 2
log_is_full = 3
OTHERS = 4.
IF sy-subrc <> 0.
MESSAGE e000(db) WITH 'Error while adding message to Log'.
ENDIF.
RETURN.
ELSE.
CLEAR s_msg.
s_msg-msgty = 'W'.
s_msg-msgid = 'DB'.
s_msg-msgno = '000'.
s_msg-msgv1 = '100 records Data found'.
s_msg-msgv2 = 'There could be more'.
APPEND s_msg TO t_msg.
ENDIF.
CLEAR s_msg.
s_msg-msgty = 'I'.
s_msg-msgid = 'DB'.
s_msg-msgno = '000'.
s_msg-msgv1 = 'Starting Display'.
s_msg-msgv2 = v_vbeln.
APPEND s_msg TO t_msg.
LOOP AT t_msg INTO s_msg.
CALL FUNCTION 'BAL_LOG_MSG_ADD'
EXPORTING
i_log_handle = v_log_handle
i_s_msg = s_msg
EXCEPTIONS
log_not_found = 1
msg_inconsistent = 2
log_is_full = 3
OTHERS = 4.
IF sy-subrc <> 0.
MESSAGE e000(db) WITH 'Error while adding message to Log' syst-subrc.
ENDIF.
ENDLOOP.
"Display
cl_salv_table=>factory( IMPORTING r_salv_table = o_salv " Basis Class Simple ALV Tables
CHANGING t_table = t_vbap
).
o_salv->display( ).
INSERT v_log_handle INTO t_log_handle INDEX 1.
CALL FUNCTION 'BAL_DB_SAVE'
EXPORTING
i_client = sy-mandt
i_save_all = ' '
i_t_log_handle = t_log_handle
IMPORTING
e_new_lognumbers = t_log_num
EXCEPTIONS
log_not_found = 1
save_not_allowed = 2
numbering_error = 3
OTHERS = 4.
IF sy-subrc <> 0.
MESSAGE e000(db) WITH 'Error while Saving Log to DB' .
ELSE.
MESSAGE s000(db) WITH 'Log Generated' .
ENDIF.
view raw bal_log_ex.abap hosted with ❤ by GitHub

As always, Hope you like the post and use the information in your day to day work.

Popular posts from this blog

ABAP convert internal table to excel (.xlsx) format and Send email or download

ABAP read excel(.XLSX) file to internal table in ABAP using CL_FDT_XL_SPREADSHEET

Use CL_BCS library to send email with ABAP