Dynamic Logpoints in ABAP
As an experienced trouble-shooting expert you certainly encountered the ABAP statement LOG-POINT.
Using statement LOG-POINT in ABAP you can
- log the content of nearly all kinds of variables – including internal tables
- specify an arbitrary subkey for log event aggregation
- switch on logging dynamically by using transaction SAAB
But as this kind of logging uses dedicated ABAP statements the source code has to be prepared beforehand. However, there is lots of ABAP code around, which is not prepared for logging yet.
What if you need to analyze such code without the possibility to change it, e.g. in a productive system?
New: Setting logpoints dynamically
With dynamic logpoints (available with SAP NW ABAP 7.5) you can now set logpoints dynamically -much like you set breakpoints- at arbitrary source code positions and even in productive systems (as long as you have the necessary privileges).
To set a dynamic logpoint simply right-click the marker bar next to the source code line, where you usually set a breakpoint. In the context menu simply click on “Add Logpoint…”.
In the “Add Logpoint” dialog you can choose between different predefined activities for different use cases, like “Log Simple Variable Values”, “Log Call Stack” and more or you can use the more advanced “User-Defined Logging”, where you can enter the variables to be logged, the key for aggregation and an optional condition in a free-style way.
But let us first have a look at a simple example.
Example 1: Logging simple variables
Function module RS_TABLE_LIST_CREATE is used by transaction SE16 to create, generate and call the ABAP report needed to display the individual database table contents. It takes a parameter TABLE_NAME, which is the name of the database table to be displayed.
We now want to know, which database tables are being displayed in our system and how often.
Therefore, set a dynamic logpoint at the first executable line of the function module RS_TABLE_LIST_CREATE, choose activity “Log Simple Variable” for your logpoint and specify variable TABLE_NAME as variable to be logged:
Don’t limit the logpoint activation for specific users or application servers. Just leave the “Activation” section as is and press “finish”. Now your logpoint is activated for all users at all servers and the system collects the log data for you.
In the source code, you can now see the red logpoint symbol in the marker bar. Hover over the symbol and you’ll see the logpoint properties at a glance.
After a while you want to see your log results, so switch to the logpoint view. Refresh the display by using the “Collect logs …” button:
In the example described here 7 log events have been collected after a while.
If you now highlight the logpoint entry of RS_TABLE_LIST_CREATE, the result display comes up at the right side of the logpoint view:
You can now see the individual database table names and how often they have been displayed in the system using transaction SE16.
Example 2: Who is calling my service? (Log Call Stack)
If you need to change the behavior of a specific service (e.g. a function module or method), you should know, who is calling it. The information of the direct caller might be sufficient sometimes, but often you need to know the complete ABAP call stack for a deeper analysis.
How can we tackle such a task with dynamic logpoints?
Assume that we are interested in a special service that is the UTC time stamp conversion to system time implemented in method CL_ABAP_TSTMP=>SYSTEMTSTMP_UTC2SYST. We now want to analyze, who is calling the service and how often.
This is rather simple. Just set a dynamic logpoint at e.g. the first line of the method implementation and use the predefined activity “Log Call Stack”.
Activate the logpoint and after a while switch to the logpoint view to have a look at the results.
It may look like this.
On the left side of the result display hash key values can be found, representing all individual ABAP stack hierarchies the method CL_ABAP_TSTMP=>SYSTEMTSTMP_UTC2SYST was called from. The “Log Events” column on the right side tells you how often this has happened. If you navigate into the details of one result display row, you can see the involved ABAP stack in the column “Field Values”.
So you just need a few clicks to get complete information about how often a dedicated service was called in a system and who called it along with detailed information about the ABAP call stack.
But now you may ask yourself:
Where do the hash key values come from and what they are good for?
To answer this, we first need to look at the more advanced activity “User-Defined Logging” in the next example.
Example 3: Log the number of ALV items displayed by the transactions executed in the system
In this example you will see, how easy it is to detect the transactions in your system, which are using ALV and how many list items they show. A glimpse of the content displayed by ALV can also easily be added.
To realize this you should use the activity “User-Defined Logging”, with the input fields “Key Definition”, “Field Values” and an “Optional Condition”.
Now set a dynamic logpoint at the first executable line of function module REUSE_ALV_GRID_DISPLAY. Parameter T_OUTTAB contains the data to be displayed.
In the key definition specify the built-in functions req_type() and req_entrypoint(), which are returning the request type and the name of the current request (e.g. “TA” and “SM50”). Then the literal ‘ALV lines:’ is used for better readability and finally the built-in function lines( ) puts the number of lines of table T_OUTTAB into the key string.
In the Field Value section specify the first line of table T_OUTTAB, just to get an idea what kind of data is displayed in the current transaction.
Last but not least you may want to limit the logging to certain users, which can be done in the condition, like it is shown above.
After a while you get results like this:
You can now clearly see what requests/transactions are using ALV, how many lines they are showing and how often they have been called in the system.
In this example, we used the built-in functions
- req_type( )
- req_entrypoint( )
- lines ( )
But there are more.
Other useful built-in function are for example
- stack_hash( )
- stack( )
The stack_hash( ) function returns a hash key of the current ABAP stack, while function stack( ) delivers the current ABAP stack itself in an internal table.
Now you can understand, what the activity “Log Call Stack” in example 2 is doing: It pre-fills the “Key Definition” input field with stack_hash( ) and writes function stack( ) into the “Field Values”.
The unique hash value returned by stack_hash() makes the system to count similar and collect different ABAP stacks, while function stack( ) puts the ABAP stack into the “Field Values” of the result display by returning an internal table, filled with the ABAP stack.
You have seen how easy it is to configure, start and display your individual tailor-made analysis with dynamic logpoints.
Use the predefined activities, like “Log Simple Variable Values” or “Log Call Stack”, wherever it is sufficient for you and use the full-fledged flexibility of the “User Defined Logging”, where you need it. There is nearly nothing you can not do with dynamic logpoints.
And the best thing is: you not even have to change the source code for it!