Saturday, July 28, 2012

byteman example : enable debug logging

A quick introduction to byteman: Built by the jboss community, it allows you to add code to your existing java program on the fly.

It is very handy in situations like:
  • You want to print a parameter value on the method (better yet, run a getter chain on it)
  • Change return value of the method
  • Know what's going on in code that you don't own
  • ...
This demonstration is to enable debug logging for log4j. Obviously there are other ways to enable debug logging for log4j, but it is useful in situations where you don't have write access to the config file, or you don't know what config file to change.

Here is a typical call to log something in debug - protected by a isDebugEnabled() call.

if (logger.isDebugEnabled())
{
    logger.debug("The parameter value " + param + " is valid");
}

We have to make sure the isDebugEnabled returns true, and then the call to debug goes through overriding the internal log4j check to verify if debug is indeed enabled.

Byteman works with rules, here we are creating two rules to make sure debug log is written.

Rule 1: make sure isDebugEnabled() returns "true"

RULE enable debug logging
    CLASS org.apache.log4j.Category
    METHOD isDebugEnabled()
    AT ENTRY
    IF true
    DO return true
ENDRULE

Rule 2: call the forcedLog() when logger.debug() is called

RULE force debug logging
    CLASS org.apache.log4j.Category
    METHOD debug(java.lang.Object)
    AT ENTRY
    IF true
    DO $0.forcedLog(org.apache.log4j.Category.FQCN, org.apache.log4j.Level.DEBUG, $1, null)
ENDRULE

Attach byteman to your jvm: The following command will deploy byteman agent into your running jvm (pid), and listens at port 6666. More help here

java -jar lib/byteman-install.jar -h localhost -p 6666 --pid--

Deploy the rules file:
java -classpath lib/byteman.jar:lib/byteman-submit.jar \
    org.jboss.byteman.agent.submit.Submit \
    -h localhost -p 6666 -path to script-

Now, debug logging should be enabled for all categories now. If you want to filter only a certain logger, you can modify the rule which returns true on isDebugEnabled as follows

RULE Enable debug logging
    CLASS org.apache.log4j.Category
    METHOD isDebugEnabled()
    AT ENTRY
    BIND constant:string = "NAME OF MY LOGGER"
    IF $0.getName().contains(constant)
    DO return true
ENDRULE

When you are done, remove all the rules

java -classpath lib/byteman.jar:lib/byteman-submit.jar \
    org.jboss.byteman.agent.submit.Submit \
    -h localhost -p 6666 -u

That's it, download Byteman and instrument your code.