Write stack trace of an exception into a file with Byteman

356 views Asked by At

I have a framework that ignores exceptions in it, and I want to inspect the cause of these exceptions. I am trying to use Byteman to do it.

Byteman can write the message of an exception, or call stack of the target method itself into a log file like this:

RULE PrintStackTrace
CLASS org.example.TargetClass
METHOD targetMethod
AT EXCEPTION EXIT
IF true
DO
  traceOpen("log", "/tmp/byteman.log");
  traceln("log", $^.getMessage());
  traceStack(null, "log");
  traceClose("log");
ENDRULE

But I couldn't find the way to write the result of printStackTrace() of the exception ($^). $^.printStackTrace() writes the stack trace into the console, but the redirection like 2>&1 logfile didn't work to write the stack trace to a file.

Is there any way to write the stack trace of a exception ($^) into a file with Byteman?

1

There are 1 answers

0
Byteman Project On BEST ANSWER

It is possible to do this but only if you supply a custom Helper class.

You can get part way to the solution by calling

$^.getOurStackTrace()

This is a private method of Throwable which returns a StackTraceElement[]. This is the tyep used to assemble the data printed by printStackTrace. The base class of the returned array, StackTraceElement, has a toString() method that prints the method, file and line number for each successive element in the Throwable's stack backtrace. So, if you define your own Helper class as follows you can use it to print a stack trace to a trace file using the trace method inherited from Helper:

package org.my;
import org.jboss.byteman.rule.helper.Helper

class MyHelper extends Helper {
  public void traceStackElements(Object traceFile,
                                 Throwable t,
                                 StackTraceElement[] elements) {
    traceln(tracefile, t.toString());
    for (int i = 0; i < elements.length; i++) {
      traceln("  at " + elements[i].toString());
    }
  }
}

You rule needs to specify MyHelper as its helper class and call this extra builtin.

RULE PrintStackTrace
CLASS org.example.TargetClass
METHOD targetMethod
AT EXCEPTION EXIT
HELPER org.example.MyHelper
IF true
DO
  traceOpen("log", "/tmp/byteman.log");
  traceStackElements("log", $^, getOurStackTrace());
  traceClose("log");
ENDRULE

You will need to compile MyHelper against byteman.jar which defines the standard Helper class. You will also ensure the class is located in the classpath so it can be resolved when the rule is injected.