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:
BAL_LOG_CREATE
- creates a new log and returns its idBAL_LOG_MSG_ADD
- add a message to the log by IDBAL_DB_SAVE
- saves logs with specified identifiers in the database
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:

- Message type - this parameter determines the color of the icon when viewing the log
- Level of importance - entries are automatically divided into categories based on this attribute.
- The sorting criterion is a three character word, a sign for grouping and sorting messages
- The level of detail - a number from 1 to 9 inclusive, can participate in filters
- 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:
- Record messages from classes and just text from a string
- Separation by importance, levels of detail, setting sorting criteria
- Message filter with a specified level of detail prior to logging
- Easy way to define your own logic for displaying message details
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:
- the value supplied to the
WRITE
method must be of a dictionary or elementary type; - the browsing function module must declare a parameter of the same type;
- This parameter should be called
I_DATA
.
ExampleIf
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
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_UTILSSAPlink home page:
https://www.assembla.com/spaces/saplink/wiki