Tracing
Content
Introduction
JEAF X-Fun's tracing is like an abstraction for many other tracing solutions that are available. When writing your application code you do not have to care about the tracing solution that should be used in the current environment. Therefore JEAF defines a Tracing API that is independent from any implementation. In addition to regular tracing it also adds some feature that are very helpful in enterprise environments.
JEAF knows the following trace levels trace (ordered from low to high):
TRACE
,DEBUG, INFO, WARN, ERROR, FATAL
Full example class can be found here: TracingSample.java
Simple Tracing
One big difference to other tracing solutions is that JEAF's API does not require something like a logger. Instead the logger is taken from the context. This means that the current service / component from which the tracing is called is used to identify the needed "Logger". Idea behind that is that enterprise applications are usually separated into multiple services. When it comes to tracing then it's sufficient to configure tracing on the level of services / components. Through this approach usage of the API is simpler and less error-prone. If tracing is called not from within a service then the logger of the application will be used.
Simple tracing with JEAF X-Fun
// First let's start with simple tracing.
Trace lTrace = XFun.getTrace();
lTrace.trace("Message with level TRACE");
lTrace.debug("Message with level DEBUG");
lTrace.info("Message with level INFO");
lTrace.warn("Message with level WARN");
lTrace.error("Message with level ERROR");
lTrace.fatal("Message with level FATAL");
This will cause the following output in logs. As you can see on the generated output the so called Application-ID is used as logger as we called the tracing not from within a service call.
TRACE XFunSampleApp - Message with level TRACE
DEBUG XFunSampleApp - Message with level DEBUG
INFO XFunSampleApp - Message with level INFO
WARN XFunSampleApp - Message with level WARN
ERROR XFunSampleApp - Message with level ERROR
FATAL XFunSampleApp - Message with level FATAL
In addition to standard tracing JEAF X-Fun also offers additional features that help in enterprise environments. One example therefore is classes from JEAF's Internationalization features such as MessageID
and ErrorCode
can be directly used in Tracing-API. There you have the option to programmatically define the trace level or you can use the trace level that was defined in the message resource. In general it's recommend to not overwrite the trace level from the message definition.
Tracing in combination with ErrorCode / MessageIDs
lTrace.info(AccountingMessages.BANK_BALANCE_NOT_SUFFICIENT);
lTrace.write(AccountingMessages.BANK_BALANCE_NOT_SUFFICIENT);
// Of course same as for messages also traces can be parameterized. In order to avoid
// garbage JEAF only converts the error code and it's parameters into a message string
// if the trace level is enabled.
lTrace.info(AccountingMessages.BANK_BALANCE_NOT_SUFFICIENT, "100.00 EUR");
lTrace.write(AccountingMessages.BANK_BALANCE_NOT_SUFFICIENT, "100.00 EUR");
Log output
INFO XFunSampleApp - [20002] Money transfer failed. Transaction amount: {0}
INFO XFunSampleApp - [20002] Money transfer failed. Transaction amount: {0}
INFO XFunSampleApp - [20002] Money transfer failed. Transaction amount: 100.00 EUR
INFO XFunSampleApp - [20002] Money transfer failed. Transaction amount: 100.00 EUR
Additional Tracing Features
In many cases there are several places inside your code where you want to log the same information about an object. Instead of implementing a trace specific variant of toString()
you also have the option to make use of a so called ObjectFormatter
. This is a class that provides a string representation of an object for tracing.
As the code below shows the implementation of such an ObjectFormatter
is pretty simple. As you can see the trace output of an object can also vary depending on the current trace level.
Implementation of an ObjectFormatter
/**
* Class implements a {@link ObjectFormatter} for Books.
*
* As we have JEAF Maven Plugin integrated into our build process the only configuration
* that is required is annotation @TraceObjectFormatter here on this class.
*
* Annotation {@link TraceObjectFormatter} requires that you define all the classes for
* which the formatter is responsible. In case of inheritance it's sufficient to only
* define the base class.
*/
@TraceObjectFormatter(supportedClasses = Book.class)
public class BookFormatter implements ObjectFormatter {
@Override
public String formatObject( Object pObject, TraceLevel pTraceLevel ) {
// As we registered this formatter only to "Books" JEAF will ensure that only
// "Books" will be passed.
Book lBook = (Book) pObject;
// As the current trace level is also passed as parameter it is also possible to
// vary the generated output depending on the current trace level.
String lString;
switch (pTraceLevel) {
// On leveles TRACE and DEBUG we want to trace some more information
case TRACE:
case DEBUG:
lString = "'" + lBook.getTitle() + "' by " + lBook.getAuthor() + " published in "
+ lBook.getPublishingDate().get(Calendar.YEAR);
break;
// Default trace representation
default:
lString = lBook.getTitle() + " (" + lBook.getAuthor() + ")";
}
return lString;
}
}
The tracing of the object itself is very simple.
Tracing with ObjectFormatter
// Sometimes there are cases where you want to have a special trace output about an
// object. In this case it's possible to hand over the object to JEAF Tracing. In this
// case JEAF will make use of a so called TraceObjectFormatter
Book lBook = new Book();
lBook.setAuthor("Stephen Hawking");
lBook.setTitel("A Brief History of Time");
lBook.setPublishingDate(new GregorianCalendar(1988 + 1, 0, 0));
// This will produce the following log:
// A Brief History of Time (Stephen Hawking)
XFun.getTrace().infoObject(lBook);
// While on level DEBUG we will see some additional information:
// 'A Brief History of Time' by Stephen Hawking published in 1988
XFun.getTrace().debugObject(lBook);
Log output
INFO XFunSampleApp - A Brief History of Time (Stephen Hawking)
DEBUG XFunSampleApp - 'A Brief History of Time' by Stephen Hawking published in 1988
Fallback when no ObjectFormatter is defined
// In case that there is no formatter defined for a class then the objects toString() will
// be called by JEAF. In the example below this will result in "... I'm just a closet"
//
// However this variant of tracing objects is not recommended as it pollutes our business
// object with technical information about tracing :-(
Closet lCloset = new Closet();
XFun.getTrace().infoObject(lCloset);
Closet.java
public class Closet {
@Override
public String toString( ) {
return "I'm just a closet";
}
}
Log output
INFO XFunSampleApp - I'm just a closet