Sei sulla pagina 1di 63

Application Logging in SAP Using ABAP

This article explains how to create your own


application logging program in ABAP.
SAP provides standard functionality to write into as
well as view the application log. This article will
explain in detail how to create your own logging
function module for application logging using
standard SAP log facility. Two transaction code
related to application logging are
 SLG0 -> Used to maintain the log object
 SLG1 -> Used to view the log

Configuration step
In this step create a log object.
1. Open transaction SLG0. An information message
about cross-client table will come.
2. 2. Click the button "New Entries". Enter the name
and description of your log object (say ZTESTLOG
as object name and "Test Log" as object
description) and save.

Development Step
The following standard function modules provided
by SAP has been used to create the Z function
module for logging.
 BAL_GLB_MSG_DEFAULTS_SET
 BAL_DB_SAVE
 BAL_LOG_MSG_ADD
Here are the steps:
1. Go to transaction SE11. Create a z-structure
Z_LOG_MESSAGE having the following fields
Component Component Type
MSGTY SYMSGTY
MSG_TEXT_1 SYMSGV
MSG_TEXT_2 SYMSGV
MSG_TEXT_3 SYMSGV
MSG_TEXT_4 SYMSGV
2. Crate a message class say ZMESSAGE in
transaction SE91 and a message 999 with four
placeholder ( & ) as the text.
3. Go to transaction SE37. Create a function group
say ZLOG
4. After the function group is created, create a
function module in that group. Let is name it
ZIU_MESSAGE_LOGGING.
Import parameters:
a. I_LOG_OBJECT type BALOBJ_D -> Application
log: Object name (Application code)
b. I_EXTNUMBER type String -> Application Log:
External ID
Export parameters: None
Changing parameters: None
Tables parameters:
T_LOG_MESSAGE type Z_LOG_MESSAGE
Exceptions:
LOG_HEADER_INCONSISTENT
LOGGING_ERROR
Paste the code below as the source code
Error rendering macro 'code': Invalid value
specified for parameter 'lang'
FUNCTION ZIU_MESSAGE_LOGGING.
*"-----------------------------------
-----------------------------------
*"*"Local interface:
*" IMPORTING
*" REFERENCE(I_LOG_OBJECT) TYPE
BALOBJ_D
*" REFERENCE(I_EXTNUMBER) TYPE STRING
*" TABLES
*" T_LOG_MESSAGE STRUCTURE
Z_LOG_MESSAGE
*" EXCEPTIONS
*" LOG_HEADER_INCONSISTENT
*" LOGGING_ERROR
*"-----------------------------------
-----------------------------------

* Author :Ashim Chowdhury

* DESCRIPTION: This function module


is used insert messages in the
* application log

CONSTANTS: c_message TYPE syst-


msgid VALUE 'ZMESSAGE',
c_999 TYPE syst-msgno VALUE '999'.

DATA:
l_log_handle TYPE balloghndl,
l_s_log TYPE bal_s_log,
l_dummy TYPE string,
l_ext_no TYPE bal_s_log-extnumber,
l_s_mdef TYPE bal_s_mdef.

IF t_log_message[] IS NOT INITIAL.


l_s_log-object = i_log_object.
l_ext_no = i_extnumber.
l_s_log-extnumber = l_ext_no.

* Create the log with header data


CALL FUNCTION 'BAL_LOG_CREATE'
EXPORTING
i_s_log =
l_s_log
IMPORTING
e_log_handle =
l_log_handle
EXCEPTIONS
log_header_inconsistent = 1
OTHERS = 2.

IF sy-subrc <> 0.
CASE sy-subrc.
WHEN 1.
RAISE
log_header_inconsistent.
WHEN OTHERS.
RAISE logging_error.
ENDCASE.
ENDIF.

l_s_mdef-log_handle =
l_log_handle.

* Set the default value


CALL FUNCTION
'BAL_GLB_MSG_DEFAULTS_SET'
EXPORTING
i_s_msg_defaults = l_s_mdef
EXCEPTIONS
OTHERS = 0.

* Loop the message table and write


the messages into the log
LOOP AT t_log_message.

* Use the message type ZMESSAGE and


msg no 999
* Issue the message in a dummy
variable
MESSAGE ID c_message TYPE
t_log_message-msgty NUMBER c_999
WITH t_log_message-msg_text_1
t_log_message-msg_text_2
t_log_message-msg_text_3
t_log_message-msg_text_4
INTO l_dummy.

* The parameters set by message


statement will be used
* Add the message in the log
PERFORM msg_add.
ENDLOOP.

* save logs in the database


CALL FUNCTION 'BAL_DB_SAVE'
EXPORTING
i_save_all = 'X'
EXCEPTIONS
log_not_found = 1
save_not_allowed = 2
numbering_error = 3
OTHERS = 4.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-
msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3
sy-msgv4.
ENDIF.

ENDIF.

ENDFUNCTION.
Error rendering macro 'code': Invalid value
specified for parameter 'lang'
*------------------------------------
--------------------------------
* FORM MSG_ADD
*------------------------------------
--------------------------------
* Add the message to the log
*------------------------------------
-------------------------------*
FORM msg_add.
DATA:
l_s_msg TYPE bal_s_msg.

* define data of message for


Application Log
l_s_msg-msgty = sy-msgty.
l_s_msg-msgid = sy-msgid.
l_s_msg-msgno = sy-msgno.
l_s_msg-msgv1 = sy-msgv1.
l_s_msg-msgv2 = sy-msgv2.
l_s_msg-msgv3 = sy-msgv3.
l_s_msg-msgv4 = sy-msgv4.

* add this message to log file


* (I_LOG_HANDLE is not specified, we
want to add to the default log.
* If it does not exist we do not care
=>EXCEPTIONS log_not_found = 0)
CALL FUNCTION 'BAL_LOG_MSG_ADD'
EXPORTING
* I_LOG_HANDLE =
i_s_msg = l_s_msg
EXCEPTIONS
log_not_found = 0
OTHERS = 1.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty
NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3
sy-msgv4.
ENDIF.
ENDFORM.
Using the function module:
In your ABAP program write the following code
and use this function module
ZIU_MESSAGE_LOGGING for logging.
Error rendering macro 'code': Invalid value
specified for parameter 'lang'
* Data declaration->
* Internal table for message logging
DATA: it_log_message TYPE STANDARD
TABLE OF z_log_message,
wa_log_message TYPE z_log_message,
l_ext_number TYPE string.

Constants:
c_obj_zxiproxy TYPE balobj_d VALUE
'ZTESTLOG'.

* Now populate the internal table


with the log messages as shown below.
wa_log_message-
* msgty is the type of the message.
* E -> Error, W -> Warning, S ->
Success

* Logging code for insert message


into log
CLEAR wa_log_message.
wa_log_message-msgty = 'E'. " Can use
W or S
wa_log_message-msg_text_1 = < Message
text 1>.
wa_log_message-msg_text_2 = < Message
text 2>
wa_log_message-msg_text_3 = < Message
text 3>
wa_log_message-msg_text_4 = < Message
text 4>

* Append the message into the


internal table
APPEND wa_log_message TO
it_log_message.

At the end transfer the log message


to the system log by calling function
module ZIU_MESSAGE_LOGGING.
L_EXT_NUMBER will bt any string of
your choice.

* Function module ZIU_MESSAGE_LOGGING


will do the logging
* i_log_object is the object type (to
be configrd using txn SLG0

CALL FUNCTION 'ZIU_MESSAGE_LOGGING'


EXPORTING
i_log_object = c_obj_zxiproxy
i_extnumber = l_ext_number
TABLES
t_log_message = it_log_message
EXCEPTIONS
log_header_inconsistent = 1
logging_error = 2
OTHERS = 3.
IF sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY
NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-
MSGV4.
ENDIF.
ENDIF.
The logged messages can be viewed in
transaction SLG1. For filtering the messages use
the Object type.
 abap
 logging
 application
 snippet
 program
5 Comments

1.
Guest
Maybe additional the FM
BAL_DSP_LOG_DISPLAY and in background the
BAL_DSP_LOG_PRINT do a good job. By using
this functions you can also inform the user about
the entries, that will be written to the application
log.
o Feb 21, 2007

2.
Paul Snyman
FYI You don't need to create a custom structure to
store the messages in - SAP has provided
structure SYMSG for this purpose.
Regards,
Paul
o Apr 30, 2007

3.
Guest
If you have a registered namespace with the
"/abc/" format, why can't you use it rather than the
"x" or "y" names?
o Jun 26, 2008

4.
Former Member
Good Document.
Thanks for you help & contribution.
o Oct 19, 2012

5.
Former Member
One of the problems we encountered was when
the application log was committed in the same
SAP LUW. After the BAL_DB_SAVE you need an
implicit or explicit commit work.
If you write entries to the application log and the
calling program issues a ROLLBACK WORK or
crashes, the application log entries that have not
been committed yet will be lost. And if you commit
the application log by using explicit COMMIT
WORK statement, the updates in the calling
program are also committed.
In the past, we solved this by using RFC
DESTINATION 'NONE' or a HTTP call to force a
separate LUW.
As of WAS731, BAL_DB_SAVE has been
extended with two parameters: i_2th_connection
and i_2th_connect_commit. You can use these to
force a different LUW. I use them to commit
application log entries directly so my trace is not lost.
Note that you don't need to set up this second connection (trx DBACOCKPIT).

Using Application Log


Skip to end of metadata
 Created by Former Member, last modified
on Dec 03, 2007
Go to start of metadata
Author: Xinpeng Lin
Submitted: 2.12.2007
This Code Snippets will clarify some general
process of working with application log when
ABAP programmming. Such as creating,
adding, deleting, displaying, formatting
application logs and saving it to the database.
When we do ABAP programming,sometimes
we need to bring the situation arised at
runtime to the attention of the end users,
which are usually errors, warnings and
successful information.To do this, we can use
Application Log which is a set of Function
Modules provided by SAP for collecting
messages, saving, reading and deleting logs in
the database and displaying logs.
1.Define application log objects
Application log objects are defined in the
system. The object definition assigns a work
area. An object can be divided into sub-objects
.Logging is performed object-specifically, via
function modules.Using transaction code
SLG0, we can define our own object and
subobject.For example, object: ZTEST,
subobject: ZTEST01.
2.Create a log
Using Function Module
'BAL_LOG_CREATE', we can create a log
where all messages should be added to.
DATA: gv_log_handle TYPE balloghndl. "
Log: Log Handle
DATA: ls_log TYPE bal_s_log. "
data

* define some header data of this log


ls_log-extnumber = 'Application Log Dem
ls_log-object = 'ZTEST'.
ls_log-subobject = 'ZTEST01'.
ls_log-aldate = sy-datum.
ls_log-altime = sy-uzeit.
ls_log-aluser = sy-uname.
ls_log-alprog = sy-repid.

CALL FUNCTION 'BAL_LOG_CREATE'


EXPORTING
i_s_log = ls_log
IMPORTING
e_log_handle = gv_log_han
EXCEPTIONS
log_header_inconsistent = 1
OTHERS = 2.

IF sy-subrc <> 0.
MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBE
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-
ENDIF.
The function module 'BAL_LOG_CREATE'
returns the log handle (LOG_HANDLE,
CHAR22). The LOG_HANDLE is a globally
unique identifier (GUID) which identifies a
log uniquely. You can access this log with this
handle, e.g. to change the header data or to put
a message in the log.
3. Put a message in the log
Using Function Module
'BAL_LOG_MSG_ADD', we can add a
message into the application log.This message
is put in the log identified by the log handle
GV_LOG_HANDLE, which is mostly the
T100 information (message type, work area,
message number, the 4 message variables).
DATA: L_S_MSG TYPE BAL_S_MSG.
* define data of message for Application
L_S_MSG-MSGTY = SY-MSGTY.
L_S_MSG-MSGID = SY-MSGID.
L_S_MSG-MSGNO = SY-MSGNO.
L_S_MSG-MSGV1 = SY-MSGV1.
L_S_MSG-MSGV2 = SY-MSGV2.
L_S_MSG-MSGV3 = SY-MSGV3.
L_S_MSG-MSGV4 = SY-MSGV4.

CALL FUNCTION 'BAL_LOG_MSG_ADD'


EXPORTING
i_log_handle = gv_log_h
i_s_msg = l_s_msg
EXCEPTIONS
log_not_found = 1
msg_inconsistent = 2
log_is_full = 3
OTHERS = 4.

IF sy-subrc <> 0.
MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBE
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-
ENDIF.

4. Display log
Using Function Module
'BAL_DSP_LOG_DISPLAY', we can display
the collected messages. This function module
can be called without parameters. All
messages in memory are displayed in a
standard format (this standard format is used
e.g. in the transaction SLG1).
CALL FUNCTION 'BAL_DSP_LOG_DISPLAY'
EXCEPTIONS
PROFILE_INCONSISTENT = 1
INTERNAL_ERROR = 2
NO_DATA_AVAILABLE = 3
NO_AUTHORITY = 4
OTHERS = 5.

IF sy-subrc <> 0.
MESSAGE ID SY-MSGID TYPE SY-MSGTY NU
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 S
ENDIF.

5. Save logs in the database


Using Function Module 'BAL_DB_SAVE, we
can save all memory data in the database. The
importing parameter I_SAVE_ALL should be
set as 'X'.
CALL FUNCTION 'BAL_DB_SAVE'
EXPORTING
i_save_all = 'X'
EXCEPTIONS
LOG_NOT_FOUND = 1
SAVE_NOT_ALLOWED = 2
NUMBERING_ERROR = 3
OTHERS = 4.

IF sy-subrc <> 0.
MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMB
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-
ENDIF.

6. Find logs in the database


Using Function Module 'BAL_DB_SEARCH,
we can find logs in the database. We should
pass the log header filter criteria (structure
BAL_S_LFIL), and a table of log headers
(structure BALHDR) which satisfy the criteria
is returned.
DATA: gr_object TYPE bal_s_obj.
DATA: gr_extnumber TYPE bal_s_extn.
DATA: gs_log_filter TYPE bal_s_lfil.
DATA: gt_log_header TYPE balhdr_t.

* create a filter with all relevant crit


gr_object-sign = 'I'.
gr_object-option = 'EQ'.
gr_object-low = 'ZTEST'.
APPEND gr_object TO gs_log_filter-object

gr_extnumber-sign = 'I'.
gr_extnumber-option = 'EQ'.
gr_extnumber-low = 'Application Log D
APPEND gr_extnumber TO gs_log_filter-ext
* search on DB for these logs
CALL FUNCTION 'BAL_DB_SEARCH'
EXPORTING
i_s_log_filter = gs_log_filter
IMPORTING
e_t_log_header = gt_log_header
EXCEPTIONS
LOG_NOT_FOUND = 1
NO_FILTER_CRITERIA = 2.

IF sy-subrc <> 0.
MESSAGE ID SY-MSGID TYPE SY-MSGTY NU
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-M
ENDIF.

7. Load logs from the database


Using Function Module 'BAL_DB_LOAD',
we can load logs from the database. By setting
the importing parameter
'I_T_LOG_HEADER' with the return values
from function module 'BAL_DB_SEARCH',
we can specify which logs are to be loaded in
memory.
DATA: gt_log_header TYPE balhdr_t.

* load these messages into memory


CALL FUNCTION 'BAL_DB_LOAD'
EXPORTING
i_t_log_header = gt_log_header
EXCEPTIONS
NO_LOGS_SPECIFIED = 1
LOG_NOT_FOUND = 2
LOG_ALREADY_LOADED = 3.

IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NU
WITH sy-msgv1 sy-msgv2 sy-msgv3 s
ENDIF.
8. Read log from database
Using Function Module
'APPL_LOG_READ_DB', we can read logs
from database if we want to analyze the log
ourselves. By setting the importing parameter
OBJECT or SUBOBJECT etc., we can specify
which logs are to be read.
DATA: P_NUMBER_OF_LOGS LIKE SY-TABIX.
* Log header data
DATA: BEGIN OF P_HEADER_DATA_TAB OCCURS
INCLUDE STRUCTURE BALHDR.
DATA: END OF P_HEADER_DATA_TAB.
* Log parameters
DATA: BEGIN OF P_HEADER_PARA_TAB OCCURS
INCLUDE STRUCTURE BALHDRP.
DATA: END OF P_HEADER_PARA_TAB.
* Log messages
DATA: BEGIN OF P_MESSAGE_TAB OCCURS 0.
INCLUDE STRUCTURE BALM.
DATA: END OF P_MESSAGE_TAB.
* Message parameters
DATA: BEGIN OF P_MESSAGE_PARA_TAB OCCURS
INCLUDE STRUCTURE BALMP.
DATA: END OF P_MESSAGE_PARA_TAB.

CALL FUNCTION 'APPL_LOG_READ_DB'


EXPORTING
OBJECT = 'ZTEST'
SUBOBJECT = 'ZTEST01'
EXTERNAL_NUMBER = 'Application Log D
IMPORTING
NUMBER_OF_LOGS = P_NUMBER_OF_LOGS
TABLES
HEADER_DATA = P_HEADER_DATA_T
HEADER_PARAMETERS = P_HEADER_PARA_T
MESSAGES = P_MESSAGE_TAB
MESSAGE_PARAMETERS = P_MESSAGE_PARA_
9. Delete logs from the database
Using Function Module 'BAL_DB_DELETE',
we can delete logs from the application. By
setting the importing parameter
I_T_LOGS_TO_DELETE ' with the return
values from function module
'BAL_DB_SEARCH', we can specify which
logs are to be loaded in memory.
DATA: gt_log_header TYPE balhdr_t.

CALL FUNCTION 'BAL_DB_DELETE'


EXPORTING
I_T_LOGS_TO_DELETE = gt_log_header
EXCEPTIONS
NO_LOGS_SPECIFIED = 1
OTHERS = 2.

IF sy-subrc <> 0.
MESSAGE ID SY-MSGID TYPE SY-MSGTY NU
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 S
ENDIF.

10. Formatting Log Display


We can use the display profile (structure
BAL_S_PROF) to specifiy how the logs are
displayed. It contains field catalogs which
describe which fields are to be in the list and
in the levels of the navigation tree.
Application Log provides display profiles
which you can get with the follwoing function
modules:
BAL_DSP_PROFILE_DETLEVEL_GET
BAL_DSP_PROFILE_NO_TREE_GET
BAL_DSP_PROFILE_POPUP_GET
BAL_DSP_PROFILE_SINGLE_LOG_GET
BAL_DSP_PROFILE_STANDARD_GET
If no display profile is specified, the standard
display profile from transaction SLG1 is used.
Let us take a look at these function modules
one by one.
o BAL_DSP_PROFILE_DETLEVEL_GET
The messages are inserted into the navigation
tree. The tree-level in which they appear is
determined by field DETLEVEL of structure
BAL_S_MSG (which is used when adding a
message to the log, eg. with
BAL_LOG_MSG_ADD).
o BAL_DSP_PROFILE_NO_TREE_GET:
Presentation of a log whithout a navigation
tree next to it. This kind of presentation is
usefull when there are not that many messages
and therefore a navigation tree would make no
sense.
o BAL_DSP_PROFILE_POPUP_GET:
Presentation of a log in a popup. This is
similar to the previous point. No tree is shown
(does not make sense in a popup, not enough
space).
o
BAL_DSP_PROFILE_SINGLE_LOG_GET:
the 'standard' profile to display one log:
In the tree the log header is displayed. One
level below there are different categories for
the problem classes of the messages. The user
can easily select for example only
important messages. All messages of the log
are displayed at once on the right side.
This profile is used in transaction SLG1 when
only one log has been selected.
o BAL_DSP_PROFILE_STANDARD_GET:
The 'standard' profile to display many logs.
This is similar to the previous profile, the only
diffrences are:
 On the right side the overview of log headers
is not expanded down to the problem class
level.
 No messages ar shown initially. The user has
to choose a log (or a part of a log, e.g. the
very important messages of a log)
This profile is used in transaction SLG1 when
more than one log has been selected.
As the process of these function module is
similar, let us take function module
'BAL_DSP_PROFILE_DETLEVEL_GET' as
a example.
DATA: l_s_display_profile TYPE bal_s_pro

* get a prepared profile


CALL FUNCTION 'BAL_DSP_PROFILE_DETLEVEL_
IMPORTING
e_s_display_profile = l_s_display_pr
EXCEPTIONS
OTHERS = 1.

IF sy-subrc <> 0.
MESSAGE ID SY-MSGID TYPE SY-MSGTY NU
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 S
ENDIF.

* use grid for display if wanted


l_s_display_profile-use_grid =
* set report to allow saving of variants
l_s_display_profile-disvariant-report =
* when you use also other ALV lists in y
* please specify a handle to distinguish
display
* variants of these different lists, e.g
l_s_display_profile-disvariant-handle =

* call display function module


CALL FUNCTION 'BAL_DSP_LOG_DISPLAY'
EXPORTING
i_s_display_profile = l_s_display_pr
EXCEPTIONS
PROFILE_INCONSISTENT = 1
INTERNAL_ERROR = 2
NO_DATA_AVAILABLE = 3
NO_AUTHORITY = 4
OTHERS = 5.

IF sy-subrc <> 0.
MESSAGE ID SY-MSGID TYPE SY-MSGTY NU
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 S
ENDIF.
11. Callback Routine
Using callback routines, we can affect the
program flow at various events in Application
Log. Callback routines can be FORM routines
or function modules.
The following is a example which will popup
a message whenever a message is sent to the
application log.
DATA: g_s_configuration TYPE bal_s_conf.
DATA: g_s_log TYPE bal_s_log.
DATA: g_s_msg TYPE bal_s_msg.

* define callback to display a message w


PERFORM bal_callback_display_set
CHANGING
g_s_configuration.

* set this configuration


CALL FUNCTION 'BAL_GLB_CONFIG_SET'
EXPORTING
i_s_configuration = g_s_configuratio
EXCEPTIONS
OTHERS = 0.

* create log
CALL FUNCTION 'BAL_LOG_CREATE'
EXPORTING
i_s_log = g_s_log
EXCEPTIONS
OTHERS = 0.

DO 3 TIMES.
g_s_msg-msgid = 'BL'.
g_s_msg-msgno = 326.
g_s_msg-msgty = 'E'.

* create message
CALL FUNCTION 'BAL_LOG_MSG_ADD'
EXPORTING
i_s_msg = g_s_msg
EXCEPTIONS
OTHERS = 0.
ENDDO.

* display log
CALL FUNCTION 'BAL_DSP_LOG_DISPLAY'
EXCEPTIONS
OTHERS = 1.

IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMB
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-
ENDIF.

*---------------------------------------
---------------*
* FORM BAL_CALLBACK_DISPLAY_SET
*---------------------------------------
---------------*
FORM bal_callback_display_set
CHANGING
c_s_configuration TYPE bal_s_conf.

* we want very important messages to occ


immediately
c_s_configuration-display-callback-usere
c_s_configuration-display-callback-usere
repid.
c_s_configuration-display-callback-usere
= 'BAL_CALLBACK_DISPLAY'.

ENDFORM. "bal_callback_display_set
*---------------------------------------
---------------*
* FORM BAL_CALLBACK_DISPLAY
*---------------------------------------
---------------*
FORM bal_callback_display
USING
i_s_msg TYPE bal_s_msg.

* issue a message
MESSAGE i325(bl) WITH 'BAL_CALLBACK_DI

ENDFORM. "bal_callback_display
 abap
 application
 snippet
 tutorial
 log
3 Comments
1.
Former Member
Thank you very much.
I made a application log...^^
Best regards.
o Feb 08, 2008
2.
Guest
Hi,
Good Material. I had created an appln log for
our ISU process. But we used MSG_*
Function modules.
Any idea what is the difference between
BAL_* and MSG_* FMs ? tried to search, but
could find much.
Thanks.
Regards
Megha
o Aug 09, 2010
3.
Former Member

Hi.
What if I have a standard FM that updates DB,
but does not return error/warning/success
messages?
Where is the log stored in such cases? How
can we access it?

It’s been always a headache when customer raises a message and you are not sure what might
have gone wrong!!!
At this point if you have application logging in place it can be really helpful to trace and check
which code might have triggered the issue.
Application logging can be useful for the below scenarios too:
1…When you want to record the progress of the execution of an application so that you can
reconstruct it later if necessary
2…when you are not sure/not able to debug a code (foreground/background) and you want to
drill down the error cause. In this case you can easily check the application log and decide the
exact location where the problem can be.

So let’s start how you can create an application logging.


Transaction code: SLG0 is used to create an object which is used to identify your logs.
So here I have created an application log Object named: ZHR_ENC.

And a Sub-object ZHRENC_SUB.


Its like: I want to create an application log for COUNTRY management. And inside the countries
whenever application is related to a particular state. I create sub-object based on the states.
Once you are done with the creation of the Object and sub object it’s time to put the code
which will actually create the application logs.
You can write the below code to your enhancements/User-Exit/reports (any custom code) so
that when it is executed logging is done.
(For testing purpose just copy the below code in Report program ZTST_APPL_LOG)

*&———————————————————————*
*& Report ZTST_APPL_LOG
*&
*&———————————————————————*
*&
*&
*&———————————————————————*
REPORT ZTST_APPL_LOG.
type-pools: abap.
data: l_log_handle type balloghndl,
l_timestamp type tzntstmps,
l_timezone type timezone value ‘UTC’,
l_str_log type bal_s_log,
l_str_balmsg type bal_s_msg,
l_str_message type bapiret2,
l_msg_logged type boolean,
l_tab_messages type bapiret2_t.
*-Building messages
*–Use your own message which you want to Display in the log
do 1 times.
call function ‘BALW_BAPIRETURN_GET2’
exporting
type = ‘E’
cl = ‘BPFS’
number = ‘006’
importing
return = l_str_message.
append l_str_message to l_tab_messages.
clear l_str_message.
enddo.
*-Logging messages
convert date sy–datum time sy–uzeit
into time stamp l_timestamp time zone l_timezone.
l_str_log–extnumber = l_timestamp.
condense l_str_log–extnumber.
l_str_log–object = ‘ZHR_ENC’.
l_str_log–subobject = ‘ZHRENC_SUB’.
l_str_log–aldate_del = sy–datum + 5.
call function ‘BAL_LOG_CREATE’
exporting
i_s_log = l_str_log
importing
e_log_handle = l_log_handle
exceptions
log_header_inconsistent = 1
others = 2.
if sy–subrc <> 0.
message id sy–msgid type sy–msgty number sy–msgno
with sy–msgv1 sy–msgv2 sy–msgv3 sy–msgv4 into l_str_message–message.
write: ‘Type’,sy–msgty, ‘Message’,l_str_message–message.
else.
loop at l_tab_messages into l_str_message.
move: l_str_message–type to l_str_balmsg–msgty,
l_str_message–id to l_str_balmsg–msgid,
l_str_message–number to l_str_balmsg–msgno,
l_str_message–message_v1 to l_str_balmsg–msgv1,
l_str_message–message_v2 to l_str_balmsg–msgv2,
l_str_message–message_v3 to l_str_balmsg–msgv3,
l_str_message–message_v4 to l_str_balmsg–msgv4.
call function ‘BAL_LOG_MSG_ADD’
exporting
i_log_handle = l_log_handle
i_s_msg = l_str_balmsg
importing
e_msg_was_logged = l_msg_logged
exceptions
log_not_found = 1
msg_inconsistent = 2
log_is_full = 3
others = 4.
if sy–subrc <> 0.
message id sy–msgid type sy–msgty number sy–msgno
with sy–msgv1 sy–msgv2 sy–msgv3 sy–msgv4 into l_str_message–message.
write: ‘Type’,sy–msgty, ‘Message’,l_str_message–message.
endif.
endloop.
if sy–subrc eq 0.
call function ‘BAL_DB_SAVE’
exporting
i_save_all = abap_true
exceptions
log_not_found = 1
save_not_allowed = 2
numbering_error = 3
others = 4.
if sy–subrc <> 0.
message id sy–msgid type sy–msgty number sy–msgno
with sy–msgv1 sy–msgv2 sy–msgv3 sy–msgv4 into l_str_message–message.
write: ‘Type’,sy–msgty, ‘Message’,l_str_message–message.
else.
write: ‘Messages Saved in the log’.
endif.
endif.
endif.
write : ‘done with log number’,l_str_log–extnumber.

In the above code three function modules are doing the full job.
‘BAL_LOG_CREATE’ it creates the application logging object
‘BAL_LOG_MSG_ADD’ it adds the messages to your application logging object/sub-object
‘BAL_DB_SAVE’ saves the messages into to database.
Note: Here I have used the standard message class BPFS (message number: 006).Incase if it’s
not available in your system create new one using Transaction code SE91 or reuse any existing
message.
Execute the created report .You can use the transaction Code: SLG1 to monitor the application
logging based on the object.
So now when customers raise the Ticket the first step you can do is. Check the application
logging in the production and you will have clear picture what might have been gone wrong.
Alert Moderator

1 Comment
You must be Logged on to comment or reply to a post.

1. Former MemberJune 6, 2013 at 12:29 pm

Thanks for sharing

like (0)

Application Log
Das Application Log ist eine Standardlösung von SAP, um sehr komfortable Möglichkeit Meldungen
(Fehler, Erfolgsmeldungen etc.) lokal (temporär) oder persistent (dauerhaft) zu speichern und darzustellen.

Um übermäßig große Tabellengrößen zu verhindern, sollten Application Logs auf der Datenbank in
regelmäßigen Abständen gelöscht werden, z. B. im Monatsrhythmus.
Inhaltsverzeichnis
[Verbergen]

 1 Funktionsbausteine

 2 Dokumentation in SAP

 3 Application Log Transaktionen

o 3.1 SLG0 (Objekte und Unterobjekte pflegen)

o 3.2 SLG1 (Protokoll anzeigen)

o 3.3 SLG2 (Protokoll löschen)

o 3.4 SLGD (Protokollanzeige mit Selektionsbild)

o 3.5 SBAL_TEST_REPORT (Test Application Log)

o 3.6 SLGN (Pflege Nummernkreise)

 4 Testprogramm SBAL_DEMO_01

o 4.1 Grundlagen

o 4.2 Coding

 5 Application Log mit Zusatzfeldern (Kontext)


 6 Tabellen

 7 YouTube

 8 Web-Links

 9 Literatur
Funktionsbausteine

 BAL_LOG_CREATE

 BAL_LOG_MSG_ADD

 BAL_DSP_LOG_DISPLAY
Dokumentation in SAP

 Programm = SBAL_DOCUMENTATION

 Transaktion = SBAL_DOCU_DISPLAY
Application Log Transaktionen
SLG0 (Objekte und Unterobjekte pflegen)

 In der Transaktion werden die Objekte gepflegt. Optional können einem Objekt auch Unterobjekte
zugewiesen werden, um eine feinere Untergliederung eines Objekts zu haben.
SLG1 (Protokoll anzeigen)

 Transaktion SLG1
SLG2 (Protokoll löschen)

 Transaktion SLG2
SLGD (Protokollanzeige mit Selektionsbild)

 Transaktion SLGD = Report SBAL_DISPLAY_2


SBAL_TEST_REPORT (Test Application Log)

 Transaktion SBAL_TEST_REPORT
SLGN (Pflege Nummernkreise)

 Transaktion SLGN
Testprogramm SBAL_DEMO_01
Grundlagen

Sobald eine Meldung mit dem Typ E = Error in der Liste steht, wird die Problemklasse rot dargestellt, damit
man schon auf den ersten Blick erkennt, dass eine Einzelmeldung Aufmerksamkeit erfordert.
Es können auch Meldungen ausgeblendet werden. Hier wurden die Erfolgsmeldungen ausgeblendet,
sodass nur die Warnungen und Fehler verbleiben.
Coding

report SBAL_DEMO_01 message-id bl.

***********************************************************************
***********************************************************************
* REPORT SBAL_DEMO_01
*
* This report shows a simple example how the application log function
* modules could be used.
* For this purpose this reports simulates the check of a flight
* (specified by carrier, connection ID and flight date).
* A log is created with BAL_LOG_CREATE.
* Messages are sent to this log using BAL_LOG_MSG_ADD
* (see form msg_add).
* Finally the log is displayed with BAL_DSP_LOG_DISPLAY.
* Nothing is saved on the database.
*
***********************************************************************
***********************************************************************

***********************************************************************
******************** SELECTION SCREEN *********************************
***********************************************************************
selection-screen begin of block b01 with frame title text-001.
parameters:
p_carrid type bal_carrid default 'SF',
p_connid type bal_connid default '0003',
p_fldate type bal_fldate default sy-datum.
selection-screen end of block b01.

***********************************************************************
******************** CONSTANTS, TYPES, DATA ***************************
***********************************************************************
set extended check off.
include sbal_constants.
set extended check on.
data:
g_s_log type bal_s_log,
g_value type i,
g_passenger type bal_custmr,
g_everything_ok(1) type c,
g_dummy type c. "#EC NEEDED

***********************************************************************
************************ MAIN PROGRAM *********************************
***********************************************************************
end-of-selection.

***************************************************************
* create a log where all messages should be added to
***************************************************************
* define some header data of this log
g_s_log-extnumber = 'Application Log Demo'. "#EC NOTEXT
g_s_log-aluser = sy-uname.
g_s_log-alprog = sy-repid.
* ... see structure BAL_S_LOG for further data ...
* ... which can be added to a log header ...
* create a log
call function 'BAL_LOG_CREATE'
exporting
i_s_log = g_s_log
exceptions
others = 1.
if sy-subrc <> 0.
message id sy-msgid type sy-msgty number sy-msgno
with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
endif.

***************************************************************
* do something to check if flight is allowed
***************************************************************
* ... result is negative:
* 305(BL): 'Flight allowance does not exist'
message e305 into g_dummy.
perform msg_add using probclass_very_high.

***************************************************************
* do something to check if weight is OK
***************************************************************
* ... result is negative:
* 301(BL): 'Maximum weigth is exceeded'
message e301(bl) into g_dummy.
perform msg_add using probclass_very_high.

***************************************************************
* do something to check if there are too many passengers
***************************************************************
* ... result is negative:
* 302(BL): 'Flight is overbooked'
message e302(bl) into g_dummy.
perform msg_add using probclass_high.

***************************************************************
* do something to check if airplane is available
***************************************************************
* ... result is negative:
* 303(BL): 'Airplane &1 is not available'
message id 'BL' type 'E' number 303 with '747-400' into g_dummy.
perform msg_add using probclass_high.

***************************************************************
* do something to check if the crew is OK
***************************************************************
* ... result is negative ....
* 308(BL): 'Stewardess &1 is ill and therefore not available'
message e308(bl) with 'JONES' into g_dummy.
perform msg_add using probclass_high.

***************************************************************
* do something to check if the crew has enough time to sleep
***************************************************************
* ... result is negative:
* 309(BL): 'Relax phases for the crew are too short'
message e309(bl) into g_dummy.
perform msg_add using probclass_high.

***************************************************************
* check passenger list
***************************************************************
do 60 times.

* derive passenger number


write sy-index to g_passenger left-justified.

* assumption: everything is OK for this passenger


g_everything_ok = 'X'.
***************************************************************
* non-smoker seat available ?
***************************************************************
* ... for some passengers a non-smoker seat is not available:
if g_passenger = 22 or g_passenger = 34 or g_passenger = 66.
* 310(BL): 'Passenger &1 can only be booked on smoker seat'
message e310(bl) with g_passenger into g_dummy.
perform msg_add using probclass_medium.
g_everything_ok = ' '.
endif.

***************************************************************
* is payment checked ?
***************************************************************
* ... for some passengers payment is not yet checked:
g_value = sy-index mod 16.
if g_value = 0.
* 304(BL): 'Payment for passenger &1 is not yet checked'
message w304(bl) with g_passenger into g_dummy.
perform msg_add using probclass_medium.
g_everything_ok = ' '.
else.
* 306(BL): 'Payment for passenger &1 is done'
message s306(bl) with g_passenger into g_dummy.
perform msg_add using probclass_medium.
endif.

***************************************************************
* did passenger cancel his flight ?
***************************************************************
* ... some passnegers have cancelled their flight:
g_value = sy-index mod 26.
if g_value = 0.
* 307(BL): 'Flight for passenger &1 was cancelled'
message s307(bl) with g_passenger into g_dummy.
perform msg_add using probclass_medium.
g_everything_ok = ' '.
endif.

***************************************************************
* Everything is OK
***************************************************************
* ... when no errors occured everything is OK for this passenger:
if g_everything_ok = 'X'.
* 311(BL): 'Booked flight for passenger &1 is checked and OK'
message s311(bl) with g_passenger into g_dummy.
perform msg_add using probclass_low.
endif.

enddo.

***************************************************************
* display log file
***************************************************************
* - we do not specify a display profile I_S_DISPLAY_PROFILE
* since we want to use the standard profile
* - we also do not specify any filter (I_S_LOG_FILTER, ...
* I_T_MSG_HANDLE) since we want to display all messages available
call function 'BAL_DSP_LOG_DISPLAY'
* EXPORTING
* I_S_LOG_FILTER =
* I_T_LOG_CONTEXT_FILTER =
* I_S_MSG_FILTER =
* I_T_MSG_CONTEXT_FILTER =
* I_T_LOG_HANDLE =
* I_T_MSG_HANDLE =
* I_S_DISPLAY_PROFILE =
* I_AMODAL = ' '
exceptions
others = 1.
if sy-subrc <> 0.
message id sy-msgid type 'S' number sy-msgno
with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
endif.

***********************************************************************
****************** FORMS *********************************************
***********************************************************************
*--------------------------------------------------------------------
* FORM MSG_ADD
*--------------------------------------------------------------------
form msg_add using value(i_probclass) type bal_s_msg-probclass.
data:
l_s_msg type bal_s_msg.

* define data of message for Application Log


l_s_msg-msgty = sy-msgty.
l_s_msg-msgid = sy-msgid.
l_s_msg-msgno = sy-msgno.
l_s_msg-msgv1 = sy-msgv1.
l_s_msg-msgv2 = sy-msgv2.
l_s_msg-msgv3 = sy-msgv3.
l_s_msg-msgv4 = sy-msgv4.
l_s_msg-probclass = i_probclass.
* ... see structure BAL_S_LOG or report SBAL_DEMO_02 for ...
* ... further data which can be added to a message ...
* add this message to log file
* we do not specify I_LOG_HANDLE since we want to add this message
* to the default log. If it does not exist we do not care
* (EXCEPTIONS log_not_found = 0).
call function 'BAL_LOG_MSG_ADD'
exporting
i_s_msg = l_s_msg
* I_LOG_HANDLE =
exceptions
log_not_found = 0
others = 1.
if sy-subrc <> 0.
message id sy-msgid type sy-msgty number sy-msgno
with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
endif.

endform.

Application Log mit Zusatzfeldern (Kontext)

 Der Application Log kann auch um zusätzliche Felder angereichert werden

 Beispielreport = SBAL_DEMO_02

Siehe auch Tricktresor: Application Log mit Kontext

Tabellen

In this tutorial we will show how to create, view and delete application log using transaction
SLG0, SLG1 and SLG2 respectively. The demo program below can be used to populate the
application log.
X
by Counterflix
Please note that this type of application log comes handy when we want to add a log to proxy
interfaces. Message in this type of application log can be viewed any time.
The following main transactions are used for application log:
 SLG0 : To create log ‘Object’ and ‘Sub Object’
 SLG1 : To display the application log entries
 SLG2 : To delete the application log entries
Step 1 – Create Application Using SLG0:
The first step is to create the application log in transaction ‘SLG0’ before we can populate the
log via an ABAP program. In ‘SLG0’ create an ‘Object’ together with its ‘Sub Object’ using
the following steps:
 Create the object ‘ZOBJ001’

 Create the sub object ‘ZSUBOBJ001’ (same steps as when creating the object)

 Save

Step 2 – Create ABAP program to populate the Application Log:


Please find below a sample program which demonstrate how to populate the application log
created in step 1.

1 REPORT ztestapplog.
2 *&--------------------------------------------------------------------&*
3 *& Program Description: &*
4 *& ----------------------- &*
5 *& This demo program demonstrate how to create application log via &*
6 *& transaction code 'SLG0' and display the log via 'SLG1'. &*
7 *& &*
8 *& Author: ABAPCOOKBOOK &*
9 *& Website: www.abapcookbook.com &*
10 ************************************************************************
11
12 ************************************************************************
13 * DATA DECLARATIONS *
14 ************************************************************************
15 *Constants:
16 CONSTANTS:
17 gc_object TYPE bal_s_log-object VALUE 'ZOBJ001',
18 gc_subobject TYPE bal_s_log-subobject VALUE 'ZSUBOBJ001',
19 gc_message_id TYPE bapiret2-id VALUE 'V1',
20 gc_msgno1 TYPE bapiret2-number VALUE '091',
21 gc_success TYPE c VALUE 'S',
22 gc_error TYPE c VALUE 'E',
23 gc_detail_level1 TYPE c VALUE '1',
24 gc_problem_class_important TYPE c VALUE '2',
25 gc_probclass_medium TYPE bal_s_msg-probclass VALUE '3',
26 gc_probclass_low TYPE bal_s_msg-probclass VALUE '4',
27 gc_problem_class_other TYPE c VALUE ''.
28
29 *Variables:
30 DATA:
31 gv_log_handle TYPE balloghndl,
32 gv_msgv1 TYPE symsgv.
33
34
35 ************************************************************************
36 * CREATE LOG. *
37 ************************************************************************
38 *IMPORTANT: Make sure the object 'ZOBJ001' and sub-object 'ZOBJ001' has
39 * been created in transaction 'SLG0'. Log can be deleted via
40 * transaction 'SLG2'.
41
42 * The log can be viewed via transaction 'SLG1' using
43 * the object 'ZOBJ001' and sub-object 'ZOBJ001'.
44
45 *Create the application log.
46 PERFORM f_create_bal_log USING gv_log_handle.
47
48
49 ************************************************************************
50 * ADD MESSAGE TO LOG. *
51 ************************************************************************
52 *This is a test condition to add a message.
53 IF 1 NE 2.
54
55 * Typecasting the date.
56 gv_msgv1 = sy-datum.
57
58 * Add a message to the application log.
59 * Message: 'Date & is not valid'
60 PERFORM f_add_msg_to_log USING gv_log_handle " Log Handler
61 gc_problem_class_important " Class Problem Level
62 gc_error " Error Message
63 gc_message_id " Message Class
64 gc_msgno1 " Message Number
65 gv_msgv1 " Message Dynamic Content(&) 1
66 space " Message Dynamic Content(&) 2 (Empty)
67 space " Message Dynamic Content(&) 3 (Empty)
68 space " Message Dynamic Content(&) 4 (Empty)
69 gc_detail_level1. " Application Detail Level
70
71 ENDIF.
72
73 ************************************************************************
74 * SAVE LOG. *
75 ************************************************************************
76 *At the end of all operation, save the application log.
77 *The log can be viewed via transaction 'SLG1' using
78 *the object 'ZOBJ001' and sub-object 'ZOBJ001'.
79 PERFORM f_save_bal_log USING gv_log_handle.
80
81
82 ************************************************************************
83 * ROUTINES: *
84 ************************************************************************
85
86 *----------------------------------------------------------------------*
87 * Sub routine to create the application log for error logging *
88 * purposes. *
89 *----------------------------------------------------------------------*
90 FORM f_create_bal_log USING pe_log_handle TYPE balloghndl.
91 *----------------------------------------------------------------------*
92 * Local data declarations.
93 * Structures.
94 DATA:
95 lst_log TYPE bal_s_log.
96
97 * Defining some header data of the application log.
98 lst_log-aldate = sy-datum.
99 lst_log-altime = sy-uzeit.
100 lst_log-aluser = sy-uname.
101 lst_log-alprog = sy-repid.
102 lst_log-object = gc_object.
103 lst_log-subobject = gc_subobject.
104
105 * Creationg the application log.
106 CALL FUNCTION 'BAL_LOG_CREATE'
107 EXPORTING
108 i_s_log = lst_log
109 IMPORTING
110 e_log_handle = pe_log_handle
111 EXCEPTIONS
112 OTHERS = 1.
113 * Not necessary to cater for this exception.
114
115 ENDFORM.
116
117
118 *----------------------------------------------------------------------*
119 * Sub routine to add a message to the processing log. *
120 *----------------------------------------------------------------------*
121 FORM f_add_msg_to_log USING pi_log_handle TYPE balloghndl
122 pi_probclass TYPE bal_s_msg-probclass
123 pi_msgty TYPE bal_s_msg-msgty
124 pi_msgid TYPE bal_s_msg-msgid
125 pi_msgno TYPE bal_s_msg-msgno
126 pi_msgv1 TYPE bal_s_msg-msgv1
127 pi_msgv2 TYPE bal_s_msg-msgv2
128 pi_msgv3 TYPE bal_s_msg-msgv3
129 pi_msgv4 TYPE bal_s_msg-msgv4
130 pi_detlevel TYPE bal_s_msg-detlevel.
131 *----------------------------------------------------------------------*
132 * Structures:
133 DATA:
134 lst_ballog_msg TYPE bal_s_msg.
135
136 * Defining data of message for the application log.
137 lst_ballog_msg-probclass = pi_probclass.
138 lst_ballog_msg-msgty = pi_msgty.
139 lst_ballog_msg-msgid = pi_msgid.
140 lst_ballog_msg-msgno = pi_msgno.
141 lst_ballog_msg-msgv1 = pi_msgv1.
142 lst_ballog_msg-msgv2 = pi_msgv2.
143 lst_ballog_msg-msgv3 = pi_msgv3.
144 lst_ballog_msg-msgv4 = pi_msgv4.
145 lst_ballog_msg-detlevel = pi_detlevel.
146
147 * Adding this message to log file.
148 CALL FUNCTION 'BAL_LOG_MSG_ADD'
149 EXPORTING
150 i_log_handle = pi_log_handle
151 i_s_msg = lst_ballog_msg
152 EXCEPTIONS
153 log_not_found = 0
154 OTHERS = 1.
155 * Not necessary to cater for these exceptions.
156
157 ENDFORM.
158
159
160 *----------------------------------------------------------------------*
161 * Sub routine to save the application log to database. *
162 *----------------------------------------------------------------------*
163 FORM f_save_bal_log USING pi_log_handle TYPE balloghndl.
164 *----------------------------------------------------------------------*
165 * Internal Tables:
166 DATA:
167 lt_loghandle TYPE bal_t_logh.
168
169 * Append the log handler to an internal table for saving purposes.
170 APPEND pi_log_handle TO lt_loghandle.
171
172 * Saving the application log.
173 CALL FUNCTION 'BAL_DB_SAVE'
174 EXPORTING
175 i_t_log_handle = lt_loghandle
176 EXCEPTIONS
177 log_not_found = 1
178 save_not_allowed = 2
179 numbering_error = 3
180 error_message = 4
181 OTHERS = 5.
182 * Not necessary to cater for these exceptions.
183
184 ENDFORM. "F_SAVE_BAL_LOG
Step 3 – Displaying application log in SLG1:
Execute the above program, an entry will be added to the application log. This log entry can
be viewed via transaction ‘SLG1’.
X
by Counterflix
In transaction, please enter the object ‘ZOBJ001′ and sub object ‘ZSUBOBJ001’ (created in
step 1) and execute.
The following log will be displayed.

Step 4 – Delete log entries in SLG2:


Finally, log entries can be deleted via transaction code ‘SLG2’.

Voila hope this helps. You can also refer to this tutorial on how to display application
log automatically in a program.

abapapplication logcodecreate logdisplay application log in SLG1logsample programsapSLG0SLG1SLG2Tutorial


Share this post
Related posts
Solve Error ‘File Has Already Been Loaded’ in FEBC
June 22, 2017

How To Quickly Save ABAP Code To Your Computer


June 2, 2017

SAP ABAP Message Types


May 30, 2017

Back Button Not Working in GUI-STATUS/PF-STATUS


May 29, 2017

Potrebbero piacerti anche