← Back to LTTng's blog

Tutorial: Tracing Java Logging Frameworks

Comments

The LTTng-UST project is quite useful to instrument and trace C/C++ applications. In recent versions of the user space tracer, it is now possible to trace Java applications by leveraging existing Java logging frameworks. In practice, the messages logged by the framework will be rerouted to the user space tracer, hence a comprehensive view of the application stack and interaction with the rest of the system can be obtained. As of version 2.6, LTTng-UST supports two Java logging frameworks:

In this tutorial, we will see how to build LTTng-UST with the Java agent, how to instrument existing Java applications, and, finally, how to obtain traces resulting from the execution of those programs.

Building LTTng-UST with Java agent support

In order to use LTTng with Java applications, LTTng-UST needs to be built with Java agent support. Some Linux distributions may already have LTTng-UST packages including support for Java applications. If not, you will need to build LTTng-UST from source with the following configuration flags.

The configure script will automatically detect the appropriate Java binaries to use in order to build the Java agent.

Java agent with JUL support:

./configure --enable-java-agent-jul

Java agent with log4j support:

To build the agent with log4j support, make sure that the log4j JAR file is in your Java classpath.

export CLASSPATH=$CLASSPATH:/path/to/log4j.jar
./configure --enable-java-agent-log4j

Java agent with JUL + log4j support

export CLASSPATH=$CLASSPATH:/path/to/log4j.jar
./configure --enable-java-agent-all

Instrumenting Java applications

In order to trace your application using the existing JUL or log4j logging facility, some snippet of code needs to be added to your application's main or execution loop. The highligted text in the example below show the required lines:

import org.lttng.ust.LTTngAgent;

public class MyApp
{
    public static void main(String[] argv) throws Exception
    {
        // ...

        // Call this as soon as possible (before logging)
        LTTngAgent lttngAgent = LTTngAgent.getLTTngAgent();

        // ...

        // Not mandatory, but cleaner
        lttngAgent.dispose();
    }
}

By calling the LTTngAgent.getLTTngAgent() method, the agent will initialize its communication threads and will be able to communicate with the LTTng session daemon.

From the user's point of view, once the LTTng-UST Java agent has been initialized, JUL and log4j loggers may be created and used as usual. The agent adds its own handler to the root logger, so that all loggers may generate LTTng events with no effort.

Here is a simple example with the JUL framework illustrating the above:

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lttng.ust.agent.LTTngAgent;

public class MyApp
{
	private static final int answer = 42;
	private static LTTngAgent lttngAgent;

	public static void main(String args[]) throws Exception
	{
		Logger helloLog = Logger.getLogger("hello");
		lttngAgent = LTTngAgent.getLTTngAgent();

		Thread.sleep(5000);

		helloLog.info("Hello World, the answer is " + answer);

		lttngAgent.dispose();
	}
}

When building your Java application, you need to make sure that the Java agent JAR file, liblttng-ust-agent.jar, is in your classpath. You will find below an example on how to build the sample application with the Java agent support:

export CLASSPATH=$CLASSPATH:/usr/share/java/liblttng-ust-agent.jar
javac -classpath "$CLASSPATH" MyApp.java

Now that we have built the LTTng-UST Java agent and properly instrumented our Java applications, its time to trace!

Tracing the applications

Tracing the application is accomplished via the lttng command line tool. We will need to create a session, enable some JUL or log4j events and then start our applications in order to trace it.

For reference on this procedure, consult the controlling tracing section of the official documentation.

Session setup for JUL logging (-j, --jul domain):

lttng create java-test
lttng enable-event -a -j
lttng start

Alternatively for log4j (-l, --log4j domain):

lttng create java-test
lttng enable-event -a -l
lttng start

Start your Java application:

export CLASSPATH=$CLASSPATH:/path/to/liblttng-ust-java-agent.jar
./MyApp

When you're ready to view the logs, stop tracing and view the resulting trace:

lttng stop
lttng view

which will output something like:

[...]
[02:51:59.050393159] (+?.?????????) kappa lttng_jul:user_event: { cpu_id = 3 }, { msg = "Hello World, the answer is 42", logger_name = "hello", class_name = "MyApp", method_name = "main", long_millis = 1420703518998, int_loglevel = 800, int_threadid = 1 }
[...]

Conclusion

This tutorial covered the LTTng-UST Java agent and how to trace Java applications. At the moment, only the JUL and log4j logging backends are supported but the UST Java agent can easily be extended to support other logging backends.

For a complete reference on how to instrument Java applications using LTTng-UST, see the Java application section in LTTng's official documentation.