El Application Log (BAL) es el framework estándar para registro persistente en SAP. Los logs se almacenan en la base de datos y pueden visualizarse mediante la transacción SLG1.
Concepto básico
| Elemento | Descripción |
|---|---|
| Log Object | Agrupación (p.ej. aplicación) - mantener en SLG0 |
| Sub-Object | Subcategoría del Log Object |
| Log Handle | ID único de una instancia de log |
| Message | Mensaje individual del protocolo |
| SLG1 | Transacción para visualización de logs |
Tipos de mensaje
| Tipo | Significado | Icono |
|---|---|---|
| A | Aborto | Rojo |
| E | Error | Rojo |
| W | Advertencia | Amarillo |
| I | Información | Azul |
| S | Éxito | Verde |
Ejemplos
1. Crear log simple
DATA: lv_log_handle TYPE balloghndl, ls_log TYPE bal_s_log.
" Cabecera del logls_log-object = 'ZTEST'. " Objeto de log (desde SLG0)ls_log-subobject = 'PROCESS'. " Subobjetols_log-aldate = sy-datum.ls_log-altime = sy-uzeit.ls_log-aluser = sy-uname.ls_log-alprog = sy-repid.ls_log-extnumber = 'Mi procesamiento 001'.
" Crear logCALL FUNCTION 'BAL_LOG_CREATE' EXPORTING i_s_log = ls_log IMPORTING e_log_handle = lv_log_handle EXCEPTIONS log_header_inconsistent = 1 OTHERS = 2.
IF sy-subrc <> 0. RETURN.ENDIF.
" Añadir mensajeDATA: ls_msg TYPE bal_s_msg.
ls_msg-msgty = 'S'.ls_msg-msgid = 'ZMYAPP'.ls_msg-msgno = '001'.ls_msg-msgv1 = 'Procesamiento iniciado'.
CALL FUNCTION 'BAL_LOG_MSG_ADD' EXPORTING i_log_handle = lv_log_handle i_s_msg = ls_msg EXCEPTIONS log_not_found = 1 msg_inconsistent = 2 OTHERS = 3.
" Más mensajesls_msg-msgty = 'I'.ls_msg-msgv1 = '100 registros procesados'.CALL FUNCTION 'BAL_LOG_MSG_ADD' EXPORTING i_log_handle = lv_log_handle i_s_msg = ls_msg.
ls_msg-msgty = 'S'.ls_msg-msgv1 = 'Procesamiento completado'.CALL FUNCTION 'BAL_LOG_MSG_ADD' EXPORTING i_log_handle = lv_log_handle i_s_msg = ls_msg.
" Guardar logCALL FUNCTION 'BAL_DB_SAVE' EXCEPTIONS log_not_found = 1 save_not_allowed = 2 numbering_error = 3 OTHERS = 4.
IF sy-subrc = 0. COMMIT WORK. WRITE: / 'Log guardado'.ENDIF.2. Enfoque OO con CL_BAL_LOG
CLASS zcl_application_log DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING iv_object TYPE balobj_d iv_subobject TYPE balsubobj iv_extnumber TYPE balnrext OPTIONAL.
METHODS: add_success IMPORTING iv_message TYPE string.
METHODS: add_error IMPORTING iv_message TYPE string.
METHODS: add_warning IMPORTING iv_message TYPE string.
METHODS: add_info IMPORTING iv_message TYPE string.
METHODS: add_exception IMPORTING ix_error TYPE REF TO cx_root.
METHODS: save RETURNING VALUE(rv_success) TYPE abap_bool.
METHODS: display.
METHODS: get_messages RETURNING VALUE(rt_messages) TYPE bapiret2_t.
PRIVATE SECTION. DATA: mv_log_handle TYPE balloghndl.
METHODS: add_message IMPORTING iv_type TYPE sy-msgty iv_message TYPE string.ENDCLASS.
CLASS zcl_application_log IMPLEMENTATION. METHOD constructor. DATA: ls_log TYPE bal_s_log.
ls_log-object = iv_object. ls_log-subobject = iv_subobject. ls_log-aldate = sy-datum. ls_log-altime = sy-uzeit. ls_log-aluser = sy-uname. ls_log-alprog = sy-repid. ls_log-extnumber = iv_extnumber.
CALL FUNCTION 'BAL_LOG_CREATE' EXPORTING i_s_log = ls_log IMPORTING e_log_handle = mv_log_handle EXCEPTIONS OTHERS = 1. ENDMETHOD.
METHOD add_message. DATA: ls_msg TYPE bal_s_msg.
" Mensaje libre ls_msg-msgty = iv_type. ls_msg-msgid = 'ZLOG'. ls_msg-msgno = '000'. ls_msg-msgv1 = iv_message(50). IF strlen( iv_message ) > 50. ls_msg-msgv2 = iv_message+50(50). ENDIF. IF strlen( iv_message ) > 100. ls_msg-msgv3 = iv_message+100(50). ENDIF. IF strlen( iv_message ) > 150. ls_msg-msgv4 = iv_message+150(50). ENDIF.
CALL FUNCTION 'BAL_LOG_MSG_ADD' EXPORTING i_log_handle = mv_log_handle i_s_msg = ls_msg EXCEPTIONS OTHERS = 1. ENDMETHOD.
METHOD add_success. add_message( iv_type = 'S' iv_message = iv_message ). ENDMETHOD.
METHOD add_error. add_message( iv_type = 'E' iv_message = iv_message ). ENDMETHOD.
METHOD add_warning. add_message( iv_type = 'W' iv_message = iv_message ). ENDMETHOD.
METHOD add_info. add_message( iv_type = 'I' iv_message = iv_message ). ENDMETHOD.
METHOD add_exception. DATA: ls_msg TYPE bal_s_msg.
ls_msg-msgty = 'E'. ls_msg-msgid = 'ZLOG'. ls_msg-msgno = '001'. ls_msg-msgv1 = ix_error->get_text( )(50).
CALL FUNCTION 'BAL_LOG_MSG_ADD' EXPORTING i_log_handle = mv_log_handle i_s_msg = ls_msg EXCEPTIONS OTHERS = 1. ENDMETHOD.
METHOD save. DATA: lt_log_handles TYPE bal_t_logh.
APPEND mv_log_handle TO lt_log_handles.
CALL FUNCTION 'BAL_DB_SAVE' EXPORTING i_t_log_handle = lt_log_handles EXCEPTIONS log_not_found = 1 save_not_allowed = 2 numbering_error = 3 OTHERS = 4.
rv_success = xsdbool( sy-subrc = 0 ).
IF rv_success = abap_true. COMMIT WORK. ENDIF. ENDMETHOD.
METHOD display. DATA: lt_log_handles TYPE bal_t_logh, ls_profile TYPE bal_s_prof.
APPEND mv_log_handle TO lt_log_handles.
CALL FUNCTION 'BAL_DSP_PROFILE_STANDARD_GET' IMPORTING e_s_display_profile = ls_profile.
CALL FUNCTION 'BAL_DSP_LOG_DISPLAY' EXPORTING i_t_log_handle = lt_log_handles i_s_display_profile = ls_profile EXCEPTIONS OTHERS = 1. ENDMETHOD.
METHOD get_messages. DATA: lt_msg TYPE bal_t_msg, ls_msg TYPE bal_s_msg.
CALL FUNCTION 'BAL_LOG_MSG_READ' EXPORTING i_log_handle = mv_log_handle IMPORTING e_t_msg = lt_msg EXCEPTIONS OTHERS = 1.
LOOP AT lt_msg INTO ls_msg. APPEND VALUE bapiret2( type = ls_msg-msgty id = ls_msg-msgid number = ls_msg-msgno message_v1 = ls_msg-msgv1 message_v2 = ls_msg-msgv2 message_v3 = ls_msg-msgv3 message_v4 = ls_msg-msgv4 ) TO rt_messages. ENDLOOP. ENDMETHOD.ENDCLASS.
" UsoDATA(lo_log) = NEW zcl_application_log( iv_object = 'ZTEST' iv_subobject = 'BATCH' iv_extnumber = |Procesamiento { sy-datum }|).
lo_log->add_success( 'Procesamiento iniciado' ).lo_log->add_info( '500 registros cargados' ).
TRY. " Procesamiento... lo_log->add_success( 'Procesamiento exitoso' ). CATCH cx_root INTO DATA(lx_error). lo_log->add_exception( lx_error ).ENDTRY.
IF lo_log->save( ). lo_log->display( ).ENDIF.3. Crear objeto de log en SLG0
Transacción: SLG0
1. Clic en "Nuevas entradas"2. Objeto: ZTEST3. Texto del objeto: Mi aplicación de prueba4. Guardar
5. Crear subobjeto: - Subobjeto: BATCH - Texto: Procesamiento batch
- Subobjeto: ONLINE - Texto: Procesamiento online4. Log con contexto (datos adicionales)
DATA: lv_log_handle TYPE balloghndl, ls_log TYPE bal_s_log, ls_msg TYPE bal_s_msg.
" Crear logls_log-object = 'ZORDERS'.ls_log-subobject = 'PROCESS'.ls_log-extnumber = 'Procesamiento de pedidos'.
CALL FUNCTION 'BAL_LOG_CREATE' EXPORTING i_s_log = ls_log IMPORTING e_log_handle = lv_log_handle.
" Mensaje con contextols_msg-msgty = 'E'.ls_msg-msgid = 'ZORD'.ls_msg-msgno = '001'.ls_msg-msgv1 = '0000001234'. " Número de pedido
" Estructura de contexto (para navegación)DATA: ls_context TYPE bal_s_cont.ls_context-tabname = 'VBAK'.ls_context-value = '0000001234'.
ls_msg-context-tabname = 'VBAK'.ls_msg-context-value = ls_context-value.
CALL FUNCTION 'BAL_LOG_MSG_ADD' EXPORTING i_log_handle = lv_log_handle i_s_msg = ls_msg.5. Leer logs de la base de datos
DATA: lt_log_filter TYPE bal_s_lfil, lt_log_header TYPE balhdr_t, lt_log_handles TYPE bal_t_logh.
" Definir filtrolt_log_filter-object = VALUE #( ( sign = 'I' option = 'EQ' low = 'ZTEST' ) ).lt_log_filter-subobject = VALUE #( ( sign = 'I' option = 'EQ' low = 'BATCH' ) ).lt_log_filter-aldate = VALUE #( ( sign = 'I' option = 'GE' low = sy-datum - 7 ) ).
" Buscar logsCALL FUNCTION 'BAL_DB_SEARCH' EXPORTING i_s_log_filter = lt_log_filter IMPORTING e_t_log_header = lt_log_header EXCEPTIONS log_not_found = 1 no_filter_criteria = 2 OTHERS = 3.
IF sy-subrc = 0. WRITE: / 'Logs encontrados:', lines( lt_log_header ).
" Cargar logs CALL FUNCTION 'BAL_DB_LOAD' EXPORTING i_t_log_header = lt_log_header IMPORTING e_t_log_handle = lt_log_handles EXCEPTIONS OTHERS = 1.
" Mostrar CALL FUNCTION 'BAL_DSP_LOG_DISPLAY' EXPORTING i_t_log_handle = lt_log_handles EXCEPTIONS OTHERS = 1.ENDIF.6. Eliminar logs
DATA: lt_log_filter TYPE bal_s_lfil, lt_log_header TYPE balhdr_t.
" Encontrar logs antiguos (más de 30 días)lt_log_filter-object = VALUE #( ( sign = 'I' option = 'EQ' low = 'ZTEST' ) ).lt_log_filter-aldate = VALUE #( ( sign = 'I' option = 'LE' low = sy-datum - 30 ) ).
CALL FUNCTION 'BAL_DB_SEARCH' EXPORTING i_s_log_filter = lt_log_filter IMPORTING e_t_log_header = lt_log_header EXCEPTIONS OTHERS = 1.
" Eliminar logsIF lt_log_header IS NOT INITIAL. CALL FUNCTION 'BAL_DB_DELETE' EXPORTING i_t_logs_to_delete = lt_log_header EXCEPTIONS OTHERS = 1.
IF sy-subrc = 0. COMMIT WORK. WRITE: / 'Eliminados:', lines( lt_log_header ), 'logs'. ENDIF.ENDIF.Módulos de función importantes
| Módulo de función | Descripción |
|---|---|
BAL_LOG_CREATE | Crear log |
BAL_LOG_MSG_ADD | Añadir mensaje |
BAL_DB_SAVE | Guardar en BD |
BAL_DB_SEARCH | Buscar logs |
BAL_DB_LOAD | Cargar logs |
BAL_DB_DELETE | Eliminar logs |
BAL_DSP_LOG_DISPLAY | Mostrar logs |
Notas importantes / Mejores prácticas
- Objetos de log mantener en SLG0 (no hardcodear).
- Número externo para búsqueda fácil en SLG1.
- COMMIT WORK no olvidar tras BAL_DB_SAVE.
- Jerarquía usar para estructuración clara.
- Contexto para navegación a documentos.
- Callbacks implementar para visualización de detalles.
- Registro masivo para rendimiento con muchos mensajes.
- Logs antiguos limpiar regularmente (rendimiento).
- Clase de problema y nivel de detalle usar para filtrado.
- Combinar con Background Jobs para protocolo batch.