Есть мнение, что каждый ABAP-разработчик написал свой логгер. Но может ли ваш логгер добавлять произвольные поля или например «проваливаться в транзакции»? И все это стандартными возможностями без каких-либо точек расширения. Ниже представляю описание своего класса для ведения логов. Скачать его можно через ABAP Git по ссылке.
Создание экземпляра класса
Ниже представлены основные варианты использования конструктора класса. Помимо приведенных вариантов в конструктор можно передать любые параметры структуры BAL_S_LOG. Описание параметров подробно описано в статье.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
" Сообщения будут храниться в памяти и очистятся после закрытия программы DATA(lo_log) = NEW zcl_log( ). " Сообщения можно будет записать в БД для просмотра в SLG1, SLGD DATA(lo_log) = NEW zcl_log( iv_object = 'ZBAL_OBJECT' " Имя объекта (настройка в SLG0) iv_subobject = 'ZBAL_SUBOJBECT' " Имя подобъекта (настройка в SLG0) ). " Загрузится лог из БД, новые сообщения будут записываться в него же DATA(lo_log) = NEW zcl_log( iv_log_handle = lv_log_handle " Ид. номер журнала ). |
Добавление новых сообщений
Для ведения логов рекомендуется все сообщения выносить в класс сообщений (тр. SE91) и добавлять их в лог через оператор MESSAGE и метод ADD_SYST. Этот подход позволит находить сообщения через журнал использования и добавлять перевод при необходимости. Все методы содержат необязательные параметры, аналогичные полям структуры BAL_S_MSG. Описание параметров подробно описано в статье.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
DATA(lo_log) = NEW zcl_log( ). " Добавление сообщение из системной структуры SY MESSAGE e444(00) INTO sy-msgli. " Соединение прервано. lo_log->add_syst( ). " Добавление сообщение из строки lo_log->add_free_text( iv_msgty = rs_c_error iv_text = lv_message ). " Добавление сообщения из структуры " Параметр структуры может содержать структуры типа " - ADD_BAL_S_MSG " - ADD_BAL_S_MSGR " - ADD_BAPIRET1 " - ADD_BAPIRET2 " - ADD_BAPIRETURN " - ADD_BDCMSGCOLL " - ADD_FIMSG " - ADD_MESG lo_log->add_struct( ls_return ). " Добавление сообщений из таблицы " Тип строки таблицы может принимать те же значения что и структура " Удобно использовать при получении таблицы сообщений BAPI, BDC и.п. lo_log->add_table( lt_return ). " Добавление сообщений из другого лога lo_log->add_log( lo_other_log ). |
Добавление исключений
Для добавления исключений реализовано 2 метода: ADD_EXCEPTION и ADD_EXC. Первый использует BAL_LOG_EXCEPTION_ADD и дает возможность отобразить подробное сообщение. Второй метод позволяет отобразить стек вызовов исключения и локализовать место возникновения. Демонстрация ниже.
1 2 3 4 5 6 7 8 9 |
DATA(lo_log) = NEW zcl_log( ). TRY . DATA(lv_kek) = 1 / 0. CATCH cx_root INTO DATA(lo_error). lo_log->add_exception( lo_error ). lo_log->add_exc( lo_error ). ENDTRY. |
Так будет выглядеть журнал сообщений
При детализации первого сообщения (метод ADD_EXCEPTION) будет отображаться подробное сообщение
При детализации второго (метод ADD_EXC) будет отображаться стек вызовов и место возникновения исключения. Можно будет провалиться в программу и строку где оно возникло.
Отображение сообщений
Для отображения сообщений используется метод DISPLAY. Вывод сообщений реализуется через BAL_DSP_LOG_DISPLAY, для детальной настройки которого можно заполнить необязательный параметр IS_DISPLAY_PROFILE типа BAL_S_PROF.
1 2 3 4 5 6 7 8 9 10 11 12 |
DATA(lo_log) = NEW zcl_log( ). MESSAGE s042(00) INTO sy-msgli. " Данные сброшены. lo_log->add_syst( ). TRY. DATA(lv_kek) = 1 / 0. CATCH cx_root INTO DATA(lo_error). lo_log->add_exc( lo_error ). ENDTRY. lo_log->display( ). |
Можно также выводить сообщения в модальном окне через метод POPUP. При этом, вызовется BAL_DSP_LOG_DISPLAY с профилем POPUP.
1 2 3 |
... lo_log->popup( ). |
Для просмотра сообщений через DISPLAY или POPUP у пользователя должны быть права на SLG1. Если их нет и нужно отобразить сообщения, можно воспользоваться методом MODAL. Данный метод использует функцию MESSAGES_SHOW, которая не требует никаких дополнительных прав. При этом, возможность детализации сообщений пропадет.
1 2 |
... lo_log->modal( ). |
Сохранение и поиск сообщений из базы данных
Для сохранения логов в БД необходимо использовать методы SAVE и COMMIT. Для поиска логов из БД следует использовать статичный метод SEARCH, который принимает на вход критерии выбора логов (структура типа BAL_S_LFIL) и возвращает инстанцию лога с найденными сообщениями.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
" Сохранение логов в БД DATA(lo_log) = NEW zcl_log( iv_object = 'ZTEST_OBJECT' iv_subobject = 'ZTEST_SUBOBJECT' ). MESSAGE s042(00) INTO sy-msgli. " Данные сброшены. lo_log->add_syst( ). lo_log->save( ). lo_log->commit( ). " Поиск логов DATA(lo_log) = zcl_log=>search( VALUE #( object = VALUE #( ( low = 'ZTEST_OBJECT' ) ) subobject = VALUE #( ( low = 'ZTEST_SUBOBJECT' ) ) ) ). lo_log->popup( ). |
Кумуляция сообщений
Некоторые сообщения отправляются программой несколько раз без предоставления новой информации. Такие сообщения могут быть объединены с помощью необязательного параметра IV_CUMULATE (в каждом методе добавления сообщений). Когда повторяется одно и то же сообщение, новое сообщение не добавляется, счетчик MSG_COUNT для старого сообщения увеличивается.
1 2 3 4 5 6 |
DATA(lo_log) = NEW zcl_log( ). DO 10 TIMES. MESSAGE s042(00) INTO sy-msgli. " Данные сброшены. lo_log->add_syst( iv_cumulate = abap_true ). ENDDO. lo_log->popup( ). |
Если же IV_CUMULATE не передавать или передать в него значение ABAP_FALSE, то будут отображаться все сообщения.
Изменение и удаление и сообщений
Любое сообщение имеет свой номер. Зная данный номер сообщение можно изменить или удалить. Пример ниже сначала добавляет сообщение, затем изменяет его и удаляет.
1 2 3 4 5 6 7 8 9 10 |
DATA(lo_log) = NEW zcl_log( ). MESSAGE e190(00) INTO sy-msgli. " Изменение пароля невозможно. lo_log->add_syst( IMPORTING es_msg_handle = DATA(ls_msg_handle) ). MESSAGE s192(00) INTO sy-msgli. " Пароль изменен. lo_log->change_from_syst( ls_msg_handle ). lo_log->del( ls_msg_handle ). |
Функциональные методы
Все методы класса ZCL_LOG являются функциональными. Это означает что все методы имеют параметр возврата RETURNING. В методах где результат не должен возвращаться, возвращается инстанция текущего лога. Это позволяет выводить сообщения через цепочки вызовов.
1 2 3 4 5 |
MESSAGE s042(00) INTO sy-msgli. " Данные сброшены. NEW zcl_log( )->add_syst( )->modal( ). |
Дополнительные поля в сообщении
Иногда текст сообщения имеет смысл только в определенном контекста. Добавить контекст можно через параметр IS_CONTEXT, который есть в каждом методе добавления сообщения. Ниже пример добавления поля поставки к сообщению. По значениям данного поля можно также производить поиск через метод SEARCH.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
DATA ls_content TYPE vbeln_line. DATA ls_context TYPE bal_s_cont. FIELD-SYMBOLS <lv_content> TYPE c. SELECT SINGLE * INTO CORRESPONDING FIELDS OF ls_content FROM likp. ASSIGN ls_content TO <lv_content> CASTING. ls_context-tabname = cl_abap_typedescr=>describe_by_data( ls_content )->get_relative_name( ). ls_context-value = <lv_content>. MESSAGE e130(vg) INTO sy-msgli. " Документ проведен. NEW zcl_log( )->add_syst( is_context = ls_context )->popup( ). |
Вложение данных к сообщению
В каждом методе добавления сообщений есть необязательный параметр I_ATTACHMENT, который позволяет приложить к сообщению произвольные данные: значение, структура, таблица.
1 2 3 4 5 6 7 8 9 10 |
SELECT * INTO TABLE @DATA(lt_data) FROM spfli. DATA(lo_log) = NEW zcl_log( ). MESSAGE s094(00) INTO sy-msgli. " Данные были сохранены. lo_log->add_syst( i_attachment = lt_data ). lo_log->popup( ). |
При добавлении сообщения с параметром I_ATTACHMENT автоматически появится кнопка «Подробно», при нажатии на которую откроется программа отображения данных.
Пример отображения вложенной таблицы
Пример отображения вложенной структуры
Произвольная детализация сообщения
Внутренняя механика детализации сообщения описана в статье. Однако, на практике использовать ее можно только в процедурном стиле. Для ООП программирования детализацию сообщения можно сделать путем имплементации интерфейса ZIF_LOG_DETAILS
Интерфейс ZIF_LOG_DETAILS содержит три метода:
CREATE — создание инстанции объекта по ключу
GET_KEY — возвращает ключ для создания объекта
SHOW — метод отображения данных
Ниже описан пример для проваливания в FB03
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
CLASS lcl_details DEFINITION. PUBLIC SECTION. INTERFACES zif_log_details. METHODS constructor IMPORTING is_bkpf_key TYPE bkpf_key. PRIVATE SECTION. DATA ms_bkpf_key TYPE bkpf_key. ENDCLASS. CLASS lcl_details IMPLEMENTATION. METHOD constructor. ms_bkpf_key = is_bkpf_key. ENDMETHOD. METHOD zif_log_details~create. ro_instance = NEW lcl_details( CONV #( iv_key ) ). ENDMETHOD. METHOD zif_log_details~get_key. rv_key = CONV #( ms_bkpf_key ). ENDMETHOD. METHOD zif_log_details~show. SET PARAMETER ID 'BUK' FIELD ms_bkpf_key-bukrs. SET PARAMETER ID 'GJR' FIELD ms_bkpf_key-gjahr. SET PARAMETER ID 'BLN' FIELD ms_bkpf_key-belnr. CALL TRANSACTION 'FB03' AND SKIP FIRST SCREEN. ENDMETHOD. ENDCLASS. START-OF-SELECTION. PERFORM main. FORM main. DATA ls_bkpf_key TYPE bkpf_key. DATA lo_details TYPE REF TO lcl_details. DATA lo_log TYPE REF TO zcl_log. SELECT SINGLE * INTO CORRESPONDING FIELDS OF ls_bkpf_key FROM bkpf. lo_log = NEW #( ). lo_details = NEW #( ls_bkpf_key ). MESSAGE s015(ujh0) INTO sy-msgli. " Открыть документ lo_log->add_syst( io_details = lo_details ). lo_log->popup( ). ENDFORM. |
При нажатии на «Подробно» откроется FB03 с выбранным документом.
Присоединиться к обсуждению...