
BTP - Application Job (Log)
How do I create a job log in the application job so that the user receives important information about the job? In this article we take a closer look at the topic.
Table of contents
The output of messages for a job is important because debugging is not possible in the ABAP environment and we need information about certain states in the job, especially if it aborts during processing. In this article we'll look at the specifics and how to attach a log to the job.
Introduction
To generate messages for the job, we need the application log, which is known from on-premise via transactions SLG0 and SLG1. In the ABAP Environment, generation works a little differently than we are used to on-premise. Last week we published the article about logging in the ABAP Cloud environment, where you can read about the similarities and differences and get further information that we will not go into in detail in this article.
Application Log
In this section we extend the job to output messages and provide insights into the job run, especially if problems arise.
Log Object
First of all, we have to create an Application Log object and sub-object in order to be able to save messages on the job. We create it in the job package using the ABAP Development Tools:
Messages
In the next step we want to use the application log in the job. To do this, we extend the executing class ZCL_BS_DEMO_JOB_ADT_EXE that we created in this article. To do this, we define a new method that is supposed to create and save some messages.
METHODS log_some_messages
IMPORTING id_severity TYPE cl_bali_free_text_setter=>ty_severity
RAISING cx_bali_runtime
cx_uuid_error.
In the method we create a demo log object, add some free text messages and save the log to the database. The first message is determined by the transfer parameter. Basically you don't need the variable LO_FREE and you could chain the call. For the sake of clarity, we have separated the calls in the example.
METHOD log_some_messages.
DATA lo_free TYPE REF TO if_bali_free_text_setter.
DATA(lo_log) = cl_bali_log=>create( ).
DATA(lo_header) = cl_bali_header_setter=>create( object = 'ZBS_DEMO_JOB_LOG'
subobject = 'JOB'
external_id = cl_system_uuid=>create_uuid_c32_static( ) ).
lo_log->set_header( lo_header ).
lo_free = cl_bali_free_text_setter=>create( severity = id_severity
text = 'This message is free' ).
lo_log->add_item( lo_free ).
lo_free = cl_bali_free_text_setter=>create( severity = if_bali_constants=>c_severity_warning
text = 'This is a warning' ).
lo_log->add_item( lo_free ).
lo_free = cl_bali_free_text_setter=>create( severity = if_bali_constants=>c_severity_status
text = 'This is a success' ).
lo_log->add_item( lo_free ).
cl_bali_log_db=>get_instance( )->save_log( log = lo_log
assign_to_current_appl_job = abap_true ).
ENDMETHOD.
Hint: What is particularly important is the setting when saving the log; here the flag ASSIGN_TO_CURRENT_APPL_JOB must be set to ABAP_TRUE so that the log is saved with the running job.
Execution
Let's now plan the job in the system and let it run. A corresponding identification of the job run now appears in the “Log” area; this also serves as navigation into the logs.
If you click on the button, you will be taken to the corresponding application log and have further options to filter the message texts and severity of the messages.
The overall status of the job is determined by the highest severity in the messages. Because we generated an error message, the job is red.
Special feature
What actually happens if we create and save several logging objects during the job process? To do this, we call the LOG_SOME_MESSAGES method twice, once with “Warning” and once with “Error”. If we now schedule the job, we will see a change in the job status.
The indicator tells us that two logs were saved on the job. When you click on the status, we get the choice to go to one of the two logs. Each log has a corresponding severity mark so we can identify errors immediately. After the jump we see the same view as in the picture above.
Complete example
To conclude the article, review the entire job class to understand the adjustments we made in this article.
CLASS zcl_bs_demo_job_adt_exe DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_apj_dt_exec_object.
INTERFACES if_apj_rt_exec_object.
PRIVATE SECTION.
METHODS log_some_messages
IMPORTING id_severity TYPE cl_bali_free_text_setter=>ty_severity
RAISING cx_bali_runtime
cx_uuid_error.
ENDCLASS.
CLASS zcl_bs_demo_job_adt_exe IMPLEMENTATION.
METHOD if_apj_dt_exec_object~get_parameters.
et_parameter_def = VALUE #( datatype = 'C'
changeable_ind = abap_true
( selname = 'TEXT'
kind = if_apj_dt_exec_object=>parameter
param_text = 'Free text'
length = 50
lowercase_ind = abap_true
mandatory_ind = abap_true )
( selname = 'COUNTRY'
kind = if_apj_dt_exec_object=>select_option
param_text = 'Country'
length = 3 )
( selname = 'R_TEXT'
kind = if_apj_dt_exec_object=>parameter
param_text = 'Text'
length = 1
radio_group_ind = abap_true
radio_group_id = 'R1' )
( selname = 'R_LAND'
kind = if_apj_dt_exec_object=>parameter
param_text = 'Country'
length = 1
radio_group_ind = abap_true
radio_group_id = 'R1' )
( selname = 'TEST'
kind = if_apj_dt_exec_object=>parameter
param_text = 'Test'
length = 1
checkbox_ind = abap_true ) ).
et_parameter_val = VALUE #( sign = 'I'
option = 'EQ'
( selname = 'TEST' low = abap_true )
( selname = 'R_TEXT' low = abap_false )
( selname = 'R_LAND' low = abap_true ) ).
ENDMETHOD.
METHOD if_apj_rt_exec_object~execute.
DATA ld_text TYPE c LENGTH 50.
DATA lt_r_country TYPE RANGE OF I_CountryText-Country.
DATA ld_radio_text TYPE abap_boolean.
DATA ld_radio_country TYPE abap_boolean.
DATA ld_test TYPE abap_boolean.
LOOP AT it_parameters INTO DATA(ls_parameter).
CASE ls_parameter-selname.
WHEN 'TEXT'.
ld_text = ls_parameter-low.
WHEN 'COUNTRY'.
INSERT CORRESPONDING #( ls_parameter ) INTO TABLE lt_r_country.
WHEN 'R_TEXT'.
ld_radio_text = ls_parameter-low.
WHEN 'R_LAND'.
ld_radio_country = ls_parameter-low.
WHEN 'TEST'.
ld_test = ls_parameter-low.
ENDCASE.
ENDLOOP.
DATA(ls_database) = VALUE zbs_dmo_jtrack( identifier = cl_system_uuid=>create_uuid_x16_static( )
rdate = cl_abap_context_info=>get_system_date( )
rtime = cl_abap_context_info=>get_system_time( )
test = ld_test ).
CASE abap_true.
WHEN ld_radio_text.
ls_database-content = ld_text.
WHEN ld_radio_country.
SELECT FROM I_CountryText
FIELDS CountryName
WHERE Country IN @lt_r_country
AND Language = @sy-langu
INTO TABLE @DATA(lt_names).
ls_database-content = concat_lines_of( table = lt_names sep = `, ` ).
ENDCASE.
INSERT zbs_dmo_jtrack FROM @ls_database.
COMMIT WORK.
log_some_messages( if_bali_constants=>c_severity_warning ).
log_some_messages( if_bali_constants=>c_severity_error ).
ENDMETHOD.
METHOD log_some_messages.
DATA lo_free TYPE REF TO if_bali_free_text_setter.
DATA(lo_log) = cl_bali_log=>create( ).
DATA(lo_header) = cl_bali_header_setter=>create( object = 'ZBS_DEMO_JOB_LOG'
subobject = 'JOB'
external_id = cl_system_uuid=>create_uuid_c32_static( ) ).
lo_log->set_header( lo_header ).
lo_free = cl_bali_free_text_setter=>create( severity = id_severity
text = 'This message is free' ).
lo_log->add_item( lo_free ).
lo_free = cl_bali_free_text_setter=>create( severity = if_bali_constants=>c_severity_warning
text = 'This is a warning' ).
lo_log->add_item( lo_free ).
lo_free = cl_bali_free_text_setter=>create( severity = if_bali_constants=>c_severity_status
text = 'This is a success' ).
lo_log->add_item( lo_free ).
cl_bali_log_db=>get_instance( )->save_log( log = lo_log
assign_to_current_appl_job = abap_true ).
ENDMETHOD.
ENDCLASS.
Conclusion
With the application logs you have the opportunity to send messages in the job to the outside world. You are not limited to one log, but can attach as many logs to the job as possible. However, you should note that the only identification is then the ID of the log and a comprehensive search is not possible.