-
Notifications
You must be signed in to change notification settings - Fork 0
Add Data Container
Data containers can be used to attach virtually any kind of data to a log message. The data will accessible in SLG1 while displaying a log.
Depending on the type of the data container, it might display detail information or navigate somewhere.
The screenshot shows a list of data containers, that have been attached to a single log message.
All data containers need to implement the interface /USI/IF_BAL_DATA_CONTAINER or - to be even more precise - one of its comprehensive interfaces.
Interface | Purpose |
---|---|
/USI/IF_BAL_DATA_CONTAINER | Defines the methods that the data container will need to interact with the rest of the API. It does NOT contain a method to do anything with the internally stored data. Such methods will be added by the comprehensive interfaces. |
/USI/IF_BAL_DATA_CONTAINER_NAV | For data containers, that are navigating somewhere (e.g. jump to a source code position) |
/USI/IF_BAL_DATA_CONTAINER_RND | For data containers, that will render their data using a GUI_CONTAINER provided by the API |
Different types of containers may have differnt cardinalities:
- [0-1] e.g. source code position of an exception
- [0-n] e.g. internal tables
This method has to return ABAP_TRUE
for cardinality [0-n] and ABAP_FALSE
for [0-1].
Has to return the exact classname of the implementing class.
CAUTION: The classname is used as a key value by the persistence layer. It will also be used to call method deserialize dynamically when loading log data for display. Changing it later will make already stored containers inaccessible!
Has to return the describing short text of a container, that will be displayed in the tree control in SLG1.
HINT: If your data container allows multiple instances (cardinality [0-n]) you might want to add individual label texts to every single container instance to be able to tell them apart. Single-use-containers can use static texts (e.g. text symbols of the class).
If you need dynamic texts, it is highly recommended to use a translatable text container for that purpose. This will ensure, that you will see these labels in a language that you understand when displaying the log.
Currently two text containers are shipped with the API:
-
/USI/CL_BAL_TC_LITERAL_C40
- Text will be stored 'as is' on the database
- Consider using english texts when using this container
-
/USI/CL_BAL_TC_REPORT_TEXT_C40
- Dynamic reference to a text symbol
- Text will be read when displaying data in SLG1
- Implements a fallback strategy for missing translations and will display the text in the most reasonable language (As per system customizing)
- Fallback #1: Fallback languages defined in T002C-LAKETT. Up to two fallback languages are supported by this fallback mechanism.
- Fallback #2: General language priority defined in table T778L.
" Example: how to integrate translatable text containers into a data container
CLASS zcl_bal_dc_my_container DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES: [...]
METHODS constructor
IMPORTING
i_container_title TYPE REF TO /usi/if_bal_text_container_c40 OPTIONAL " Import container title
i_container_data TYPE string.
PRIVATE SECTION.
DATA: container_title TYPE REF TO /usi/if_bal_text_container_c40,
container_data TYPE string.
ENDCLASS.
CLASS zcl_bal_dc_my_container IMPLEMENTATION.
METHOD constructor.
container_title = i_container_title. " Store it internally
container_data = i_container_data.
ENDMETHOD.
METHOD /usi/if_bal_data_container~get_description.
DATA container_title_text TYPE /usi/if_bal_text_container_c40=>ty_text.
r_result = TEXT-des. " Prefix for your container type (e.g. "HTML-Document")
IF container_title IS BOUND. " Add text to description
container_title_text = container_title->get_text( ).
CONCATENATE r_result `: ` container_title_text INTO r_result IN CHARACTER MODE.
ENDIF.
ENDMETHOD.
[...]
ENDCLASS.
Converts the internal data of the instance into an XML-String.
HINT: Use transformation ID to convert data to XML
" Example without text container
METHOD /usi/if_bal_data_container~serialize.
CALL TRANSFORMATION id
SOURCE container_data = container_data
RESULT XML r_result.
ENDMETHOD.
" Example with text container
METHOD /usi/if_bal_data_container~serialize.
DATA: container_title_classname TYPE /usi/bal_text_cont_classname,
serialized_container_title TYPE /usi/bal_xml_string.
" Serialize container title
IF container_title IS BOUND.
container_title_classname = container_title->get_classname( ).
serialized_container_title = container_title->serialize( ).
ENDIF.
" Serialize container data and serialized container title
CALL TRANSFORMATION id
SOURCE container_data = container_data
container_title_classname = container_title_classname
serialized_container_title = serialized_container_title
RESULT XML r_result.
ENDMETHOD.
Recreates an instance from an XML-String
HINT: Use transformation ID to convert XML to internal format.
" Example without text container
METHOD /usi/if_bal_data_container~deserialize.
DATA: container_data TYPE string,
transformation_error TYPE REF TO cx_transformation_error.
" Convert XML to internal format
TRY.
CALL TRANSFORMATION id
SOURCE XML i_serialized_data_container
RESULT container_data = container_data.
CATCH cx_transformation_error INTO transformation_error.
" ALWAYS (!!!) catch transformation errors!
" This will avoid short dumps in SLG1, if something is wrong with the XML conversion.
RAISE EXCEPTION TYPE /usi/cx_bal_type_mismatch
EXPORTING
textid = /usi/cx_bal_type_mismatch=>/usi/cx_bal_type_mismatch
previous = transformation_error.
ENDTRY.
" Use data to recreate the container instance
CREATE OBJECT r_result TYPE zcl_bal_dc_my_container
EXPORTING
i_container_data = container_data.
ENDMETHOD.
" Example with text container
METHOD /usi/if_bal_data_container~deserialize.
DATA: container_data TYPE string,
container_title TYPE REF TO /usi/if_bal_text_container_c40,
container_title_classname TYPE /usi/bal_text_cont_classname,
exception TYPE REF TO cx_root,
exception_text TYPE string,
serialized_container_title TYPE /usi/bal_xml_string.
" Convert XML to internal format
TRY.
CALL TRANSFORMATION id
SOURCE XML i_serialized_data_container
RESULT container_data = container_data
container_title_classname = container_title_classname
serialized_container_title = serialized_container_title.
CATCH cx_transformation_error INTO exception.
" ALWAYS (!!!) catch transformation errors!
" This will avoid short dumps in SLG1, if something is wrong with the XML conversion.
RAISE EXCEPTION TYPE /usi/cx_bal_type_mismatch
EXPORTING
textid = /usi/cx_bal_type_mismatch=>/usi/cx_bal_type_mismatch
previous = exception.
ENDTRY.
" Recreate the text container, if needed
IF container_title_classname IS NOT INITIAL.
TRY.
CALL METHOD (container_title_classname)=>/usi/if_bal_text_container_c40~deserialize
EXPORTING
i_serialized_text_container = serialized_container_title
RECEIVING
r_result = container_title.
CATCH cx_sy_dyn_call_error
/usi/cx_bal_root INTO exception.
exception_text = exception->get_text( ).
ASSERT ID /usi/bal_log_writer
FIELDS exception_text
CONDITION exception IS NOT BOUND.
CLEAR container_title.
ENDTRY.
ENDIF.
" Use data to recreate the container instance
CREATE OBJECT r_result TYPE zcl_bal_dc_my_container
EXPORTING
i_container_title = container_title
i_container_data = container_data.
ENDMETHOD.
Jumps to e.g. a source code position, but could also call transactions, etc. Implement the navigation you need.
Renders the internal data of the data container.
The API will provide an instance of class CL_GUI_CONTAINER that has to be used as the parent for all controls used to display the data.
Data containers are assigned to log levels and will only be saved, if the current log level meets the required minimum (see: Customizing -> Log Levels -> Relevant Data Containers).