Tutorial - Logging and Tracing Mechanism in SAP PDF
Tutorial - Logging and Tracing Mechanism in SAP PDF
Table of Contents
1.
2.
INTRODUCTION ........................................................................................................................................... 6
2.1
WHAT IS LOGGING AND TRACING? ............................................................................................................ 6
2.1.1
Purpose.............................................................................................................................................. 6
2.1.2
Advantage .......................................................................................................................................... 6
2.2
CURRENT PACKAGE ................................................................................................................................... 7
2.2.1
Overall Logic..................................................................................................................................... 7
2.2.2
Conceptual view and terminology ..................................................................................................... 7
3.
4.
5.
ADMINISTRATIVE ISSUE......................................................................................................................... 46
5.1
5.2
5.3
6.
6.1
6.2
6.3
APPENDIX A ........................................................................................................................................................ 50
SEVERITY LEVELS ................................................................................................................................................ 50
APPENDIX B......................................................................................................................................................... 51
OVERVIEW OF CLASSES HIERARCHY .................................................................................................................... 51
APPENDIX C ........................................................................................................................................................ 52
DEFAULT BEHAVIOR OF CERTAIN OBJECTS ........................................................................................................... 52
Table of Figures
Figure 2-1 Conceptual View of SAP Logging tool ................................................................................... 8
Figure B-1 Class diagram of the logging API ......................................................................................... 51
Table 2-1 Terminology of key components .............................................................................................. 8
Table 3-1 Common Output API group 1 .............................................................................................. 10
Table 3-2 Common Output API group 2 .............................................................................................. 10
Table 4-1 Placeholders of TraceFormatter .............................................................................................. 24
Table 4-2 Placeholders of filename ......................................................................................................... 29
Table 4-3 Common Output API with support of translation ................................................................... 31
Table 4-4 Setting relative severity........................................................................................................... 36
Table 4-5 Summary of configurable attributes of some classes .............................................................. 44
Table A-1 Definition of severity levels ................................................................................................... 50
Table C-1 Default attributes values......................................................................................................... 52
Table C-2 Highlights of default behavior................................................................................................ 53
1.1
Target Audience
Primarily all SAP Java developers who are required to provide logs in a productive environment
for the customers, or who are simply interested in having traces to assist their own debugging tasks
are the audience.
1.2
2. Introduction
2.1
2.1.1 Purpose
There are various infrastructure and application development groups in SAP coding in Java, and
either they have their own (quick & dirty) logging mechanism, or they do not do this at all.
However, the availability and readability of traces or event logs are very important for both the
developers and the potential users, like testing group, support group and operators. Therefore, a
common logging framework must be made available to satisfy the requirements of these groups,
especially in a large and distributed environment. A standardized infrastructure will be essential
and beneficial for both the developers and the consumers.
2.1.2 Advantage
In designing this framework, we have kept the following in mind:
Easy to use API
Enabling logs is not a popular task for developer. So, the API/method calls to do so have to be
simple and intuitive.
Performance
The switching on of the logging mechanism should not degrade the performance of the
application as if running with logging,
Easy to maintain
The log insertion done by developer is totally decoupled from executing the code.
Switching on or controlling the amount of log output is configurable at runtime without
modifying the source code.
2.2
Current Package
com.sap.tc.logging referred as SAP Logging API, with all functionality for both tracing
and events logging
Log
Log Manager
Manager
1
application
Message
with severity
Log
Log
Controller
Controller
1
Log
Record
Log
Log
publish
1 severity
severity
Filter
Filter
Formatter
Term
Description
Logging Manager
Log Controller
Log Record
Log
Formatter
Filter
Background
The concept of the SAP logging tool is very similar to the other available tools in the market. It
offers better support for a common practice in logging:
Generates classical trace messages and log messages
There exists APIs that are handy to bridge these two types of messages together for advanced
analysis.
Other advanced features will be covered in the later sections.
Are you outputting messages for logging or for tracing?
If your goal is to pinpoint distinguished problematic logistic areas, then you should focus on log
messages, while if you are more interested in analyzing coding problems, then trace messages is
the one to be used.
Yes, this will be the major task as a developer to enable logging: classify the source area that needs
to be logged/traced, and then insert the output messages in the code. Simple enough.
What are the basic classes to start with?
From the conceptual view diagram Figure 2-1, you should know by now the Java class that
represents the source area: Log Controller. In general, you deal with its two subclasses directly:
Category: generate log messages
Location: generate trace messages
Examples for a Category:
/System/Database, System/Security,
Examples for a Location:
com.sap.tc, com.sap.tc.logging,
(Please refer to Appendix B for a complete class hierarchy diagram defined for this logging API).
Lets start getting familiar with the tool by focusing on one area. Since both API for logging and
tracing are quite similar, it will be very straightforward to use one or the other when you have
learnt one of them. Most examples will be focused on the tracing API.
3.2
errorT(string the_message)
warningT(string the_message)
infoT(string the_message)
pathT(string the_message)
debugT(string the_message)
Table 3-1 Common Output API group 1
The second group also has intuitive names, but without explicit severity level shown in their
names. Table 3-2 below shows the ones that are commonly used:
Common output API
(mostly for program flow)
entering()
exiting()
throwing(Throwable the_exception)
assertion(Boolean the_assertion,
String the_message):
Description
Denote method entry with level Severity.Path. Always
used together with exiting().
Denote method exit with level Severity.Path. Always used
together with entering().
Output the exception content with level Severity.Warning
A trace method to verify your assertion and will throw a
Severity.Error message when the condition is false.
Refer to the Javadocs, it may first appear that there are overwhelmingly numerous methods, but
they are pretty much overloaded methods with different arguments to enhance flexibility. It is
better to provide more options for different requirements, rather than inadequate APIs. (More
details shown in Section 4.2.4).
The APIs shown above are in their simplest form for clarity. But even with these methods, you are
already in good shape to start playing with logging/tracing.
3.3
3.3.1 Tracing
package com.sap.fooPackage;
public class FooClass{
public void method1(){
Tutorial Logging & Tracing Mechanism in SAP
By: Infrastructure Management Team
A typical program
without tracing
inserted.
1
}
public void method2(){
try{
.
}
catch (IOException e){
..
}
}
public static void main(String[] args){
FooClass test1 = new FooClass();
test1.method1();
test1.method2();
}
}
Now, lets insert traces into the program (original code is grayed out for your convenience).
The API to create a source trace object is simple, as well as the output methods used for writing
traces.
package com.sap.fooPackage;
Sample program showing
the instrumentation of
traces
// (0)
import com.sap.tc.logging.*;
public class FooClass{
static{
myLoc.setEffectiveSeverity(Severity.PATH);
myLoc.addLog(new ConsoleLog());
}
public void method1(){
// (3) Enable the writing of trace messages
myLoc.entering("method1");
myLoc.exiting();
}
public void method2(){
myLoc.entering("method2");
try{
.
}
catch (IOException e){
myLoc.throwing(method2, e);
..
}
myLoc.exiting();
}
public static void main(String[] args){
FooClass test1 = new FooClass();
test1.method1();
test1.method2();
}
}
3.3.2 Explanation
There are mainly a few additional lines you need to activate the tracing feature. Refer the
numbering below to that in the sample source code.
(0): Import the SAP logging package
(1): Get access to a location object for the current class. The API provided should be intuitive
enough: a class method provided by Location class. Users do not have to work on
constructor, just call Location.getLocation(<name of location object>), and
receive a handle to the unique location
(2): Assign severity level and destination for the location object
This will be the level to be compared against the severity of the trace messages. Messages
with severity lower than this of the location object will not be printed. Refer to Appendix A
to get familiar with the severity level definition.
By default, Severity.NONE will be assigned (that is, there will be no output at all). So, for this
sample coding, an explicit level Severity.PATH is assigned to screen out all the debugging
messages, which have a lower severity.
Also by default, no output destination is assigned (again, no output at all). In the example
above, we direct the output to the console. Refer to Appendix B with class diagram that
shows that we mainly have two types of logs: FileLog, ConsoleLog.
(In Section 4.6, you will learn that it is not necessary to hardcode it here in the source, and
you can configure this setting externally without messing with the code.)
(3): Insert trace messages in your program
The example shows a few APIs that write out trace messages: entering, warningT,
throwing, exiting. Which messages will eventually be printed? We know that all these
messages will successfully pass the level Severity.PATH (as specified in this example in step
(2)).
3.3.3 Output
In the example above, messages will be directed to the console with the (default) format readable
by operators (using TraceFormatter).
The content of the output file for the example above looks like this:
May 3, 2001 6:54:18 PM com.sap.fooPackage.FooClass.method1 [main]
Path: Entering method
May 3, 2001 6:54:18 PM com.sap.fooPackage.FooClass.method1 [main]
Warning: Sample warning message
May 3, 2001 6:54:18 PM com.sap.fooPackage.FooClass.method1 [main]
Path: Exiting method
May 3, 2001 6:54:18 PM com.sap.fooPackage.FooClass.method2 [main]
Tutorial Logging & Tracing Mechanism in SAP
By: Infrastructure Management Team
3.4
Coding Recommendations
The logic so far is straightforward and the learning curve is not steep, just a few additional lines,
and you can enjoy the decent result in a log file.
Before we wrap up this section, there are certain recommendations for you to improve the tracing
functions.
Static reference
As you may have noticed from the sample coding, the variable that holds the location object
is declared with a static modifier to improve efficient access. Basically, a handle to a location
object can always be obtained by calling Location.getLocation(<id>). However,
making such a call every single time may degrade the performance.
Default Setting
In the previous section, you have already encountered a few times that a default value has already
been set and you simply have to accept the default behavior mentioned in the example. These
settings can be easily manipulated and changed by you through the API or an external
configuration file (details in Section 4.6).
Advantages
Default values are meant to provide a reasonable logging behavior with minimal configuration
required to be done by the users. For example, once a user has specified to output the message to a
console, it is assumed to be read by operators, and thus, a TraceFormatter (formatting message
that is readily understood by human being) is selected with the predefined message pattern that can
clearly displays the message and its relevant info:
May 3, 2001 6:54:18 PM com.sap.fooPackage.FooClass.fooMethod [main]
Path: Entering method
References
There will be more predefined values appearing in the following sections. To assist you in moving
on smoothly with the tutorial, as well as avoiding ambiguity for your future coding, refer to
Appendix C where we are keeping track of the various default settings and behavior.
4.2
Detailed Example
To recap again, there are mainly 4 steps in enabling logging for your application.
Identify source code area, e.g. a class Node, and represent it with a Location object
Location loc = Location.getLocation("<package>.Node");
//default: Severity.NONE
It is a legitimate deduction that more than 90% of your development time will be spent on step 1
and 4. Eventually, step 2 and 3 can be mainly configured externally so that users can control the
output without the need to modify source code and recompile again.
Shown below is a very basic sample code, showing step 1 & step 4:
package com.sap.fooPackage;
import com.sap.tc.logging.*;
public class Node {
private static final Location loc =
Location.getLocation("com.sap.fooPackage.Node");
public void announce(Object o) {
String method = "announce(java.lang.Object)";
loc.entering(method);
try{
// do something...
loc.debugT(method, "Connecting to ");
}
catch (Exception e) {
loc.fatalT(method,
"Error processing object {0}",
new Object[] {o});
}
loc.exiting();
}
}
Step 2 & 3 are not shown at this point, but assuming the severity level assigned to this is set to be
Severity.ALL (accept all severity levels and output everything) and output has been piped to a
ConsoleLog (terminal).
The output will look like this, formatted with TraceFormatter (default formatter for ConsoleLog).
May 3, 2001 6:54:18 PM com.sap.fooPackage.Node.announce [main] Path: Entering method
May 3, 2001 6:54:18 PM com.sap.fooPackage.Node.announce [main] Debug: Connecting to .
May 3, 2001 6:54:18 PM com.sap.fooPackage.Node.announce [main] Path: Exiting method
The following 4 sections will further explain each step in details. Bear in mind that in this section
4.2, we try to focus only on the most basic scenario and its API and avoid jumping into the
advanced logic. This should be good enough to get you started. But you will find frequent
references to later sections that cover the logic or advanced features in details.
Or instead of passing the name manually, for Location, you may as well pass the class instance
(java.lang.Object) or the class itself (java.lang.Class). Refer to the Javadocs for details.
In this case, the location object is by default referring to the class level, while using the string
argument (java.lang.String), you have the flexibility in the definition, e.g. include also the
method name to explicitly control logging over methods individually.
Now that you have got a handle to the source, you are ready to configure and ask this source to
generate messages. It is recommended that initially, you should assign make the handle to be
static to improve the efficiency:
static final Location loc = Location.getLocation(this.getClass())
Then, any messages with severity lower than INFO will be discarded, others will be directed to the
destination.
Introduce concept of hierarchical severity
Hierarchical severity will be mentioned in Section 4.4.2, but one quick note is, because of the
hierarchical naming feature of location or category, you can save some effort by assigning severity
to the parent, and its children will automatically inherit the assigned severity as well.
static final Location loc = Location.getLocation(com.sap.fooPackage);
loc.setEffectiveSeverity(Severity.INFO);
If you have a location com.sap.fooPackage.Class1, it will have inherited the severity INFO
already.
Default with strictest severity
By default, source object (assume the ascendants has not been assigned severity yet) has
SEVERITY.NONE. Therefore, developer can freely enable the output methods in the source code,
but the actual logging is not activated until it is explicitly switched on when things are ready.
Types of log
Currently, there are 2 types of logs: ConsoleLog, FileLog.
ConsoleLog is for printing to terminal, while FileLog is for writing messages to files.
Multiple destinations
Tutorial Logging & Tracing Mechanism in SAP
By: Infrastructure Management Team
There are times you may want to assign multiple logs to a single source. Message generated from a
source will be sent to both of them simultaneously. For example, output messages to both the
console and a file.
The simplest ways to do so is as below:
loc.addLog(new ConsoleLog());
loc.addLog(new FileLog(C:\\temp\\testOutput.log);
Creating a log
As you can see from the Javadoc API, the constructors are overloaded where you can specify
certain options for the logs, while we only show the most basic one here (using minimal
parameters for simplicity). Therefore, default settings are used and worth noted:
ConsoleLog is using a TraceFormatter by default.
FileLog is using ListFormatter and the output file will not be a rolling file type, but one single
output file, increasing in size when more and more messages appended to it. More
configurations can be specified for a FileLog and the details are described in 4.4.5.
For example, if you want to switch to a XMLFormatter of a Filelog, you may call:
loc.addLog(new FileLog(C:\temp\testOutput.log, new XMLFormatter());
Attaching a log
Refer to the Javadoc, there are two other APIs in assigning Logs to a Location or Category,
addPrivateLog, addLocalLog, because there are actually three forms of log assignments.
They behave differently in terms of inheritance by children of a Location or Category source. In
short, these three are mutually exclusive, and the example addLog shown here is
straightforward for beginners. It supports forced inheritance to children and message output
unconditionally. More details can be found in sections 4.4.3 and 4.5.1.
4.2.4.1
Location
Category
The names are self-explanatory about the severity level of the messages generated by these
methods. The overloaded pattern is the same for each severity output (masked with xxxx
here):
Location
Category
xxxxT(String message)
xxxxT(String subloc, String message)
xxxxT(String message, Object[] args)
xxxxT(String subloc, String message,
Object[] args)
There exists a pattern in method overloading: evolves around the core argument: message.
The addition of subloc, args offers the flexibility for developers to log messages in the
level of details that they need. Understanding these arguments can help you select the
heavily overloaded methods easier.
loc:
It is obvious that the only difference in the API between Location and Category is an
additional loc argument in Category output methods. It is a typical request that log
messages are always written with respect to a source code area. This proves to be very
helpful for logging analysis. By specifying the loc argument, you indicate that the message
should be written as a trace message associated with the loc object. With a little
configuration done for loc, logging can be just done once but will be piped for both
message types (logs & traces) simultaneously. This is explained in details in Section 4.5.2.
Vice versa, this works for Location as well, and API is available to specify the category
argument. But since this is optional for Location, so we wont list them here. (Again, refer
to Section 4.5.2).
subloc:
Treat the subloc argument as the method name of the source class that the message is
generated from. This is optional, but with this argument included in the trace/log, the
picture when doing analysis will be much clearer, especially you can specify different
arguments for overloaded methods.
message:
The actual message to be printed is put in argument message. Make up something simple
that is meaningfully describing the situation/problem. (Aforementioned, language
independency is supported, using ResourceBundle. Refer to 4.4.7 for more examples of
output methods).
args:
Array of additional arguments that are informative, e.g. dynamic information to be included
in the message. This is achieved by using java.text.MessageFormat API to resolve
arguments.
To reiterate, refer to the sample code at the beginning of Section 4.2.3, with method
announce(Object o). This is a simple example of working on Location object.
package com.sap.fooPackage;
import com.sap.tc.logging.*;
public class Node {
private static final Location loc =
Location.getLocation("com.sap.fooPackage.Node");
public void announce(Object o) {
String method = "announce(java.lang.Object)";
try {
// do something...eg. connecting to DB, perform certain actions
loc.debugT(method, "Connecting to .);
//minor error in writing something
loc.warningT(method,
"Problems in row {0} to {1},
new Object[] {row1, rowN});
//finish successfully
loc.infoT(method, "DB action done successfully);
}
catch (Exception e) {
}
} // method announce
} // class Node
Potential output, assuming the simplest case with ConsoleLog and default TraceFormatter:
May 3, 2001 6:54:18 PM com.sap.fooPackage.Node.announce [main] Debug: Connecting to .
May 3, 2001 6:54:18 PM com.sap.fooPackage.Node.announce [main] Warning: Problems in row 15 to
18
May 3, 2001 6:54:18 PM com.sap.fooPackage.Node.announce [main] Info: DB action done successfully
} // method store
// class Node
Note that the output will be identical to the previous example, assuming the default setting
is used (with ConsoleLog and default TraceFormatter). Only when you configure the
output display accordingly (e.g. use another formatter, or change the pattern of the
TraceFormatter), then you will get different result. See Section 4.4.1 for more information.
4.2.4.2
Program flow
This is only available in Location. Tracing the flow of program is a common practice:
entering, exiting, throwing, assertion.
exiting: output a default message (Exiting Method with Path severity) indicating
that it is leaving a source block. NOTE: ALWAYS paired up with method
entering.
Method
Description
exiting()
Exiting a source block in general. As long as
the methodname (subloc) is specified in
entering , it is not necessary to provide
subloc as argument here anymore. See the
result of the following sample code.
exiting(String subloc) //DEPRECATED
Specify the method name in subloc
exiting(Object res)
A general source block with result:
Exiting method with <res>
exiting(String subloc, Object res)
Same as above but with specific method name
Potential output, assuming the simplest case with ConsoleLog and default TraceFormatter:
May 3, 2001 6:54:18 PM com.sap.fooPackage.Node.announce [main] Path: Entering method
May 3, 2001 6:54:18 PM com.sap.fooPackage.Node.announce [main] Path: Exiting method
assertion: to test a condition and output an error message, normally with the
assertion included (Assertion failed: <assertion test>) when the evaluation is
false
Method
Description
assertion(Boolean assertion, String desc)
Evaluate the assertion, if false, print desc with the
default message: Assertion failed: <desc> where
<desc> is the assertion test itself, e.g. 5 > 3
assertion(String subloc,
Same as above but with specific method name
Boolean assertion, String desc)
Potential output, assuming the simplest case with ConsoleLog and default TraceFormatter:
May 3, 2001 6:54:18 PM com.sap.fooPackage.Node.announce [main]
Error: Assertion failed: Stupid comparison
May 3, 2001 6:54:18 PM com.sap.fooPackage.Node.announce [main]
Warning: Throwing java.io.FileNotFoundException:
C:\Not_Exist\zzzzz.log (The system cannot find the path specified)
4.2.4.3
Master gate
LogT
All the other output methods of first type (with severity) are ultimately routed through
this method to actually perform any logging.
Location: basically, these are the same as the first type of method, xxxxxT( ), but
only with an additional severity argument at the beginning:
logT(int
logT(int
logT(int
logT(int
severity,
severity,
severity,
severity,
String
String
String
String
message)
subloc, String message)
message, Object[] args)
subloc, String message, Object[] args)
loc,
loc,
loc,
loc,
String
String
String
String
message)
subloc, String message)
message, Object[] args)
subloc, String message,
4.3
Typical Practice
The steps and logic of doing logging should be fairly clear by now.
Certainly, the information given is adequate to get users started on instrumenting logging in their
code. However, a good style of doing logging is recommended:
Enabling logging in two major steps: initialization and the individual source classes.
Two stages : higher level vs individual level
Applications are normally made up of different components and are deployed in a distributed
environment. Typically, there should exist a common initialization routine for a component.
Logging configuration, such as setting severity, assigning destination logs, can be done at this
stage as well. Then, the actual insertion of trace/log messages will be done in the respective Java
class level at the reasonable points.
A top-down approach is used, that is, defining coarse configuration at a higher level (componentoriented parent node). Most of the time, users do not need to fine-tune the logging behavior in
such details for each class. Then, a basic configuration at the top level will be good enough to get
logging started. Only when specific setting has to be done individually for certain classes, then the
users can as well enable that in the class level.
Component level at initialization
For example, a component ComX under SAP may have the following package hierarchy:
com.sap.comX.xxx.xxxx.xxx. During initialization, if logging is desired for monitoring important
messages (with severity error or above) to be shown at the console, one should set up something
like this:
Location _loc = Location.getLocation(com.sap.comX);
_loc.setEffectiveSeverity(Severity.ERROR);
_loc.addLog(new ConsoleLog());
Class level
In the individual class, it is recommended to have a static variable to hold the access to the
location object (for better performance) and then start inserting messages:
static Location _loc = Location.getLocation(<classname>.class);
_loc.infoT(.);
_loc.errorT(.);
The code will be cleaner with this 2-level setting. And the reason why this works is because of the
hierarchical feature implemented in the logging framework. Refer to Section 4.4.2 and 4.4.3 for
more details.
You will gradually find that the actual logging part within each class is pretty static, only the
configuration part to manipulate the logging behavior is dynamic, such as, output volume, output
destination, output format. This will be covered in details in Section 4.6.
These two sections provide the basic concepts and show you the basic steps to get you started. In
order to benefit the most out of the tool, you should explore around with the references of the next
few sections.
4.4
Basic Features
This section describes a few tricks that enhance the intelligence to meet the common logging
requirements.
Log (destination)
A log represents the destination where the messages to be written to. It is also the object we
will specify and assign an appropriate formatter for the log, as well as multiple optional
filters (see the next two sections). Like the log controller source object, a severity level can
be defined for each log, but unlike the default for log controller (Severity.NONE), the
default for a log is Severity.ALL, that is, no effect on the main severity level check with log
controller. (See Appendix C for an overview of default values.)
Currently, the following logs are provided:
ConsoleLog
Direct the messages to System.err (java.lang.System)
Typical use in debugging process for a quick view of problems
FileLog
Direct the messages to a file or a set of rotating files (more details in Section 4.4.5)
StreamLog
Direct the messages into an arbitrary OutputStream (java.io.OutputStream)
4.4.1.2
Formatter
Each type of log destination can print the messages in different formats. Currently, there
are three major types of formatter:
TraceFormatter
Human readable format
This is very likely to be the most commonly used formatter when users want to
quickly understand what is going on with the application.
Normally, not used with log viewers (refer to Section 6.2). Therefore, users can
customize the pattern of the TraceFormatter, indicated by various placeholders.
Details can be referred to the Javadoc of method setPattern. By default, the
pattern is:
%24d %-40l [%t] %s: %m
The number in the pattern denotes the width of a field. In the first example: %-40l
indicates a 40 char limit for the location name (com.sap.FooClass.fooMethod) that will
be right aligned (with a minus sign). If the length of a string exceeds the width
defined, the string will be truncated. The second example: %l simply displays the
full string that will be left aligned.
The meaning of the place holders (details can be found in Javadoc):
Placeholder Description
%d
timestamp in readable form
%l
%c
%t
%s
%m
%I
%p
%g
XMLFormatter
Suitable for file transfer to be further processed in other applications
Sample out of the same result is:
<record>
<id>10.48.27.165:4A5AB2:E99D2EDAFF:-8000</id>
<time>Mon Jan 01 22:00:00 PDT 2001</time>
<source>com.sap.FooClass</source>
<location>com.sap.FooClass.fooMethod</location>
<thread>main</thread>
<severity>Fatal</severity>
<msg-type>Plain</msg-type>
<msg-clear>A sample fatal message</msg-clear>
</record>
ListFormatter
Output in this format serves like a router to send the data to be processed further by
another application, e.g. a log viewer, instead of being read directly by an end-user
As simple hash-separated fields to be processed mainly with a log viewer
Sample output of the same result is, as of version 1.3:
#1.3#10.48.27.165:4A5AB2:E99D42D4F4:-8000#Mon Jan 01 22:00:00 PDT
2001#com.sap.FooClass#com.sap.FooClass.fooMethod#main##0#0#Fatal##Plain###A
sample fatal message#
Filter
When parent com.sap is explicitly assigned with Severity.FATAL, this severity will not be
inherited straightly by com.sap.foo because it gets denied by its ceiling threshold. Instead,
com.sapmarkets.foo will get the ceiling threshold Severity.WARNING. The same theory
applies to the floor threshold, i.e., any severity of parent that is lower than Severity.DEBUG will
be ignored.
Only when the parents severity falls between the severity range of the child can overwrite the
childs severity with its own value.
(A technical side note: assigning explicit severity, setEffectiveSeverity(Severity.INFO),
automatically overwrites the value of both MinimumSeverity and Maximum Severity into
Severity.INFO).
Lets try to organize the possibilities here:
A default setting:
Location/
Category
Maximum
Severity
com.sapmarkets
com.sap.foo1
com.sap.foo1.child1
com.sap.foo2
com.sap.foo2.child1
NONE
NONE
NONE
NONE
NONE
Minimum
Severity
ALL
ALL
ALL
ALL
ALL
Resulting
(Effective)
Severity
Description
NONE
NONE
NONE
NONE
NONE
default
default
default
default
default
Scenario 1:
Location/
Category
Maximum
Severity
Minimum
Severity
Resulting
(Effective)
Severity
Description
com.sap
WARNING
WARNING
WARNING
com.sap.foo1
FATAL
ALL
WARNING
setEffectiveSeverity =
WARNING
setMaximumSeverity =
FATAL
com.sap.foo1.child1
com.sap.foo2
com.sap.foo2.child1
NONE
NONE
INFO
ALL
ALL
ALL
WARNING
WARNING
INFO
setMaximumSeverity =
INFO
Scenario 2:
Location/
Category
Maximum
Severity
Minimum
Severity
Resulting
(Effective)
Severity
Description
com.sap
INFO
INFO
INFO
com.sap.foo1
FATAL
FATAL
setEffectiveSeverity =
WARNING
setEffetiveSeverity =
FATAL
com.sap.foo1.child1
com.sap.foo2
com.sap.foo2.child1
NONE
NONE
FATAL
ALL
ALL
WARNING
FATAL
FATAL
INFO
WARNING
setMinimumSeverity =
WARNING
Both messages will be output to the console, even ConsoleLog is assigned only to the parent node.
Additivity
Multiple destination logs are allowed. So, unlike the severity inheritance logic, the assignment of
logs to a source object is additive. There is no race condition. For example, adding to the previous
code (original code greyed out):
static final Location parent = Location.getLocation(com.sap),
Location child =
Location.getLocation(com.sap.foo);
parent.addLog(new ConsoleLog());
parent.fatalT(A fatal message from parent);
child.fatalT(A fatal message from children);
child.addLog(new FileLog(<a file>));
In the Console, there will still be two messages printed, each from parent and child, while in the
output file <a file>, messages from child (here, only 1 message) are also printed, in addition to
Console destination.
One might want to suppress this inheritance feature in certain circumstances to fine-tune the output
behavior. This is doable, as you can find more details in Section 4.5.1.
These return a boolean true if the message passes the respective severity level check, otherwise
false.
4.4.5.1
Filename
Description
Comments
%h
%t
Home directory
System temporary directory
%u
%%
%g
This is implicitly done when users have specified values for the filesize (in byte) and the
cap for the sequencing count before rotating back to the first file. This pair of parameters
has to coexist together. Either they both have values assigned or both values equal to zero.
Otherwise, depends the option you are using to do this configuration, either an exception
can be thrown (through programming API) or values with best guess will be used (through
configuration file, see Section 4.6), e.g. both attributes get default zero values (refer to
Section 5.1 for this fault-tolerance logic).
This can be done when calling the FileLog constructor:
FileLog
=
=
=
=
=
FileLog
%t/trace.%g.log
800000
10
TraceFormatter
The first output file will be created C:\temp\trace.0.log (NOTE: sequence number starts
with 0), and when its size approaches and then exceeds the limit (800,000 bytes), the next
incoming message will be directed to a new file C:\temp\trace.1.log. This process keeps
going until the last sequenced file C:\temp\trace.9.log (count = 10), then the next file to
be written will again become C:\temp\trace.0.log.
4.4.5.3
A FileLog is a logical representation for a physical output file where messages are directed
to. With the several configuration options mentioned in the previous section, users can
Tutorial Logging & Tracing Mechanism in SAP
By: Infrastructure Management Team
manipulate the output behavior of the output file through the API of FileLog, as well as do
(multiple) assignment(s) of the FileLog to (various) source object(s).
1:1 recommended
Intuitively and normally, this should be a 1:1 relationship between the FileLog and the
actual output file. It is rare that a user will want to create two instances of FileLog on the
same file and with different configuration, e.g. one with TraceFormatter and the other one
with XMLFormatter. Currently, this is not illegal. But it does not look like a reasonable
design, and user will run into the risk of improper synchronization of messages in a multithreading environment. The full message text may get interrupted and interweaved with
another message text.
Therefore, this is NOT recommended. At the meantime, please pay attention to this when
coding or doing configuration.
Eventually, update of this kind is very likely to be done with configuration file (Section 4.6), and
changes to logging properties during runtime are supported. There is a special syntax to deal with
additive attributes. Refer to the end of section 4.6.2.3. A quick peek again:
log[File]
log[File].pattern
log[File].formatter
com.sap.logs
= FileLog
= %t/trace.log
= ListFormatter
= log[File]
## (1) in the next round, user could switch the output to Console:
com.sap.logs
= ConsoleLog
## (2) or you can add additional console ouput:
com.sap.logs
= + ConsoleLog
ResourceBundle
This logging tool does support language dependency with the use of ResourceBundle provided in
Java. (For more background about this, please refer to the java class java.util.ResourceBundle).
The basic concept is, the message text logged by the developers in their program is neutral. It is
like a message code/id and a resource bundle file for each language exists to map the message
code into the text of the respective language. During the application runtime, depends on the
locale, resource bundle file will be looked up, and message text will be translated and localized
accordingly.
More APIs
To meet this requirement, there exists a few more output methods API under Category class to
enable the translation feature for the log messages. These do not appear under the Location class
(in terms of the basic ones you have learnt in Section 4.2.4.1 that do not involve the reference to
category).
Recall the output methods of Category you have learnt in Section 4.2.4.1 and 4.2.4.3. If you are
familiar with them, you should have no problem in using these additional output methods to enable
translation, because they are very similar and have the same overloading pattern. Basically, these
are methods
having identical corresponding method names, but ended without a T
replacing the argument String message into Object msgCode
The table below shows a few commonly used methods, compared to the classic ones that you
have learnt previously.
Category (xxxx stands for the severity level)
Translation supported
Sample
MsgCode is the message id specified in the resource bundle.
For example, there are two resource files; we have the following translation (just to make fun of
British English and American English). MsgCode is the key specified in the left of the pair.
(1)
DBProblem
ProcessCanceled
WrongColor
DBProblem
(2)
ProcessCanceled
WrongColor
During runtime, depends on the specified locale (or the default locale of the platform), the output
will be either:
Process #### canceled.
Or
Process #### cancelled.
Invalid translation
What if the MsgCode specified is invalid? A MissingResourceException will be thrown. In
this case, the exception will be caught and logged by the logging framework itself without
jeopardizing the flow of the application. The value string of MsgCode itself will be used as the
translated string. This is the best substitute in this situation. (This is actually the fault-tolerance
mechanism provided by the logging tool. See Section 5.1 for details).
There exists another option that developer can specify a meaningful message string as a backup to
get around with the invalid MsgCode problem. Then, the logging framework needs not guess a
substitute value, and this backup string can give more meaningful message (although nontranslated) than a MsgCode. This is supported by the use of an additional argument MsgClear.
Note that the same set of method APIs is overloaded again with this additional argument (method
overloading is actually very systematic, so, dont get daunted by the number of methods).
Fallback supported
xxxx(Location loc, Object msgCode, String msgClear)
xxxx(Location loc, String subloc, Object msgCode, String msgClear)
xxxx(Location loc, Object msgCode, Object[] args, String msgClear)
xxxx(Location loc, String subloc, Object msgCode, Object[] args, String msgClear)
Log(int severity, Location loc, Object msgCode, String msgClear)
Log(int severity, Location loc, String subloc, Object msgCode, String msgClear)
Log(int severity, Location loc, Object msgCode, Object[] args, String msgClear)
Log(int severity, Location loc, String subloc, Object msgCode, Object[] args, String msgClear)
This is a fallback option when the use of MsgCode is not very reliable value. When argument
MsgClear (non-null) is available, its value always exists in parallel with the MsgCode. This option
becomes particularly useful when log viewers are involved. In most cases, the assumption is
MsgCode will be used by log viewer and translation is done at the time of viewing whenever the
MsgCode is valid, otherwise, MsgClear can be used as a backup.
4.5
Advanced Features
common log
local log
private log
They are mutually exclusive for each source object. The assignment of one type will
automatically disable the assignment of the other type (if any).
4.5.1.1
Common Log
So far, this is the one that has been introduced previously. This allows regular inheritance;
this log will become available to all descendants of the parent object.
The corresponding API is:
static final Location parent =
Location.getLocation(com.sap),
Location child =
Location.getLocation(com.sap.foo);
parent.addLog(new ConsoleLog());
parent.setEffectiveSeverity(Severity.NONE);
child.setEffectiveSeverity(Severity.INFO);
child.fatalT(A fatal message from children);
Local Log
Inheritance is allowed, but with additional condition: final discretion of message printing
lies with the original parent object. The log is local, in the sense that it is not available for
the descendants if the child message does not pass the severity and filter test of the parent
object.
static final Location parent =
Location.getLocation(com.sap),
Location child =
Location.getLocation(com.sap.foo);
parent.addLocalLog(new ConsoleLog());
parent.setEffectiveSeverity(Severity.NONE);
child.setEffectiveSeverity(Severity.INFO);
child.fatalT(A fatal message from children);
Contrary to the previous example, the child message will not be printed because it does not
pass the severity test of the parent.
4.5.1.3
Private Log
This completely disables inheritance. Log assignment is private: only effective for the
parent source object.
static final Location parent =
Location.getLocation(com.sap),
Location child =
Location.getLocation(com.sap.foo);
parent.addPrivateLog(new ConsoleLog());
Tutorial Logging & Tracing Mechanism in SAP
By: Infrastructure Management Team
child.setEffectiveSeverity(Severity.INFO);
child.fatalT(A fatal message from children);
In this case, child object does not inherit any destination log at all. Nothing will be printed
even the message passes all the severity and filter tests.
loc.exiting();
} // method announce
} // class Node
In order to output all the trace and log messages highlighted in the example above, user will have
the following severity setting, for example:
loc.setEffectiveSeverity(Severity.PATH);
objMgmt.setEffectiveSeverity(Severity.ERROR);
conLog = new ConsoleLog();
loc.addLog(conLog);
objMgmt.addLog(conLog);
Output
And for the output line from the category objMgmt, it will output 2 messages simultaneously:
1 log message and 1 trace message. They will have the same message id for cross-referencing
each other. This makes the analysis more comfortable.
(But recall the information in sections 4.3, 4.4.2 and 4.4.3, the configuration could have already
been taken care of in the initialization stage and is effective to this local scope through the
hierarchical inheritance logic).
If the location has stricter severity setting, e.g. default Severity.NONE, all the trace output will be
suppressed, including the one from the category, that is, that output line will NOT produce two
messages simultaneously, but only the log message.
More control
Naturally, the next question may be whether we can do more advanced configuration regarding the
correlated category and location source objects. This is positive.
Consider Category /Objects/Management; we only want to focus on some extreme situations,
that is, messages with severity FATAL. Several source code location (com.sap.xxx.a,
com.sap.xxx.b, .) can result in a fatal condition in this logical area. And for some reasons,
we are particularly interested in one of them, e.g. com.sap.xxx.a and would like to generate
more output messages, including all with severity INFO or above related with this location only,
while maintaining FATAL for the rest.
Having a tight severity control initially and then relaxing it for particular areas in question to
produce more output for analysis is essential. More details will be shown in the next section,
which shows how to achieve this by playing with the relative severities.
Regular
Location
Category
setEffectiveSeverity
(int severity)
setEffectiveSeverity()
setEffectiveSeverity
(Category relative, int severity)
setEffectiveSeverity
(Category relative)
setMaximumSeverity
(Category relative, int severity)
setMaximumSeverity
(Category relative)
setMinimumSeverity
(Category relative, int severity)
setMinimumSeverity
(Category relative)
setEffectiveSeverity
(Location relative, int severity)
setEffectiveSeverity
(Location relative)
setMaximumSeverity
(Location relative, int severity)
setMaximumSeverity
(Location relative)
setMinimumSeverity
(Location relative, int severity)
setMinimumSeverity
(Location relative)
setMaximumSeverity
(int severity)
setMaximumSeverity()
setMinimumSeverity
(int severity)
setMinimumSeverity()
Comment
Reset severity (with
respect to the relative)
Reset
Reset
Normally, you still assign severity in the regular fashion, as those listed in column 1. The
typical requirement is to assign a stricter severity in the primary source object, and a more
relaxed level tagged with a certain relative (not the other way round!).
The relative severity is specific to the pair of the location and category. When you want to
change the relative severity or reset it, the relative has to be clearly indicated in the API.
The relative severity is unidirectional:
loc1.setEffectiveSeverity(cat1, Severity.INFO);
Relative severity is also hereditary. Descendants also inherit the relative severity
assignment. The same logic of local restriction through the use of maximum(ceiling) and
minimum(floor) severity limit (described in Section 4.4.2) is also applicable to the
descendants. Note that evaluation is always done with respective to the relative(s).
4.5.3.2
The severity of a log controller can be different when a relative severity (or severities) has
been set. The rule of thumb is: inclined to a more relaxed setting.
That is, the minimum severity of the two factors below will always win:
direct severity of itself
severity related to its relative
if there exists multiple relatives, the minimum of the relative severities wins
This applies to all 3 types of severities shown in the table above: effective, maximum, and
minimum.The following tables highlights the severity results in both cases of evaluating
with and without a relative.
Regular:
setEffectiveSeverity
(int severity)
With Relative:
setEffectiveSeverity
(<log controller> relative,
int severity)
Result:
getEffectiveSeverity()
Result:
getEffectiveSeverity
(LogController relative)
FATAL
<not set>
FATAL
INFO
<not set>
INFO
INFO
ERROR
FATAL
NONE
FATAL
INFO
FATAL
INFO
INFO
INFO
Comments
Not stricter
Regular:
setMaximumSeverity
(int severity)
With Relative:
setMaximumSeverity
(<log controller> relative,
int severity)
Result:
getMaximumSeverity()
Result:
getMaximumSeverity
(LogController
relative)
FATAL
<not set>
FATAL
INFO
<nothing>
INFO
INFO
ERROR
FATAL
NONE
FATAL
INFO
FATAL
INFO
INFO
INFO
Regular:
setMinimumSeverity
(int severity)
With Relative:
setMinimumSeverity
(<log controller> relative,
int severity)
Result:
getMinimumSeverity()
Result:
getMinimumSeverity
(LogController
relative)
FATAL
<not set>
FATAL
INFO
<nothing>
INFO
INFO
ERROR
FATAL
NONE
FATAL
INFO
FATAL
INFO
INFO
INFO
Comments
Not stricter
Comments
Not stricter
As you can see, the use of relative severity is pretty independent. It never affects the
individual severity evaluation of the log controller itself. If users decide not to configure the
output with respective to any relative, the relative severity assignment has no effect on the
output. The result will stay intact as listed in column 3.
4.5.3.3
Use the table below to elaborate (effectiveSeverity). What will be the result of the following
code for each of the 4 conditions listed? This is an example to produce log messages with
respect to a location:
Category cat = Category.getCategory(Objects/Management);
Location loc = Location.getLocation(com.sap.xxx.a);
cat.warningT(loc,
methodname,
"Error registering object {0}.");
Regular:
cat.setEffectiveSeverity
(<severity>)
With Relative:
cat.setEffectiveSeverity
(loc, <severity>)
FATAL
<not set>
FATAL
INFO
<not set>
INFO
INFO
ERROR
With Relative:
loc.setEffectiveSeverity
(cat, <severity>)
FATAL
<not set>
<not set>
INFO
FATAL
INFO
INFO
ERROR
NO
YES
YES
YES
When the output methods API denote a relative(s), the logging framework tries to output
the message simultaneously to both the log controller and its relative(s). The evaluations
are independent and done separately. The results shown in the tables above are those for
the log controller itself.
Whether the output is enabled at the relative totally depends on the configuration set by the
relative itself, which at the same time, evaluate the severity with respective back to the log
controller. If no explicit relative severity is configured by the relative, the situation
becomes similar to the conditions listed in the table below. (Log a message from a category
with a relative location).
Regular:
cat.setEffectiveSeverity
(<severity>)
With Relative:
cat.setEffectiveSeverity
(loc, <severity>)
FATAL
<not set>
FATAL
INFO
<not set>
INFO
INFO
ERROR
For the case that relative severity is also specified at the relative loc (assuming its own
severity remains the default Severity.NONE value).
Regular:
cat.setEffectiveSeverity
(<severity>)
With Relative:
cat.setEffectiveSeverity
(loc, <severity>)
FATAL
<not set>
FATAL
INFO
<not set>
INFO
INFO
ERROR
4.5.3.4
<not set>
INFO
WARNING
ERROR
Summary of behavior
4.5.3.5
At loc:
loc.setEffectiveSeverity
(cat, <severity>)
This logging framework is providing about 8 severity levels to control the logging output.
In practice, it shows that this number of levels is adequate enough for most applications.
The majority of users mainly use 3 or 4 severity levels. But indeed certain users require
additional severity levels for some special logging behavior, mainly for distinguishing
different applications/stages, e.g., application area X, Y; initialization stage,
Common requirement
Defining your own severity levels sounds like a straightforward solution, that is, creating a
distinguished severity level to independently control the logging output for a specific
stage/area. For example, during the initialization stage, to output messages that has severity
level between Severity.WARNING and Severity.ERROR. Therefore, a customized severity
level, e.g. SEVERITY_INIT which is stricter than WARNING and lower than ERROR is
desired.
However, there are a few drawbacks with this approach:
Order of severity levels always total
Definition of the customized severity levels is unclear to users, e.g. support group
For developers, it is also difficult to maintain and coordinate the customized
severity levels among components and applications
Solution with SAP API
This issue can be well handled by the SAP logging API which provides support for both
logging (category) and tracing (location). As you have already learnt the details, you
should be aware of the flexibility to adjust severity level independently for different focuses
with the use of relative severity, e.g. more trace messages for initialization stage
initialization. This can be achieved easily by the following line, with category
initialization:
loc.setEffecitiveSeverity(initialization, Severity.WARNING);
Then, when writing message, call with respective to this relative initialization:
loc.errorT(initialization, <.message.>);
Assuming logging is not turned on for others (with default Severity.NONE), trace messages
of severity warning or above, regarding to initialization will still be written to the
corresponding destination logs.
4.5.4 Multi-threading
This logging tool works well in a multi-threading environment.
Thread id is stored with the message, and this can be displayed or masked in the output. Recall the
configuration that can be done for TraceFormatter, where you can specify the pattern of the
format to include the thread id or not.
A sample output in trace format:
Jan 01, 2001 10:10:00 PM
Jan 01, 2001 10:10:00 PM
Jan 01, 2001 10:10:00 PM
Jan 01, 2001 10:10:00 PM
Jan 01, 2001 10:10:00 PM
Jan 01, 2001 10:10:00 PM
4.6
Configuration tool
Configurator
PropertiesConfigurator
4.6.1 To use
4.6.1.1
Calling it
Now, on top of using the API in your code to do configuration, like setting severity,
designating output destination, you can now load in the configuration data from a
properties file (or a Java Properties object).
For example, in your code, usually in the initialization stage:
_propConfig = new PropertiesConfigurator(
new File("logging.properties"));
_propConfig.configure();
That is it.
The example shown above reads in a properties file named logging.properties in the
current directory (you can fill in an absolute filepath), and triggers the configuration as
specified in the file. Please refer to the Javadoc API for various PropertiesConfigurator
constructors, including the option to load your own classloader.
Currently, there is not a centralized storage framework to hold the properties files. Each
application should refer to its own properties management directory. Should the tool cannot
locate the properties file (eg. wrong path, non-existing), an error message will be prompted,
and application should continue to run, in this case, without logging being switched on
(assuming all configuration is done through the properties file). Refer to Section 5.1 for
details on error handling concept.
4.6.1.2
There exists an optional command where you can specify a periodic value (in minutes) to
read and load the properties file again, to scan for any new configuration automatically.
This feature will be even more useful when a log console is available.
The API in doing this, e.g. reloading the properties file every 30 minutes:
_propConfig.setPeriodicity(30);
Can you tell what this is doing? And can you map it back to the API?
This is equivalent to the following, where the configuration code is highlighted:
Location _loc = Location.getLocation(com.sap.foo);
_loc.setEffectiveSeverity(Severity.WARNING);
_loc.removeLogs();
//clean up existing attachments
//remember log assignment is additive?
_loc.addLog(new ConsoleLog());
_loc.fatalT(..);
_loc.infoT(.);
Now, with the use of the properties file, you can simply adjust the level of severity to
control the amount of output, or even redirect the messages into another destination(s).
You should notice the following sample values in the example above:
Attributes of a LogController: severity, logs
The value of severity: WARNING (constant value of class Severity, case-sensitive!)
The value of log: ConsoleLog (java class name of ConsoleLog, case-sensitive!)
Refer to the syntax rule described in the Javadoc API. Have you got a better sense of the
description? Can you follow the rule and map to the sample above?
4.6.2.2
The previous example is very straightforward. What if you need to do more configurations,
for example, assigning 2 output destinations for the location, replacing the default
configuration with your own configuration on the Log and/or on the Formattersuch as
assigning an XMLFormatter to a ConsoleLog (instead of using the default
TraceFormatter). In addition, you might want to reuse your own configuration object and
assign it to multiple other objects. It is no longer sufficient to use the classname
ConsoleLog directly.
You will have to use an identifier (~variable) to support these configurations. The notation
is not difficult: you denote the type of object, followed by the variable id in square bracket.
The 2 main types are:
log[<id>]
formatter[<id>]
Then you can manipulate the configuration of the log or formatter object with its respective
attributes, before really using it. (Refer to next section 4.6.2.4 for a summary of possible
semantics.)
Imagine this is the configuration coding that we have originally. How will you represent
this in your properties file?
Location _loc = Location.getLocation(com.sap.foo);
_loc.setEffectiveSeverity(Severity.WARNING);
TraceFormatter _trFormatter =
new TraceFormatter(%s: %-30l [%t]: %m");
loc.addLog(new ConsoleLog(_trFormatter));
loc.addLog(new FileLog(C:\\temp\\myTrace.txt, _trFormatter));
_loc.fatalT(..);
_loc.infoT(.);
Once you understand the following representation, you are quite ready to deal with various
situations, with reference to the syntax rule indicated in the Javadoc API, in addition to the
summary tables listed in the next section.
com.sap.foo.severity
= WARNING
#### Set up a FileLog, for storing trace, with <id>: File
log[File]
= FileLog
log[File].pattern
= C:\\temp\\myTrace.txt
log[File].formatter
= formatter[TraceNoDate]
#### Set up a ConsoleLog, with <id>: Console
log[Console]
= ConsoleLog
log[Console].formatter
= formatter[TraceNoDate]
#### Set up a TraceFormatter, with <id>: TraceNoDate
#### and its pattern starts with the Severity level, and
consists no date/timestamp
formatter[TraceNoDate]
= TraceFormatter
formatter[TraceNoDate].pattern
= %s: %-30l [%t]: %m
com.sap.foo.logs
= log[Console], log[File]
In the very last line, you may realize that using a , makes multiple entries possible.
4.6.2.3
There is an intelligence to deal with log assignment (additive) with periodic reloading.
Technical details are not covered here but the general behavior will be explained and this
has something to do with the syntax: the use of an optional +, e.g.:
com.sap.foo.logs
= + log[Console]
A general rule of thumb: With the presence of a new log(s) configuration, without the +,
like the sample code in the previous 2 sections, the already assigned logs of the log
controller will be discarded, while with the +, the new logs will be added to the existing
list of logs.
4.6.2.3.1
Configuration unchanged
According to the rule description, that means on the other hand, when the configuration
remains unchanged (which is typical once a stable configuration has been defined), the
use of + is not significant at all. No further action will be done and the already
attached objects will still be attached. This avoids the loss of state of the attached
objects.
4.6.2.3.2
Configuration changed
The typical configuration updates include changing the log destination, adding log
destination and the modifying properties of an existing log.
The first 2 cases are straightforward, as described at the end of Section 4.4.6. Imagine
you have already assigned logX to a location. To change the destination to logY in the
next reloading, do the following in the configuration file:
com.sap.foo.logs
= logY
logX is removed.
To add to the existing logX:
com.sap.foo.logs
= + logY
Summary highlights
The syntax rule described in the Javadoc API helps you to validate your syntax, but perhaps
it is not too clear what attributes/values can be paired/assigned with/to what objects. Or
what are required, what are optional (refer to Appendix C for default values). The summary
below highlights the semantics. Note that the list is not exhaustive, a good trick is referring
to the Javadoc API for a reasonable semantics.
Class
Possible
Attribute
LogController
severity
effSeverity
minSeverity
maxSeverity
logs
localLogs
privateLogs
filters
bundleName
Log
FileLog
Formatter
severity
effSeverity
encoding
formatter
filters
pattern
limit
cnt
pattern
Reference to API
Multiple
entries
Required
X
X
X
X
X
X
For primitive data type, you can easily assign an integer or string as an attribute value
(except Severity, see below). For attribute that takes a class, as listed above, such as Log,
Formatter, you will either use the classname directly (using default setting, see Section
4.6.2.1) or use the notation of a variable (see Section 4.6.2.2).
For the case of interface Filter, assign the fully qualified classname of the user-defined
class (make sure the class is already included in the classpath, and use an appropriate class
loader). As a matter of fact, this applies to user-defined classes for Log and Formatter as
well: use a full classname in case you are not using the standard classes provided by the
SAP API.
Attribute
Type
Possible Value
Description
severity, effSeverity,
minSeverity, maxSeverity
Integer
NONE
logs
(classname)
logs (variable)
formatter (classname)
formatter
Filters
(variable)
(classname)
Log
Formatter
Filter
(interface)
FATAL
ERROR
WARNING
INFO
PATH
DEBUG
ALL
FileLog
ConsoleLog
log[<id>]
TraceFormatter
ListFormatter
XMLFormatter
formatter[<id>]
com.sap.um.logg
ing.Filter
Again, case-sensitive
<id> can be any logical, meaningful name
If you understand the concept of relative severities (refer to Section 4.5.3) and would like to
use it, this can be expressed in the properties file as well. Again, use the notation of square
brackets.
Class
Attricute of Relative
severity
LogController
severity[<full name of relative
location or category>]
effSeverity[<full name of
relative location or category>]
minSeverity[<full name of
relative location or category>]
maxSeverity[<full name of
relative location or category>]
Reference to API
Category.getCategory(/System/Infrastructure/Database);
_cat.setEffectiveSeverity(_loc, Severity.WARNING);
4.6.2.5
Notes
formatter[Trace].pattern
= + log[Console], log[File]
= ConsoleLog
= ListFormatter
= FileLog
= %t/trace.log
= formatter[Trace]
= TraceFormatter
= %s: %24d: %m
Interestingly, order of severity assignment is not affected either. The severity inheritance is
controlled by the closest ancestor who has severity explicitly assigned.
com.sap.foo.fooChild.severity
= INFO
com.sap.foo.severity
= WARNING
= ConsoleLog
= ListFormatter
= XMLFormatter
= + ConsoleLog
= + FileLog
= + ConsoleLog, FileLog
5. Administrative issue
5.1
Examples
A few potential mistakes are invalid severity definition, poor configuration, meaningless null
message string, wrong resource bundle information, etc. These can be rectified internally and a
message is logged to indicate the problem without terminating the program. There are several
Tutorial Logging & Tracing Mechanism in SAP
By: Infrastructure Management Team
ways to replace the erroneous value with the best-guess value: using default value (refer to
Appendix C) or estimating the closest value or simply ignoring it. For example:
Invalid configuration for FileLog for the pair of parameters limit and cnt. The default
setting for FileLog will be used, that is, limit and cnt will be both equal to zero.
For some reasons, if severity level has been out of the range of the defined Severity.MAX
and Severity.MIN, severity will be corrected to the closest limit (MIN or MAX)
If a typo occurs in defining a Log or Formatter, say in the configuration file, the value will
be ignored and nothing will be assigned
A message string or message code should not be a null string, but when this happens, a
constant <null> will be assigned.
When a message code cannot be resolved to a localized string, the value of message code
will be used directly
Note: exceptions generated from methods that are called in static field declarations and initializers
do lead to immediate program termination upon class loading. Therefore, errors like this can be
cited before software distribution.
5.2
5.3
standard, mainly focusing on leaving your development code intact, with minimal penalty on
code modification. Howevre, currently, the loggingWrapper.jar is not publicly available.
Another wrapper implementation has been done for JDK1.4 developers to internally map to the
SAP logging API and objects. It is more versatile to use this wrapper for the standard API as you
have a choice to mingle the use of both the standard API and SAP API or simply stick with one
API. Coding and configuration can be reused readily with minimal penalty.
For more information about this, please refer to the Javadoc for this package:
com.sap.tc.loggingWrapper. Currently, the loggingWrapper.jar is not publicly available.
6. Future Development
6.1
6.2
Log console
This provides an interactive interface for users to easily manipulate the logging tool to suit their
needs, on both the logging behavior and the logging output. The current list of tasks is:
A message viewing tool
Options to allow selectively display trace and log messages
Interactive configuration (including starting and stopping the tool)
Support message translation at the time of viewing
This will be started by the InQMy group for the InQMy server.
6.3
Thread-specific tracing
Thread-specific and business-process-specific tracing is a well-known problem with server-based
systems. The execution of a single request might span across several servers (threads) and cause
problems. It is tricky to trace and analyze such request.
Even if it is possible to tightly time a temporary modification of the global settings (within one
VM) of the Logging API, you usually get lots of messages from other requests that you are not
interested in. This hurts the system performance as well.
Thread-specific tracing allows the configuration specific to a single thread: above all setting a
lower severity for tracing in that single thread. In principle, this is done by putting these parts of
the configuration into a ThreadLocal. Based on these thread-specific settings, settings specific to a
request spanning several servers (threads) and even systems can be implemented (businessprocess-specific tracing).
To this end, the first thread in the chain packs its settings (which it gets from the front-end or a
corresponding properties file) into a transfer object. It then hands over this transfer object as an
argument to subsequent threads executing sub-requests. These threads in turn register the transfer
object with the Logging API, thus inheriting settings from callers. After finishing the request, the
Logging API is called again to forget about the settings specified via the transfer objects.
Appendix A
Severity Levels
The following are the different levels of severity, in ascending order:
Severity
MIN
DEBUG
Value
0
100
PATH
200
INFO
300
WARNING
400
ERROR
500
FATAL
600
MAX
700
Details
Minimum restriction
For debugging purpose, with extensive and low level
information
For tracing the execution flow, e.g. used in the context of
entering and leaving a method, looping and branching
operations
Informational text, mostly for echoing what has been
performed
Application can recover from anomaly, and fulfill the
desired task, but need attention from developer/operator
Application can recover from error, but cannot fulfill
desired task due to the error
Application cannot recover from error, and the severe
situation causes fatal termination,
Maximum restriction
Here are the other 2 useful severity keywords that will totally enable and disable tracing/logging:
Severity
ALL
NONE
Value
0
701
Details
Output messages of all severity
No messages will be logged
Appendix B
Overview of Classes Hierarchy
Logging Manager
Log Controller
Category
Filter
Location
Filter
Log
Formatter
StreamLog
FileLog
ConsoleLog
ListFormatter
TraceFormatter
XMLFormatter
Appendix C
Default behavior of certain objects
Class
Attribute
Default Value
Description
LogController
Severity
MinSeverity
MaxSeverity
<output logs>
<filters>
Severity
<filters>
Formatter
Formatter
Limit
Severity.NONE
Severity.ALL
Severity.NONE
<none>
<none>
Severity.ALL
<none>
TraceFormatter
ListFormatter
0
No output at all
No floor restriction: out all
No ceiling restriction: output nothing
No output at all
Log
ConsoleLog
FileLog
Count
TraceFormatter
Pattern
ListFormatter
Pattern
XMLFormatter
Pattern
0
%24d %-40l [%t] %s: %m
No further filtering
Do not further suppress messages
No further filtering
Class
Property
Default Value
Description
Location
root name
Category
root name
FileLog
Filename,
with size limit
and count
Filename, if
not specified
by user
Message
displayed
<filename>.<ext>.cnt
%t/trace.log
Eg. C:\temp\trace.log
Content of MsgClear
in any case
Message
displayed
Message
displayed
Output
Behavior by
relative
Optional
Trace
TraceFormatter
ListFormatter
XMLFormatter
Location or
Category with
relative A
Optional
Nothing will be output
by relative A