How Do I Log a Stacktrace Using Java's Logger Class
I Am Using Java's Logger Class. I Want to Pass Ex. printStackTrace() into Logger. Log(Loglevel, String), but printStackTrace() Returns Void. So I Am Not Able...
I am using Java's Logger class. I want to pass ex.printStackTrace() into Logger.log(loglevel, String), but printStackTrace() returns void. So I am not able to pass and print the stack trace of the exception.
Is there any way that I can convert void into String, or are there any other methods to print the whole stack trace of exceptions?
13 Answers
You need to understand that void is actually nothingness. You cannot convert what is nothing. You might end up printing void as a string, but (trust me), you don't want that.
I think what you are looking for is
// assuming ex is your Exception object
logger.error(ex.getMessage(), ex);
// OR
Logger.log(errorLogLevel, ex.getMessage(), ex)
This will print the error message using the logger that you have configured. For more details, you can take a look at the java docs for Exception#getMessage()
Use java.util.logging.Logger#log(Level, String, Throwable) and pass in ex as third argument like this:
LOGGER.log(Level.INFO, ex.getMessage(), ex);
Also another alternative would be:
import org.apache.commons.lang3.exception.ExceptionUtils;
log.error("Exception : " + ExceptionUtils.getStackTrace(exception));
There's an overloaded printStackTrace method that takes in a PrintWriter.
You can do something like this
Writer buffer = new StringWriter();
PrintWriter pw = new PrintWriter(buffer);
ex.printStackTrace(pw);
Logger.log(loglevel, buffer.toString());
With below format you can have the stack trace:
java.util.logging.SimpleFormatter.format=%1$tF %1$tT [%4$-7s][%2$s] %5$s %6$s%n
The point in this pattern is %6$s. It will print the stack trace.
You can't convert void into String; no such conversion exists. void doesn't return anything back, so you have no value to retrieve.
What you probably want to do is get the message of the exception instead via ex.getMessage().
You can use the getStackTrace() method to get an array of StackTraceElements, and generate a String from there. Otherwise, if just the final error message is sufficient, use the getMessage() method as suggested by Makoto.
To get the stack trace as a String from an array of StackTraceElement objects, you need to iterate over the array (taken from JDK7 source):
StringBuilder builder = new StringBuilder();
StackTraceElement[] trace = getOurStackTrace();
for (StackTraceElement traceElement : trace)
builder.append("\tat " + traceElement + "\n");
Another option is to use printStackTrace(PrintStream s), where you get to specify where you want the stacktrace to be printed:
ByteArrayOutputStream out1 = new ByteArrayOutputStream();
PrintStream out2 = new PrintStream(out1);
ex.printStackTrace(out2);
String message = out1.toString("UTF8");
You can use an ExceptionUtils if you need to see stacktrace without throwing Exception.
String stackTrace = ExceptionUtils.getStackTrace(new Exception("YourMessage"));
log.error(stackTrace);
you CAN convert stacktrace into String using below. If e is the exception object
StringWriter stringWriter= new StringWriter();
PrintWriter printWriter= new PrintWriter(stringWriter);
e.printStackTrace(printWriter);
String stackTraceAsString= stringWriter.toString();
Thank you all. I am able to log the stack trace details using
LOGGER.log(Level.INFO, ex.getMessage(),ex);
//ex is my exception object
As Makoto says, you probably want to do an ex.getMessage().
To further clarify, void means that there is nothing returned. You can't cast nothing into something :)
You can also use ExceptionUtils from apache library or below log statement
try{
doSomething();
}
catch(Exception e){
log.error("Exception in method doSomething ",e);
}
The previous suggestions all seem to just put the stack trace in the log without prefixing each line with the logger details. My suggestion below processes the stack trace elements and formats each line as a logger line:
log.error("{}", e.toString());
StackTraceElement[] stElements = e.getStackTrace();
log.error("(stacktrace) {}", e.toString());
for (StackTraceElement ste: stElements) {
log.error("(stacktrace) at {}.{}({}.java:{})",
new Object[] {ste.getClassName(), ste.getMethodName(),
ste.getClassName(), ste.getLineNumber()});
}
Throwable thisThrowable = e;
boolean causedBy = true;
while (causedBy) {
Throwable throwable = thisThrowable.getCause();
if (throwable != null) {
log.error("(stacktrace) Caused by: {}", throwable.toString());
stElements = throwable.getStackTrace();
for (StackTraceElement ste: stElements) {
log.error("(stacktrace) at {}.{}({}.java:{})",
new Object[] {ste.getClassName(), ste.getMethodName(),
ste.getClassName(), ste.getLineNumber()});
}
thisThrowable = throwable; // For the next caused-by check
} else {
log.error("(stacktrace) No Caused-by Exception");
causedBy = false; // No more caused-by Throwables, so end the loop
}
}
Each line of the stack trace is prefixed with "(stacktrace)". This has the advantage of being able to filter them out when dumping log files, or to be able to find them easily.