大家好,
今天小弟与各位ABAPer 分享一个自己开发的比较简单的 log framework 以便在程序中记录log之用。
大家知道SAP中log的定义与查询是通过T-CODE: SLG0(定义log object 与log subobject )以及SLG1 (查询log ),这两个标准tcode 实现的。
所以开发人员自己所要做的就是在程序中使用SAP提供的标准方法去创建log ,添加log, 以及保存log。
SAP 已提供一系列标准方法,主要的有:
BAL_LOG_CREATE
BAL_LOG_MSG_ADD
BAL_DB_SAVE
BAL_DSP_LOG_DISPLAY
如果在程序中调用function去记录log,未免有些太凌乱,代码太冗长, 代码可读性会大大降低,并且同样的逻辑不能重用.
所以小弟以OO的方式,编写一个比较简单的框架:
YLOG_ABSTR 的方法的实现:
YLOG~ADD:
**********************************************************************
**********************************************************************
* This Method is to add a new msg to the log handle
**********************************************************************
**********************************************************************
call function 'BAL_LOG_MSG_ADD'
exporting
i_log_handle = me->log_handle
i_s_msg = pi_s_msg
* IMPORTING
* E_S_MSG_HANDLE =
* E_MSG_WAS_LOGGED =
* E_MSG_WAS_DISPLAYED =
* EXCEPTIONS
* LOG_NOT_FOUND = 1
* MSG_INCONSISTENT = 2
* LOG_IS_FULL = 3
* OTHERS = 4
.
if sy-subrc <> 0.
data: lv_message type string.
clear lv_message.
call function 'MESSAGE_TEXT_BUILD'
exporting
msgid = sy-msgid
msgnr = sy-msgno
msgv1 = sy-msgv1
msgv2 = sy-msgv2
msgv3 = sy-msgv3
msgv4 = sy-msgv4
importing
message_text_output = lv_message.
raise exception type ycx_log_add_error
exporting msg = lv_message.
endif.
YLOG~SAVE:
**********************************************************************
**********************************************************************
* This Method is to save the log for the log refered log handle
**********************************************************************
**********************************************************************
data lt_log_handle type bal_t_logh.
data ls_log_handle type balloghndl.
ls_log_handle = me->log_handle.
append ls_log_handle to lt_log_handle.
call function 'BAL_DB_SAVE'
exporting
* I_CLIENT = SY-MANDT
* I_IN_UPDATE_TASK = ' '
* I_SAVE_ALL = ' '
i_t_log_handle = lt_log_handle
importing
e_new_lognumbers = pr_log_number
* EXCEPTIONS
* LOG_NOT_FOUND = 1
* SAVE_NOT_ALLOWED = 2
* NUMBERING_ERROR = 3
* OTHERS = 4
.
if sy-subrc <> 0.
data: lv_message type string.
clear lv_message.
call function 'MESSAGE_TEXT_BUILD'
exporting
msgid = sy-msgid
msgnr = sy-msgno
msgv1 = sy-msgv1
msgv2 = sy-msgv2
msgv3 = sy-msgv3
msgv4 = sy-msgv4
importing
message_text_output = lv_message.
raise exception type ycx_log_save_error
exporting
msg = lv_message.
endif.
YLOG~DISPLAY:
data lt_log_handle type bal_t_logh.
if i_t_log_handle is initial.
append me->log_handle to lt_log_handle.
else.
lt_log_handle = i_t_log_handle.
endif.
me->log_display_behavior->display(
i_s_log_filter = i_s_log_filter
i_t_log_context_filter = i_t_log_context_filter
i_t_log_handle = lt_log_handle
i_s_msg_filter = i_s_msg_filter
i_t_msg_context_filter = i_t_msg_context_filter
i_t_msg_handle = i_t_msg_handle
).
SET_DISPLAY_BEHAVIOR:
me->LOG_DISPLAY_BEHAVIOR = pi_disp_bhv.
pr_log_handle = me->log_handle.
YLOG_DEF 完全继承 YLOG_ABSTR的所有实现,并没有覆盖任何方法, 只是为了有个具有默认实现的类用来实例化,大家也可以通过创建一个新的LOG 子类去继承
YLOG_ABSTR 并且覆盖或新增一些自己的方法,让自己的log类具有与众不同的实现。
YLOG_DYNPRO_DISPLAYER 是一个 实现了YLOG_DISPLAY_BEHAVIOR接口的具体类, 这个类的实现是用来把log 用classic dynpro 的方式去显示在屏幕上,供用户查看。当然大家也可以自己创建一个displayer 类去实现YLOG_DISPLAY_BEHAVIOR接口, 比如实现一个能将log 用web dynpro 的方式显示的类。使用方法: 在程序中,首先会去初始化一个YLOG_DISPLAY_BEHAVIOR的实例, 然后调用YLOG实例的SET_DISPLAY_BEHAVIOR方法,把这个显示行为装备给YLOG 的实例,那么在调用YLOG 的DISPLAY 方法去显示日志的时候, YLOG 实例会自动去使用装备给它的显示行为的display方法去显示日志。 所以真正显示日志的工作其实是display 类去做的,YLOG 实例只不过借花献佛而已,这样做的好处是可以随时修改LOG 的显示行为,我可以通过classic dynpro的方式去显示日志,也可以通过web dynpro的方式去显示日志,比较灵活一点。
YLOG_DYNPRO_DISPLAYER的方法实现:
YLOG_DISPLAY_BEHAVIOR~DISPLAY:
**********************************************************************
**********************************************************************
* This Method is to display the log using via alv
**********************************************************************
**********************************************************************
call function 'BAL_DSP_LOG_DISPLAY'
exporting
* I_S_DISPLAY_PROFILE =
i_t_log_handle = i_t_log_handle
i_t_msg_handle = i_t_msg_handle
i_s_log_filter = i_s_log_filter
i_s_msg_filter = i_s_msg_filter
i_t_log_context_filter = i_t_log_context_filter
i_t_msg_context_filter = i_t_msg_context_filter
* I_AMODAL = ' '
* I_SRT_BY_TIMSTMP = ' '
* IMPORTING
* E_S_EXIT_COMMAND =
exceptions
profile_inconsistent = 1
internal_error = 2
no_data_available = 3
no_authority = 4
others = 5
.
if sy-subrc <> 0.
data: lv_message type string.
clear lv_message.
call function 'MESSAGE_TEXT_BUILD'
exporting
msgid = sy-msgid
msgnr = sy-msgno
msgv1 = sy-msgv1
msgv2 = sy-msgv2
msgv3 = sy-msgv3
msgv4 = sy-msgv4
importing
message_text_output = lv_message.
raise exception type ycx_log_disp_error
exporting
msg = lv_message.
endif.
YLOG_SIMPLE_FACT 是一个简单工厂类,用来生产YLOG 实例, 方法实现:
PRODUCE_LOGGER:
**********************************************************************
**********************************************************************
* This Method is to produce a log intance
* PI_OBJECT specify the log object
* PI_SUBOBJECT specify the log sub object
* PI_CLASS_NAME must be the name of an exsting log class which implements
* YLOG interface , otherwise a sy_class_creation will be thrown
* and the constructor's parameter of the class
* must be PI_LOG_HANDLE type balloghndl, otherwise a
* sy_dyn_parameter_missing exception will be thrown
* VALUE( PR_LOGGER ) return the instance reference
**********************************************************************
**********************************************************************
data ls_s_log type bal_s_log.
ls_s_log-extnumber = pi_extnumber.
ls_s_log-object = pi_object.
ls_s_log-subobject = pi_subobject.
ls_s_log-aldate = sy-datum.
ls_s_log-altime = sy-uzeit.
ls_s_log-aluser = sy-uname.
data lv_log_handle type balloghndl.
call function 'BAL_LOG_CREATE'
exporting
i_s_log = ls_s_log
importing
e_log_handle = lv_log_handle
exceptions
log_header_inconsistent = 1
others = 2.
if sy-subrc <> 0.
raise exception type ycx_log_handle_cr
exporting log_header = ls_s_log.
else.
data lv_class_name type seoclsname.
lv_class_name = pi_class_name.
data lo_log_abstr type ref to ylog_abstr.
create object lo_log_abstr
type
(lv_class_name)
exporting
pi_log_handle = lv_log_handle.
data lv_disp_hbv type seoclsname.
lv_disp_hbv = pi_disp_bhv.
data lo_log_bhv type ref to ylog_display_behavior.
create object lo_log_bhv type (lv_disp_hbv).
lo_log_abstr->set_display_behavior( lo_log_bhv ).
pr_logger = lo_log_abstr.
endif.
data ls_lfil type bal_s_lfil.
data lt_r_extn type bal_r_extn.
data ls_r_extn like line of lt_r_extn.
ls_r_extn-sign = 'I'.
ls_r_extn-option = 'EQ'.
ls_r_extn-low = pi_ext_no.
ls_r_extn-high = pi_ext_no.
append ls_r_extn to lt_r_extn.
ls_lfil-extnumber = lt_r_extn.
data lt_logh type bal_t_logh.
data ls_logh like line of lt_logh.
call function 'BAL_GLB_SEARCH_LOG'
exporting
i_s_log_filter = lt_r_extn
** I_T_LOG_CONTEXT_FILTER =
** I_T_LOG_HANDLE =
importing
e_t_log_handle = lt_logh
exceptions
log_not_found = 1
others = 2
.
if sy-subrc <> 0.
raise exception type ycx_log_logh_not_found
exporting
ext_no = pi_ext_no.
endif.
read table lt_logh into ls_logh index 1.
data lv_class_name type seoclsname.
lv_class_name = pi_class_name.
data lo_log_abstr type ref to ylog_abstr.
create object lo_log_abstr
type
(lv_class_name)
exporting
pi_log_handle = ls_logh.
data lv_disp_hbv type seoclsname.
lv_disp_hbv = pi_disp_bhv.
data lo_log_bhv type ref to ylog_display_behavior.
create object lo_log_bhv type (lv_disp_hbv).
lo_log_abstr->set_display_behavior( lo_log_bhv ).
pr_logger = lo_log_abstr.
大家可能会注意到,这些方法实现中有些地方会抛出一些exception,这是我自己定义的一个异常体系,类图如下,就不详细解释了,大家也可以把抛异常的部分修改掉,用自己的方式返回这个异常状态。
好了,写完了,小弟OO 水平有限,可能设计不好,望见谅, 有些细节方面可能没有完全照顾到,望宽恕。
纯属分享一下使用SAP 标准LOG function 的一些经验心得。如有错误,请指正。