Documente Academic
Documente Profesional
Documente Cultură
normal ver isso feito recorrendo ao comando WRITE. Ora nos dias que correm, usar o comando WRITE para isto como recorrer a um par de pedras para acender uma fogueira. Afinal, porque no usar o Application Log que muito mais simples e prtico e standard e s vantagens?
O Application Log um sistema standard do SAP para guardar logs aplicacionais e usado por vrias transaces standard. Ao utiliz-lo podemos simplificar e uniformizar os logs dos nossos programas. Vamos aprender aqui como simples us-lo nos nossos desenvolvimentos. Como usar? Durante a execuo de um programa, vamos acumulando mensagens no log. No final podemos optar por apresentar as mensagens no ecr e/ou grav-las na base de dados para posterior consulta na SLG1. H casos em que no faz sentido guardar para a posterioridade; outros h, como os jobs, em que no faz sentido apresent-los no ecr. Nota: caso o objectivo seja s apresentar o log no ecr, no necessrio definir um objecto/sub-objecto. Mas como usar?? Funciona assim: 1. Configurar o objecto e sub-objecto (na SLG0);
1-12
67318517.doc
2. 3. 4. 5.
Inicializar log (definindo os seus objecto e sub-objecto); Adicionar-lhe mensagens at que a voz nos doa; Gravando-o na base de dados (para mais tarde recordar na SLG1); Apresentar o log no ecr.
Segue-se uma descrio detalhada de cada passo. No final do artigo deixo-vos o cdigo de um grupo de funes Z feito por um amigo meu que simplifica ainda mais a utilizao do Application Log. 0. Configurar na SLG0 A transaco SLG0 permite fazer a manuteno dos objectos e sub-objectos, os dois identificadores que servem para identificar os logs. Trolha que contm 2 interfaces e um job dirio. Ento na SLG0 pode definir-se o objecto ZTROLHA e debaixo destes um sub-objecto para cada um dos programas especficos: INTER1, INTER2, JOB1. O objecto tem de comear por Z ou Y; j os sub-objectos comeam pelo que bem se entender. 1. Inicializar A partir daqui vamos usar mdulos de funes do grupo de funes SBAL. A funo para inicializar o log a BAL_LOG_CREATE. No entanto, esta inicializao s necessria caso se deseje vir a guardar o log na base de dados. Se o objectivo for apenas apresent-lo no ecr este passo pode ser ignorado.
DATA: wa_log TYPE bal_s_log. wa_log-object = object. wa_log-subobject = subobject. wa_log-alprog = sy-repid. CALL FUNCTION 'BAL_LOG_CREATE' EXPORTING i_s_log = wa_log IMPORTING e_log_handle = log_handle EXCEPTIONS log_header_inconsistent = 1 OTHERS = 2.
H que guardar este log_handle. No caso de querermos gerir mais que um log ao mesmo tempo, este log_handle que permite distingui-los. 2. Amealhar A funo BAL_LOG_MSG_ADD serve para adicionar mensagens ao log.
CALL FUNCTION 'BAL_LOG_MSG_ADD' EXPORTING i_log_handle = log_handle i_s_msg = msg EXCEPTIONS
2-12
67318517.doc
= = = =
1 2 3 4.
Como boa prtica sugiro evitar mensagens dinmicas. Ver a dica aqui no Abapinho sobre isso. 3. Gravar
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.
Pronto. Assim fica guardado para a posteridade. Normalmente usamos s um log ao mesmo tempo mas esta funo pede uma tabela interna de log_handles. Enfim, fazla. 4. Apresentar no ecr
CALL FUNCTION 'BAL_DSP_LOG_DISPLAY' EXPORTING * i_s_display_profile = display_profile i_t_log_handle = it_log_handle[] i_amodal = space EXCEPTIONS profile_inconsistent = 1 internal_error = 2 no_data_available = 3 no_authority = 4 OTHERS = 5.
Esta funo apresenta o(s) log(s) no ecr. De notar o parmetro display_profile que est comentado. Esse parmetro permite configurar a forma como os logs so apresentados. O grupo de funes tem l vrias funes para configurar isto. Pronto. Simples, no? Mas para ficar ainda mais simples, aqui fica um grupo de funes Z feito pelo meu amigo leto Reinis Dzenis que pode ser usado em vez do standard:
FUNCTION-POOL z_application_log. "MESSAGE-ID ..
CONSTANTS: object_zall TYPE balobj_d VALUE 'ZALL'. * Global log handle DATA: it_log_handle TYPE bal_t_logh, log_handle TYPE balloghndl.
3-12
67318517.doc
FUNCTION z_appl_log_initialize . *"-------------------------------------------------*"*"Local interface: *" IMPORTING *" REFERENCE(OBJECT) TYPE BALOBJ_D OPTIONAL *" REFERENCE(SUBOBJECT) TYPE BALSUBOBJ OPTIONAL *" REFERENCE(EXTNUMBER) TYPE BALNREXT OPTIONAL *" REFERENCE(REPID) TYPE SY-REPID DEFAULT SY-CPROG *" EXCEPTIONS *" INIT_ERROR *"-------------------------------------------------DATA: wa_log TYPE bal_s_log. * Initialize current log object CLEAR: log_handle. * Log object IF object IS NOT INITIAL. wa_log-object = object. ELSE. wa_log-object = object_zall. ENDIF. * Log subobject wa_log-subobject = subobject. * External ID wa_log-extnumber = extnumber. * Report wa_log-alprog = repid. * Initialize log CALL FUNCTION 'BAL_LOG_CREATE' EXPORTING i_s_log = wa_log IMPORTING e_log_handle = log_handle EXCEPTIONS log_header_inconsistent = 1 OTHERS = 2. IF sy-subrc <> 0. RAISE init_error. ENDIF. * Collect log handles in table INSERT log_handle INTO TABLE it_log_handle. ENDFUNCTION. FUNCTION z_appl_log_write. *"-------------------------------------------------*"*"Local interface: *" IMPORTING *" REFERENCE(MSG) TYPE BAL_S_MSG OPTIONAL *" REFERENCE(MSG_TAB) TYPE BAL_T_MSG OPTIONAL *" REFERENCE(OBJECT) TYPE BALOBJ_D OPTIONAL *" REFERENCE(SUBOBJECT) TYPE BALSUBOBJ OPTIONAL *" REFERENCE(EXTNUMBER) TYPE BALNREXT OPTIONAL *" REFERENCE(REPID) TYPE SY-REPID OPTIONAL *" EXCEPTIONS *" INIT_ERROR
4-12
67318517.doc
*" WRITE_ERROR *"-------------------------------------------------FIELD-SYMBOLS: LIKE LINE OF msg_tab. * Initialize log if needed IF log_handle IS INITIAL. CALL FUNCTION 'Z_APPL_LOG_INITIALIZE' EXPORTING object = object subobject = subobject extnumber = extnumber repid = repid EXCEPTIONS init_error = 1 OTHERS = 2. IF sy-subrc <> 0. RAISE init_error. ENDIF. ENDIF. * Write passed message to log (if there is some...) IF msg IS NOT INITIAL. CALL FUNCTION 'BAL_LOG_MSG_ADD' EXPORTING i_log_handle = log_handle i_s_msg = msg EXCEPTIONS log_not_found = 1 msg_inconsistent = 2 log_is_full = 3 OTHERS = 4. IF sy-subrc <> 0. RAISE write_error. ENDIF. ENDIF. * Write passed table of messages to log (if there are some...) LOOP AT msg_tab ASSIGNING . CALL FUNCTION 'BAL_LOG_MSG_ADD' EXPORTING i_log_handle = log_handle i_s_msg = EXCEPTIONS log_not_found = 1 msg_inconsistent = 2 log_is_full = 3 OTHERS = 4. IF sy-subrc <> 0. RAISE write_error. ENDIF. ENDLOOP. ENDFUNCTION. FUNCTION z_appl_log_write_msg_syst. *"-------------------------------------------------*"*"Local interface: *" IMPORTING *" REFERENCE(OBJECT) TYPE BALOBJ_D OPTIONAL *" REFERENCE(SUBOBJECT) TYPE BALSUBOBJ OPTIONAL *" REFERENCE(EXTNUMBER) TYPE BALNREXT OPTIONAL
5-12
67318517.doc
*" REFERENCE(REPID) TYPE SY-REPID DEFAULT SY-CPROG *" EXCEPTIONS *" NO_SYST_MESSAGE *" WRITE_ERROR *"-------------------------------------------------DATA: msg_type msg_id msg_no TYPE msgty, TYPE msgid, TYPE msgno.
* Check if SYST contains valid message IF sy-msgty IS INITIAL OR sy-msgid IS INITIAL. RAISE no_syst_message. ENDIF. * Write Message to Log CALL FUNCTION 'Z_APPL_LOG_WRITE_MSG' EXPORTING msg_type = sy-msgty msg_id = sy-msgid msg_no = sy-msgno msg_v1 = sy-msgv1 msg_v2 = sy-msgv2 msg_v3 = sy-msgv3 msg_v4 = sy-msgv4 object = object subobject = subobject extnumber = extnumber repid = repid EXCEPTIONS write_error = 1 OTHERS = 2. IF sy-subrc <> 0. RAISE write_error. ENDIF. ENDFUNCTION. FUNCTION z_appl_log_from_bapiret. *"-------------------------------------------------*"*"Local interface: *" IMPORTING *" REFERENCE(BAPIRET2) TYPE BAPIRET2_T *" CHANGING *" REFERENCE(BAL_MSG_TAB) TYPE BAL_T_MSG *"-------------------------------------------------DATA: bal_msg LIKE LINE OF bal_msg_tab. FIELD-SYMBOLS: LIKE LINE OF bapiret2. LOOP AT bapiret2 ASSIGNING . CLEAR: bal_msg. * Save message via message class and no IF -id IS NOT INITIAL. bal_msg-msgty = -type. bal_msg-msgid = -id. bal_msg-msgno = -number. bal_msg-msgv1 = -message_v1. bal_msg-msgv2 = -message_v2. bal_msg-msgv3 = -message_v3. bal_msg-msgv4 = -message_v4.
6-12
67318517.doc
INSERT bal_msg INTO TABLE bal_msg_tab. Save message as text ELSEIF -message IS NOT INITIAL. bal_msg-msgty = -type. bal_msg-msgid = 'ZAPPLOG'. bal_msg-msgno = '000'. bal_msg-msgv1(50) = -message(50). bal_msg-msgv2(50) = -message+50(50). bal_msg-msgv3(50) = -message+100(50). bal_msg-msgv4(50) = -message+150(50). INSERT bal_msg INTO TABLE bal_msg_tab. ENDIF. ENDLOOP.
ENDFUNCTION. FUNCTION z_appl_log_write_bapiret. *"-------------------------------------------------*"*"Local interface: *" IMPORTING *" REFERENCE(BAPIRET2) TYPE BAPIRET2_T *" REFERENCE(OBJECT) TYPE BALOBJ_D OPTIONAL *" REFERENCE(SUBOBJECT) TYPE BALSUBOBJ OPTIONAL *" REFERENCE(EXTNUMBER) TYPE BALNREXT OPTIONAL *" REFERENCE(REPID) TYPE SY-REPID DEFAULT SY-CPROG *" EXCEPTIONS *" BAPIRET_INITIAL *" WRITE_ERROR *"-------------------------------------------------DATA: bal_msg_tab TYPE bal_t_msg. * See if valid BAPIRET was passed IF bapiret2[] IS INITIAL. RAISE bapiret_initial. ENDIF. * Create Application Log Message from BAPIRET CALL FUNCTION 'Z_APPL_LOG_FROM_BAPIRET' EXPORTING bapiret2 = bapiret2[] CHANGING bal_msg_tab = bal_msg_tab[]. * Write Application Log Message CALL FUNCTION 'Z_APPL_LOG_WRITE' EXPORTING msg_tab = bal_msg_tab[] object = object subobject = subobject extnumber = extnumber repid = repid EXCEPTIONS init_error = 1 write_error = 2 OTHERS = 3. IF sy-subrc <> 0. RAISE write_error. ENDIF. ENDFUNCTION.
7-12
67318517.doc
FUNCTION z_appl_log_write_text. *"-------------------------------------------------*"*"Local interface: *" IMPORTING *" REFERENCE(MSG_TXT) TYPE CHAR200 *" REFERENCE(MSG_TYPE) TYPE MSGTY DEFAULT 'I' *" REFERENCE(OBJECT) TYPE BALOBJ_D OPTIONAL *" REFERENCE(SUBOBJECT) TYPE BALSUBOBJ OPTIONAL *" REFERENCE(EXTNUMBER) TYPE BALNREXT OPTIONAL *" REFERENCE(REPID) TYPE SY-REPID DEFAULT SY-CPROG *" EXCEPTIONS *" WRITE_ERROR *"-------------------------------------------------DATA: msg TYPE bal_s_msg. msg-msgty = msg_type. msg-msgid = 'ZAPPLOG'. msg-msgno = '000'. msg-msgv1(50) = msg_txt(50). msg-msgv2(50) = msg_txt+50(50). msg-msgv3(50) = msg_txt+100(50). msg-msgv4(50) = msg_txt+150(50). CALL FUNCTION 'Z_APPL_LOG_WRITE' EXPORTING msg = msg object = object subobject = subobject extnumber = extnumber repid = repid EXCEPTIONS init_error = 1 write_error = 2 OTHERS = 3. IF sy-subrc <> 0. RAISE write_error. ENDIF. ENDFUNCTION. FUNCTION Z_APPL_LOG_READ_FROM_DB . *"-------------------------------------------------*"*"Local interface: *" IMPORTING *" REFERENCE(EXTERNALID) TYPE BALNREXT *" EXPORTING *" REFERENCE(MSG_TAB) TYPE BAL_T_MSG *"-------------------------------------------------DATA: ls_bal_s_lfil TYPE bal_s_lfil, ls_bal_s_extn TYPE bal_s_extn, lt_msg_handle TYPE bal_t_msgh, ls_msg_handle LIKE LINE OF lt_msg_handle, ls_msg TYPE bal_s_msg, l_line TYPE string, lt_log_header TYPE balhdr_t. * Configure filter with external id ls_bal_s_extn-sign = 'I'. ls_bal_s_extn-option = 'EQ'. ls_bal_s_extn-low = externalid.
8-12
67318517.doc
APPEND ls_bal_s_extn TO ls_bal_s_lfil-extnumber. * The log is still in memory so we use * this function to get message headers CALL FUNCTION 'BAL_GLB_SEARCH_MSG' EXPORTING i_s_log_filter = ls_bal_s_lfil IMPORTING e_t_msg_handle = lt_msg_handle EXCEPTIONS msg_not_found = 1 OTHERS = 2. IF sy-subrc NE 0. CALL FUNCTION 'BAL_DB_SEARCH' EXPORTING i_s_log_filter = ls_bal_s_lfil IMPORTING e_t_log_header = lt_log_header EXCEPTIONS log_not_found = 1 no_filter_criteria = 2 OTHERS = 3. CALL FUNCTION 'BAL_DB_LOAD' EXPORTING i_t_log_header = lt_log_header IMPORTING e_t_msg_handle = lt_msg_handle EXCEPTIONS no_logs_specified = 1 log_not_found = 2 log_already_loaded = 3 OTHERS = 4. ENDIF. * Get messages and write them to the log file refresh msg_tab. LOOP AT lt_msg_handle INTO ls_msg_handle. CLEAR ls_msg. CALL FUNCTION 'BAL_LOG_MSG_READ' EXPORTING i_s_msg_handle = ls_msg_handle IMPORTING e_s_msg = ls_msg * E_EXISTS_ON_DB = * E_TXT_MSGTY = * E_TXT_MSGID = * E_TXT_DETLEVEL = * E_TXT_PROBCLASS = * E_TXT_MSG = * E_WARNING_TEXT_NOT_FOUND = EXCEPTIONS log_not_found = 1 msg_not_found = 2 OTHERS = 3. append ls_msg to msg_tab. ENDLOOP. ENDFUNCTION. FUNCTION z_appl_log_db_save . *"--------------------------------------------------
9-12
67318517.doc
*"*"Local interface: *" EXCEPTIONS *" LOG_NOT_INITIALIZED *" DB_SAVE_ERROR *"-------------------------------------------------* See if log has been initialized IF it_log_handle[] IS INITIAL. RAISE log_not_initialized. ENDIF. * Try to save log to 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. RAISE db_save_error. ENDIF. ENDFUNCTION. FUNCTION z_appl_log_display. *"-------------------------------------------------*"*"Local interface: *" IMPORTING *" REFERENCE(MODE) TYPE NUM1 DEFAULT '0' *" EXCEPTIONS *" LOG_NOT_INITIALIZED *" DISPLAY_ERROR *"-------------------------------------------------DATA: display_profile TYPE bal_s_prof. * See if log has been initialized IF it_log_handle[] IS INITIAL. RAISE log_not_initialized. ENDIF. CASE mode. WHEN '0'. CALL FUNCTION 'BAL_DSP_PROFILE_STANDARD_GET' IMPORTING e_s_display_profile = display_profile. WHEN '1'. CALL FUNCTION 'BAL_DSP_PROFILE_NO_TREE_GET' IMPORTING e_s_display_profile = display_profile. WHEN '2'. CALL FUNCTION 'BAL_DSP_PROFILE_POPUP_GET' IMPORTING e_s_display_profile = display_profile. WHEN '3'. CALL FUNCTION 'BAL_DSP_PROFILE_SINGLE_LOG_GET' IMPORTING e_s_display_profile = display_profile. WHEN OTHERS. CALL FUNCTION 'BAL_DSP_PROFILE_STANDARD_GET' IMPORTING
10-12
67318517.doc
ENDCASE.
e_s_display_profile = display_profile.
* Display log CALL FUNCTION 'BAL_DSP_LOG_DISPLAY' EXPORTING i_s_display_profile = display_profile i_t_log_handle = it_log_handle[] i_amodal = space EXCEPTIONS profile_inconsistent = 1 internal_error = 2 no_data_available = 3 no_authority = 4 OTHERS = 5. IF sy-subrc <> 0. RAISE display_error. ENDIF. ENDFUNCTION. FUNCTION z_appl_log_clear. *"-------------------------------------------------*"*"Local interface: *"-------------------------------------------------FIELD-SYMBOLS: LIKE LINE OF it_log_handle. * Remove all created logs LOOP AT it_log_handle ASSIGNING . CALL FUNCTION 'BAL_LOG_REFRESH' EXPORTING i_log_handle = EXCEPTIONS log_not_found = 1 OTHERS = 2. ENDLOOP. REFRESH: it_log_handle[]. CLEAR: log_handle. ENDFUNCTION. FUNCTION z_appl_log_get_handle. *"-------------------------------------------------*"*"Local interface: *" EXPORTING *" REFERENCE(E_LOG_HANDLE) TYPE BALLOGHNDL *" REFERENCE(ET_LOG_HANDLE) TYPE BAL_T_LOGH *" EXCEPTIONS *" NO_HANDLE *"-------------------------------------------------* See if log is initialized IF it_log_handle[] IS INITIAL AND log_handle IS INITIAL. RAISE no_handle. ENDIF. e_log_handle = log_handle. et_log_handle[] = it_log_handle[]. ENDFUNCTION.
11-12
67318517.doc
FUNCTION z_appl_log_write_param. *"-------------------------------------------------*"*"Local interface: *" IMPORTING *" REFERENCE(PARAMETER) *" REFERENCE(MSG_TYPE) TYPE MSGTY DEFAULT 'I' *" REFERENCE(OBJECT) TYPE BALOBJ_D OPTIONAL *" REFERENCE(SUBOBJECT) TYPE BALSUBOBJ OPTIONAL *" REFERENCE(EXTNUMBER) TYPE BALNREXT OPTIONAL *" REFERENCE(REPID) TYPE SY-REPID DEFAULT SY-CPROG *" EXCEPTIONS *" WRITE_ERROR *"-------------------------------------------------DATA: msg_txt TYPE char200, tmp TYPE string. DATA: fieldname TYPE fieldname, ddtext TYPE ddtext. * Spell fieldname CALL FUNCTION 'Z_SPELL_FIELDNAME' EXPORTING field = parameter IMPORTING ddtext = ddtext fieldname = fieldname. IF parameter IS INITIAL. CONCATENATE: 'SELECTION:' ddtext 'is empty' INTO msg_txt SEPARATED BY space. ELSE. WRITE: parameter TO msg_txt. SHIFT msg_txt LEFT DELETING LEADING space. CONCATENATE: 'SELECTION:' ddtext 'is equal to' msg_txt INTO msg_txt SEPARATED BY space. ENDIF. * Write to log... CALL FUNCTION 'Z_APPL_LOG_WRITE_TEXT' EXPORTING msg_txt = msg_txt msg_type = msg_type object = object subobject = subobject extnumber = extnumber repid = repid EXCEPTIONS write_error = 1 OTHERS = 2. IF sy-subrc <> 0. RAISE write_error. ENDIF. ENDFUNCTION.
12-12
67318517.doc