Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to prefix every line of a stacktrace in log4j?

Tags:

java

log4j

when you write

logger.error("message", exception);

log4j produces the message and the complete stack trace :

Aug  9 06:26:13 10.175.60.14 myPrefix: [error] [TP-Processor114] [my.class.Name] message : exception
at fatherOfException
at fatherof_fatherOfException
at fatherof_fatherof_fatherOfException
...

my conversion pattern is

log4j.appender.syslog.layout.ConversionPattern=myPrefix: [%p] [%t] [%c] [%x] - %m%n

So, is it possible to prefix every line with myPrefix, as :

    Aug  9 06:26:13 10.175.60.14 myPrefix: [error] [TP-Processor114] [my.class.Name] message : exception
myPrefix    at fatherOfException
myPrefix    at fatherof_fatherOfException
myPrefix    at fatherof_fatherof_fatherOfException
    ...

When I grep my logs on myPrefix, i don't see the stack trace. We have many different prefixes (one per module)

Thanks in advance.

like image 582
Jean-Philippe Caruana Avatar asked Aug 11 '10 14:08

Jean-Philippe Caruana


People also ask

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.

What are the three most important components of log4j?

log4j has three main components: loggers: Responsible for capturing logging information. appenders: Responsible for publishing logging information to various preferred destinations. layouts: Responsible for formatting logging information in different styles.

What is a StackTrace and how does it relate to an exception?

Simply put, a stack trace is a representation of a call stack at a certain point in time, with each element representing a method invocation. The stack trace contains all invocations from the start of a thread until the point it's generated. This is usually a position at which an exception takes place.

What is stack trace exception?

A trace of the method calls is called a stack trace. The stack trace listing provides a way to follow the call stack to the line number in the method where the exception occurs. The StackTrace property returns the frames of the call stack that originate at the location where the exception was thrown.


2 Answers

Refer to Alex's answer as it's a cleaner one.

You can write your own implementation of org.apache.log4j.spi.ThrowableRenderer:

http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/spi/ThrowableRenderer.html

Then, edit your log4j configuration:

log4j.throwableRenderer=your-custom-class-name

The ThrowableRenderer returns an array of Strings. Here's your code:

String prefix = "myPrefix"; // Or some constant

List<String> l = new LinkedList<String>();
l.add(String.format("%s %s: %s", prefix, t.getClass().getName(), t.getMessage()));

for (StackTraceElement ste: t.getStackTrace()){
    l.add(String.format("%s %s", prefix, ste.toString()));
}

return (String[]) l.toArray();

Another idea would be to print the Throwable into a PrintWriter that is wrapping some Writer that writes into memory, and then re-iterate over strings delimited by line.separator, adding each line to a list:

StringWriter sw = new StringWriter();
t.printStackTrace(new PrintWriter(sw));

List<String> l = new LinkedList<String>();
for (String s: sw.toString().split(System.lineSeparator())) {
    l.add(String.format("%s %s", prefix, s));
}

return (String[]) l.toArray();
like image 93
Isaac Avatar answered Oct 11 '22 03:10

Isaac


Subclass ThrowableRenderer, for example:

import org.apache.log4j.DefaultThrowableRenderer;
import org.apache.log4j.spi.ThrowableRenderer;

public class LogThrowableRenderer implements ThrowableRenderer {

    DefaultThrowableRenderer def = new DefaultThrowableRenderer();

    @Override
    public String[] doRender(Throwable t) {
        String[] temp = def.doRender(t);
        for (int i = 0; i < temp.length; i++) {
            temp[i] = "myPrefix "+temp[i];
        }
        return temp;
    }

}

Add to your log4j.properties:

log4j.throwableRenderer=whatever.package.LogThrowableRenderer

This uses the existing DefaultThrowableRenderer to render the stacktrace in the familiar way before adding the prefix, so it will include the Throwable class, message, and cause.

like image 40
Alex Nauda Avatar answered Oct 11 '22 03:10

Alex Nauda