Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to send a stacktrace to log4j?

People also ask

How do you print Stacktrace in logs?

To print a stack trace to log you Should declare logger and method info(e. toString()) or log(Level.INFO, e. toString()). Logging is the process of writing log messages during the execution of a program to get error and warning messages as well as info messages.

Should Stacktrace be logged?

Therefore, you should log a stacktrace if, and only if, and always if, the exception indicates a bug in the program. However, that does not always indicate that a method you write should catch and log the exception.

How do you get Stacktrace strings?

The function printStackTrace() of the Exception class can take one parameter, either a PrintStream or a PrintWriter. Thus, it is possible, using a StringWriter, to print the stack trace into a String: StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e. printStackTrace(pw);


You pass the exception directly to the logger, e.g.

try {
   ...
} catch (Exception e) {
    log.error( "failed!", e );
}

It's up to log4j to render the stack trace.


If you want to log a stacktrace without involving an exception just do this:

String message = "";

for(StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) {                         
    message = message + System.lineSeparator() + stackTraceElement.toString();
}   
log.warn("Something weird happened. I will print the the complete stacktrace even if we have no exception just to help you find the cause" + message);

You can also get stack trace as string via ExceptionUtils.getStackTrace.

See: ExceptionUtils.java

I use it only for log.debug, to keep log.error simple.


The answer from skaffman is definitely the correct answer. All logger methods such as error(), warn(), info(), debug() take Throwable as a second parameter:

try {
...
 } catch (Exception e) {
logger.error("error: ", e);
}

However, you can extract stacktrace as a String as well. Sometimes it could be useful if you wish to take advantage of formatting feature using "{}" placeholder - see method void info(String var1, Object... var2); In this case say you have a stacktrace as String, then you can actually do something like this:

try {
...
 } catch (Exception e) {
String stacktrace = TextUtils.getStacktrace(e);
logger.error("error occurred for usename {} and group {}, details: {}",username, group, stacktrace);
}

This will print parametrized message and the stacktrace at the end the same way it does for method: logger.error("error: ", e);

I actually wrote an open source library that has a Utility for extraction of a stacktrace as a String with an option to smartly filter out some noise out of stacktrace. I.e. if you specify the package prefix that you are interested in your extracted stacktrace would be filtered out of some irrelevant parts and leave you with very consized info. Here is the link to the article that explains what utilities the library has and where to get it (both as maven artifacts and git sources) and how to use it as well. Open Source Java library with stack trace filtering, Silent String parsing Unicode converter and Version comparison See the paragraph "Stacktrace noise filter"


Just because it happened to me and can be useful. If you do this

try {
   ...
} catch (Exception e) {
    log.error( "failed! {}", e );
}

you will get the header of the exception and not the whole stacktrace. Because the logger will think that you are passing a String. Do it without {} as skaffman said


In Log4j 2, you can use Logger.catching() to log a stacktrace from an exception that was caught.

    try {
        String msg = messages[messages.length];
        logger.error("An exception should have been thrown");
    } catch (Exception ex) {
        logger.catching(ex);
    }

This answer may be not related to the question asked but related to title of the question.

public class ThrowableTest {

    public static void main(String[] args) {

        Throwable createdBy = new Throwable("Created at main()");
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        PrintWriter pw = new PrintWriter(os);
        createdBy.printStackTrace(pw);
        try {
            pw.close();
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        logger.debug(os.toString());
    }
}

OR

public static String getStackTrace (Throwable t)
{
    StringWriter stringWriter = new StringWriter();
    PrintWriter  printWriter  = new PrintWriter(stringWriter);
    t.printStackTrace(printWriter);
    printWriter.close();    //surprise no IO exception here
    try {
        stringWriter.close();
    }
    catch (IOException e) {
    }
    return stringWriter.toString();
}

OR

StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
for(StackTraceElement stackTrace: stackTraceElements){
    logger.debug(stackTrace.getClassName()+ "  "+ stackTrace.getMethodName()+" "+stackTrace.getLineNumber());
}