0

For a rarely occurring condition in a method which is called from different sites, I'd like to have the stack trace in the log. The exceptional conditions are note detected via exceptions, that is, there is no try-catch.

The only way I'm aware if is to use a fake exception, like this:

static void logWithStacktrace(Logger logger, Priority p, String msg) {
    try {
        throw new AssertionError();
    } catch (AssertionError e) {
        logger.log(p, msg, e);
    }
}

Is there a good way to do this without raising an exception? Maybe there is there a log4j feature I've overlooked? I'm looking for a solution that formats the stack trace as in real exception messages - ideally it would end up as a <log4j:throwable> element in the XML log file. Using Thread.getStackTrace and formatting it myself doesn't let me do that.

I'm aware that "rarely occurring" sort of screams for the code to be refactored to use exceptions. On the other hand, all I would do with the exceptions is to log them, since the problems are not really errors but an indication of questionable API usage. So it seems sort of contrived not to log them directly.

Chris
  • 4,133
  • 30
  • 38

2 Answers2

1

Several of the log4j methods accept a Throwable object. A Throwable contains a snapshot of the execution stack of its thread at the time it was created. You should be able to use this as follows:

static void logWithStacktrace(Logger logger, Priority p, String msg) {
    logger.log(p, msg, new Exception());
}
GeekyDeaks
  • 650
  • 6
  • 12
  • How obvious in retrospect. Thanks. It also has the advantage that I can write it in-line, and then there's no superfluous `logWithStacktrace` in the stack trace. – Chris Jun 30 '14 at 14:08
0

You could try the following:

Thread.currentThread().getStackTrace();

This returns an array of StackTraceElement that you can loop round and process as required. Just note that the first element is usually the getStackTrace() call, so you probably want to skip it.

GeekyDeaks
  • 650
  • 6
  • 12
  • :) someone got in whilst I was typing – GeekyDeaks Jun 30 '14 at 13:03
  • Thanks - that's always an option, but not really what I was looking for. I've updated the question to clarify the intent. – Chris Jun 30 '14 at 13:19
  • I have probably misunderstood, but log4j allows you to send Throwable objects as a third parameter to .log (and you are using it in your example). Have you tried just creating a new Throwable (e.g. Exception e = new Exception();) and then passing that to log4j as before - logger.log(p, msg, e); – GeekyDeaks Jun 30 '14 at 13:49
  • 1
    Actually you could probably just have `logger.log(p, msg, new Exception());` – GeekyDeaks Jun 30 '14 at 13:51
  • :-O - I think you got it. If edit your answer, I'll accept it. – Chris Jun 30 '14 at 13:59