SherLog enables the integration of logging statements into an Java Enterprise Application at runtime. It provides several out-of-the-box
implementations for performance measurement or logging of instance variables. This way SherLog can help you find the reason for bugs, performance issues or other problems without stopping and re-starting your application server.
Moreover, SherLog can be extended in an easy manner, offering interfaces for your own logging integration implementations.
- JDK 8 or higher
- JBoss WildFly 8.0.0 or higher
Follow these steps to build and package SherLog:
$ git clone https://github.com/PaddySmalls/BIG-SherLog.git
$ cd BIG-SherLog/
$ mvn clean package
After a successful build the generated JAR can be found in the target subfolder.
Caution: Make sure that the SherLog JAR resides on the classpath of the app you want to debug when it's built and deployed. Only then our class which is responsible for logging can be found by WildFly's ModuleClassloader!
In order to be able to use SherLog, your JBoss AS configuration has to be customized. Assuming you're running a Windows machine, open standalone.conf.bat (under Linux environments it's standalone.conf) in your favorite test editor and append the following lines right on top of the file:
These lines prepare JBoss for being accessible via JMX:
set "JAVA_OPTS=%JAVA_OPTS% -Dcom.sun.management.jmxremote.port=1090"
set "JAVA_OPTS=%JAVA_OPTS% -Dcom.sun.management.jmxremote.authenticate=false"
set "JAVA_OPTS=%JAVA_OPTS% -Dcom.sun.management.jmxremote.ssl.need.client.auth=false"
set "JAVA_OPTS=%JAVA_OPTS% -Dcom.sun.management.jmxremote"
set "JAVA_OPTS=%JAVA_OPTS% -Dcom.sun.management.jmxremote.ssl=false"
Because SherLog has to be ran as a Java agent, making JVM call a premain method right before regular server startup, we have to add additional JARs to JBoss classpath manually. Doing so, we can avoid JBoss complaining about missing logmanager setup on agent startup:
set "JAVA_OPTS=%JAVA_OPTS% -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
set "JAVA_OPTS=%JAVA_OPTS% -Xbootclasspath/p:%JBOSS_HOME%/modules/org/jboss/logmanager/main/jboss-logmanager-1.2.2.GA.jar"
set "JAVA_OPTS=%JAVA_OPTS% -Djboss.modules.system.pkgs=org.jboss.logmanager"
Since SherLog uses Apache log4j for producing it's output and ships with it's own log4j.properties file, we have to override WildFly's standard log4j configuration. Insert the following line in standalone.xml file to the logging subsystem:
<subsystem xmlns="urn:jboss:domain:logging:2.0">
<add-logging-api-dependencies value="false"/>
...
</subsystem>
With our JBoss configuration prepared, we're almost done. What's left do is to start our Java EE Application with the -javaagent parameter and pass it the location of the SherLog JAR we built at the beginning.
Extend your WildFly run configuration in your favorite IDE with the following JVM argument:
-javaagent:C:\path\to\sherlog_jar\sherlog.jar
In case you're running WildFly from command line, make sure the JVM argument is added to standalone.conf.bat.
Having applied all the steps so far you now should be able to connect to SherLog. Open jconsole and setup a connection to your application, i.e. the according WildFly process. Inspect the list of MBeans registered in the running MBean server and search for a MBean named com.big.sherlog.InstrumentationService. This MBean offers several operations that you can immediately try out in the context of your own application.
Customizing SherLog to your own needs is very simple and unextensive. The first thing you have to do is to write a class extending SherLogs BaseCodeIntegrator class:
public class MyCustomCodeIntegrator extends BaseCodeIntegrator {
@Override
protected CtMethod enhanceMethodCode(CtMethod ctMethod) {
// ... your code goes here
return ctMethod;
}
}
The enhanceMethodCode method leaves the choice of what kind of modification should be done upon to you. However, consider that Java Instrumentation API (which SherLog is heavily based on) introduces some restrictions on what kind of changes can be performed on classes already loaded by JVM. To insert your own logging statements use BaseCodeIntergators static variable PROVIDED_LOGGER. This variable refers to a pre-configured Logger that puts it's output into a users home directory.
The final step that has to be taken is to register your own custom Transformer extending SherLogs BaseTransformer base class:
@Transformer
public class MyCustomTransformer extends BaseTransformer {
public MyCustomTransformer() {
super(new MyCustomCodeIntegrator());
}
}
As you may see, all that remains to do is to subclass BaseTransformer and pass it an instance of your BaseCodeIntegrator subclass. Mind the @Transformer annotation on top of MyCustomTransformer. This enables SherLog to recognize your class a selectable transformer on server startup and it will show up in the transformer list of our MBean in jconsole.
The SherLog Debugging Tool has been developed in the context of my bachelor thesis at Bertsch Innovation GmbH (Stuttgart/Germany). Implemented to support developers and project leads in their daily work by faciliating quick debugging without stopping and restarting the application server, it's name infers from the probably most popular detective in the world.
*Caution: As for now, it will be exlpained how to setup and use SherLog in WildFly 8 environment. Further documentation for Tomcat etc. will follow soon.