📜 ⬆️ ⬇️

Another logger for SAP

Every programmer in his life should at least once write his own logger.
Popular saying
Today I would like to tell you how to use the application log in my workings, and also offer the community another bike designed to make life a little more comfortable.

So, Application Log, also known as SLG0 and SLG1 ...

SAP standard


The application log is a great help in debugging and supporting new developments, especially background tasks, web services and interfaces on the WebDynpro technology, that is, in those cases where it is not always possible or inconvenient to use the debugger. The journal is a standard SAP functionality, so it is always at your service.
')
You can view the log in transaction SLG1 :



The upper part displays the logs for the specified period, the lower part shows the messages recorded in the selected log.

Logging

Each log has two basic attributes: an object and a sub- object . This allows you to separate the entire mass of journals created in the system, by area of ​​development and specific application, for example: the Z_WEB_SERVICES object and the EXCHANGE_RATE sub-object for the service for receiving currency rates.

For maintenance of objects and sub-objects, transaction SLG0 is used.
Step 1. The entry is added in two steps: on the first screen, the object name is determined:



Step 2. Then for the new object, in the tree on the left, “Sub-objects” are selected, and a sub-object is created:



How to use it

To add logging support to your application, just use the following function modules:


By the way, BAL_DB_SAVE accepts a list of identifiers at the input and allows you to save several logs at once.

Sample code and result in SLG1 (View log)
GitHub Gist source code: z_log_test.abap



More about posts


In the previous examples, the journal is not much different from a simple text file. However, in SAP logs, a message has a larger set of properties than the date and text, and each of them can be used to filter and group records when viewing the log, some of which are shown in the diagram:



  1. Message type - this parameter determines the color of the icon when viewing the log
  2. Level of importance - entries are automatically divided into categories based on this attribute.
  3. The sorting criterion is a three character word, a sign for grouping and sorting messages
  4. The level of detail - a number from 1 to 9 inclusive, can participate in filters
  5. Additional information - an arbitrary set of parameters and a link to a function module or procedure for displaying it. It can be used, for example, to attach the HTTP server response header to a data transfer error message, or to invoke a transaction with parameters

When viewed, it looks like this.


Another logger


The more properties of messages are used, the more logging code grows, which is essentially secondary. To solve this problem, and just for the sake of convenience, developers often create helper subroutines in separate programs or write their own function modules and classes.

When designing my bike, I tried to find the optimal combination of functionality and convenience. It turned out to implement:


Using

First you need to get an instance of the object using the static method INSTANTIATE .
Arguments - object, sub-object and external identifier:

 CALL METHOD zbc_cl_log=>instantiate EXPORTING iv_object = gc_object iv_subobject = gc_subobject iv_external_id = gc_external_id RECEIVING ro_log = go_log. 

The parameter external identifier is displayed as text in a separate column of the log list and helps to find the right one with your eyes.

Writing messages to the log is done using the WRITE method:

 CALL METHOD go_log->write EXPORTING iv_type = zbc_cl_log=>info iv_text = 'Document Source (XML)' iv_class = zbc_cl_log=>class_additional_information iv_level = zbc_cl_log=>level_info iv_sort = 'XML' iv_details = gv_xml_b iv_viewer = 'ZBC_LOG_VIEWER_XML_XSTRING'. 

The level of the message filter prior to logging is determined using the THRESHOLD method, the only parameter of which can take any value from certain constants LEVEL_* or LEVEL_NO_THRESHOLD - in this case all messages will be recorded. According to my observations, there are always a lot of logs created, and sooner or later there comes a moment when their weight affects the overall system performance. Filter by level allows you to realize disabling the recording of "extra" at the moment details.

IV_DETAILS used to transfer the details of the message , and the name of the function module that is responsible for displaying this data on demand is IV_VIEWER . Inside the WRITE method, the data transmitted in IV_DETAILS TYPE ANY is serialized to XML using the ID transformation, and at the time of accessing it during viewing, the data is unpacked and transferred to the specified function module.

This approach gives rise to several features:


Example
If GV_XML_B is of type XString, then the interface of the function module will be as follows:

 FUNCTION zbc_log_viewer_xml_xstring . *"---------------------------------------------------------------------- *"*"Local Interface: *" IMPORTING *" REFERENCE(I_DATA) TYPE XSTRING *"---------------------------------------------------------------------- CALL FUNCTION 'DISPLAY_XML_STRING' EXPORTING xml_string = i_data EXCEPTIONS OTHERS = 0. ENDFUNCTION. 


Instead of conclusion

So far I have not had to try this solution on my project, and almost certainly it has bugs, shortcomings or even errors that have not yet been noticed, and I will be grateful for any comments on the code and design of the development. Sources are available on GitHub as Nugget and Slinkee files — you can install it yourself using SAPlink, the ABAP code exchange tool.

GitHub repository: https://github.com/yaruson/ZBC_LOG_UTILS
SAPlink home page: https://www.assembla.com/spaces/saplink/wiki

Source: https://habr.com/ru/post/240043/


All Articles