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.
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.
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.
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.
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.
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 String
s. 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();
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With