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

时光总嘲笑我的痴心妄想 提交于 2020-01-03 08:43:04

问题


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.


回答1:


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.




回答2:


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



回答3:


Write a wrapper function to do it for you.

private void writeToLogs(String message, Exception excp) {
    logger.error("myPrefix\t" + message, excp);
}


来源:https://stackoverflow.com/questions/3459089/is-it-possible-to-prefix-every-line-of-a-stacktrace-in-log4j

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!