Skip to content

Application Log (BAL_LOG_CREATE)

The standard three-FM pattern for structured, persistent logging — viewable in SLG1.

Purpose

The SAP application log (SLG1) stores structured messages with context (timestamp, user, program, object) independently of the program that created them. Use it instead of MESSAGE statements for background jobs, batch programs, and any code that must leave an audit trail.

The pattern uses three function modules in sequence:

  1. BAL_LOG_CREATE — open a log handle
  2. BAL_LOG_MSG_ADD / BAL_LOG_MSG_ADD_FREE_TEXT — add messages
  3. BAL_DB_SAVE — persist to database

Log objects

Log messages are grouped under a log object and sub-object (created in transaction SLGO). Always use a custom log object rather than SAP standard objects — it avoids polluting standard logs and allows targeted cleanup.

Signature

BAL_LOG_CREATE

Parameter Direction Description
I_S_LOG Importing BAL_S_LOG — object, subobject, external ID, program name
E_LOG_HANDLE Exporting Handle used in all subsequent calls

BAL_LOG_MSG_ADD_FREE_TEXT

Parameter Direction Description
I_LOG_HANDLE Importing Handle from BAL_LOG_CREATE
I_MSGTY Importing Message type: I/W/E/A/S
I_TEXT Importing Free text message

BAL_DB_SAVE

Parameter Direction Description
I_LOG_HANDLE Importing Handle to save

Complete example — background job with logging

REPORT z_batch_with_log.

DATA: lv_log_handle TYPE balloghndl,
      lv_ext_id     TYPE bal_s_log-extnumber.

START-OF-SELECTION.

  " 1 — Create log
  lv_ext_id = |Run { sy-datum } { sy-uzeit }|.

  CALL FUNCTION 'BAL_LOG_CREATE'
    EXPORTING
      i_s_log      = VALUE bal_s_log(
                       object    = 'ZMYOBJ'     " log object (SLGO)
                       subobject = 'ZBATCH'     " sub-object
                       extnumber = lv_ext_id    " external ID shown in SLG1
                       aldate    = sy-datum
                       altime    = sy-uzeit
                       aluser    = sy-uname
                       alprog    = sy-repid )
    IMPORTING
      e_log_handle = lv_log_handle.

  " 2a — Add free-text messages
  CALL FUNCTION 'BAL_LOG_MSG_ADD_FREE_TEXT'
    EXPORTING
      i_log_handle = lv_log_handle
      i_msgty      = 'I'
      i_text       = 'Processing started'.

  " 2b — Add structured T100 message (preferred for translatable text)
  CALL FUNCTION 'BAL_LOG_MSG_ADD'
    EXPORTING
      i_log_handle = lv_log_handle
      i_s_msg      = VALUE bal_s_msg(
                       msgty = 'W'
                       msgid = 'ZMY_CLASS'
                       msgno = '001'
                       msgv1 = lv_document_number ).

  " 2c — Add exception message directly
  TRY.
      " ... some risky operation ...
    CATCH cx_sy_open_sql_db INTO DATA(lx_db).
      CALL FUNCTION 'BAL_LOG_EXCEPTION'
        EXPORTING
          i_log_handle = lv_log_handle
          i_s_exc      = VALUE bal_s_exc( msgty = 'E' )
          i_exception  = lx_db.
  ENDTRY.

  " 3 — Save to database
  CALL FUNCTION 'BAL_DB_SAVE'
    EXPORTING
      i_log_handle = lv_log_handle
    EXCEPTIONS
      log_not_found = 1
      OTHERS        = 2.

  IF sy-subrc <> 0.
    MESSAGE 'Could not save application log' TYPE 'W'.
  ENDIF.

  MESSAGE 'Processing complete — see SLG1 for details' TYPE 'S'.

View logs in SLG1

  1. Run transaction SLG1.
  2. Enter your log object (ZMYOBJ) and sub-object (ZBATCH).
  3. Set a date range.
  4. Press Execute — all log entries with timestamps, users, and message types appear.

Common pitfalls

BAL_DB_SAVE must be called

If BAL_DB_SAVE is not called (e.g. the program ends early due to an error), the log exists only in memory and is lost. Call BAL_DB_SAVE in a CLEANUP block or early in the program flow.

Use I_IN_UPDATE_TASK for jobs with COMMIT WORK

If your program calls COMMIT WORK, log entries added before the commit are still persisted — BAL_DB_SAVE does its own commit internally. Pass I_IN_UPDATE_TASK = ABAP_TRUE to bundle the log save into the same LUW.

See also

Comments