How do I log a stacktrace using java's Logger class
Asked Answered
T

17

70

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?

Transmigrant answered 14/7, 2015 at 19:1 Comment(3)
in short : NO, u can not.Journalist
Sure, use this: commons.apache.org/proper/commons-lang/javadocs/api-3.4/org/… from commons-lang3 3.4Yonder
What sort of string value would "nothing" be turned into?Petersen
H
71

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()

Hebraism answered 14/7, 2015 at 19:5 Comment(7)
Thanks Saif Asif. I am able to log the whole stack trace now.Transmigrant
logger.error() is not java.util.logging, but I'm not going to downvote you because I am glad to discover logger.log(Level, Exception, Supplier) . Looks like Oracle have made java.util.logging.Logger seriously ugly! Since they were doing that, it's strange that they didn't take it further and create logger.severe(String, Exception) etcAeneous
The question asks for a solution using Java's Logger class. java.util.logging.Logger does not have a method called "error". I have downvoted this answer only because of that.Altheta
@Aeneous I agree that logger.error() looks ugly, but it is highly readable, and it is the way it is done in other simple languages like python, so it is not so terribly bad.Twinge
This is not answering the initial intention to print the stack trace to a logger, at all. getMessage() is not made for this.Limbourg
So, the answer is: logger.log(Level.SEVERE, ex.getMessage(), ex);Krasner
The output is an exception, but no a stack of suchHolmium
J
42

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);
Jemima answered 14/7, 2015 at 19:8 Comment(4)
I'm not getting stack trace to log with this, only the second argument.Rod
It is possible to suppress the stack trace by changing the log format. Which formatter are you using and how does your log format look like?Jemima
This is the real answer to the question.Kingmaker
@PanuHaaramo It depends on which formatter you use. The formatter needs to call record.getThrown() in format. Take a look at SimpleFormatter.Kingmaker
E
29

Also another alternative would be:

import org.apache.commons.lang3.exception.ExceptionUtils;

log.error("Exception : " + ExceptionUtils.getStackTrace(exception));
Eider answered 19/4, 2018 at 12:53 Comment(1)
If you're refering to org.apache.commons.lang3.exception.ExceptionUtils, it's ExceptionUtils.getStackTrace(e)Baculiform
H
17

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());
Hertzog answered 14/7, 2015 at 19:21 Comment(1)
This is the simplest method IMHO and it really prints the stack trace, not only the message.Sebaceous
B
13

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.

Brigette answered 8/8, 2018 at 5:4 Comment(0)
Y
6

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");
Ypres answered 14/7, 2015 at 19:7 Comment(3)
Just use the apache commons ExceptionUtils library; no need to reinvent the wheelDoctrine
1. String message = out1.toString("UTF8"); - compilation error, expected 0 parameterers, but got 1 2. It works correctly out2.out.toString. In case out2.toString -> 'PrintStream@hash'Excrescence
PrintStream uses UTF-8 by default or should encoding be specified by constructor ´PrintStream(String file, boolean autoFlush, Charset cs)´ ?Holmium
B
5

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().

Burgett answered 14/7, 2015 at 19:2 Comment(0)
S
2

You can use an ExceptionUtils if you need to see stacktrace without throwing Exception.

String stackTrace = ExceptionUtils.getStackTrace(new Exception("YourMessage"));
log.error(stackTrace);
Sinfonietta answered 23/10, 2020 at 8:11 Comment(0)
B
1

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(); 
Buddy answered 14/7, 2015 at 19:19 Comment(0)
T
1

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
Transmigrant answered 14/7, 2015 at 19:30 Comment(0)
B
1

With java.util.Arrays you can also solve this easily:

try {
    doSomething();
} catch (Exception e) {
    logger.error(Arrays.toString(e.getStackTrace()));
}

Arrays.toString(Object[] a) calls Object.toString() for each element or returns a String with "null" if the object is null. The elements are separated by a comma and a space. StackTraceElement implements toString(), so the array you get from e.getStackTrace() converts nicely.

Blakely answered 28/12, 2022 at 16:18 Comment(0)
D
0

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 :)

Downswing answered 14/7, 2015 at 19:5 Comment(1)
He wants a stack trace, not just the message.Calhoun
D
0

You can also use ExceptionUtils from apache library or below log statement

    try{
      doSomething();
    }
    catch(Exception e){
    log.error("Exception in method doSomething ",e);
    }
Dunstable answered 28/10, 2019 at 9:50 Comment(0)
P
0

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.

Predecessor answered 18/6, 2021 at 14:14 Comment(0)
T
0

Below set of code can be used.

public static Connection openConnection()  {
        Connection con = null;
        try {
            // load the driver
            
            //System.out.println("Load JDBC Driver");
            DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
        }
        catch (SQLException e) {
            logger.info("FAILED TO LOAD JDBC DRIVER");
            //System.out.println("Fail to Load JDBC Driver ");
            logger.error(e.getMessage(), e);
            return null;
        }
Tajo answered 14/11, 2023 at 11:8 Comment(0)
R
0
log.error("Add some message, otherwise we wont get stacktrace with out some message ", exception)

This will display stacktrace.

Ress answered 20/11, 2023 at 10:58 Comment(0)
R
0

I find myself in an old system where I can't change the logger. To put stacktrace in the log, I use primitive method like this:

        StringBuilder sb = new StringBuilder();
        for(StackTraceElement st : e.getStackTrace()) {
            sb.append("\n" + st.toString()  );
        }
        log.createError(sb.toString());

This will produce the a simple e.printStackTrace().

Ringed answered 6/5 at 8:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.