繁体   English   中英

是否可以在 log4j 中为堆栈跟踪的每一行添加前缀?

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

当你写

logger.error("message", exception);

log4j 生成消息和完整的堆栈跟踪:

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

我的转换模式是

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

那么,是否可以在每一行前面加上 myPrefix,如:

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

当我 grep 我在 myPrefix 上登录时,我没有看到堆栈跟踪。 我们有许多不同的前缀(每个模块一个)

提前致谢。

请参阅亚历克斯的答案,因为它更干净。

您可以编写自己的org.apache.log4j.spi.ThrowableRenderer实现:

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

然后,编辑您的log4j配置:

log4j.throwableRenderer = your-custom-class-name

ThrowableRenderer返回一个String数组。 这是你的代码:

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

另一个想法是将Throwable打印到PrintWriter ,该PrintWriter包装一些写入内存的Writer ,然后重新迭代由line.separator分隔的字符串,将每一行添加到列表中:

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

子类ThrowableRenderer ,例如:

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;
    }

}

添加到log4j.properties

log4j.throwableRenderer=whatever.package.LogThrowableRenderer

这使用现有的DefaultThrowableRenderer在添加前缀之前以熟悉的方式呈现堆栈跟踪,因此它将包括Throwable类,消息和原因。

使用 log4j2,您可以通过将separator指定为换行符后跟前缀来为堆栈跟踪的每一行添加前缀:

%xThrowable{separator(\nmyPrefix)}%n

您可以类似地为每个多行消息的每个新行添加前缀:

%replace{%m}{[\r\n]+}{\nmyPrefix}

例如,要为每个多行日志和堆栈跟踪行添加一个空格前缀:

appender.rolling.layout.pattern = %d [%t] %-5p %c %L - %replace{%m}{[\r\n]+}{\n }%xThrowable{separator(\n )}%n

请注意,您希望在%m之后放置%xThrowable位。

编写一个包装函数来为您完成。

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

这是我为 logback 找到并使用的一种解决方案。 API 目前不允许您为堆栈跟踪的每一行添加前缀。 对于其他行,我已经有了一个带有跟踪 ID 的模式。 所以我不得不使用它。 所以我所做的是

  1. 我创建了一个 CustomLayout extends LayoutBase
  2. 在 doLayout 方法中,您可以检查事件中是否有 TrowableProxy,您可以从中解析每一行并添加前缀。 我只是检查了我的跟踪 ID 是否在线,如果没有,我只是附加了它。

这是代码

public class MyLayout extends LayoutBase<ILoggingEvent> {

    private PatternLayout pattern = null;
    private String thePattern;

   @Override
    public String doLayout(ILoggingEvent event) {
        if (!pattern.isStarted()) {
            pattern.setPattern(thePattern);
            pattern.start();
        }

        String patternLayoutResult = pattern.doLayout(event);
        StringBuilder sb = new StringBuilder();

        String trackingId = MDC.get(TRACKING_ID);
        if (trackingId != null) {
            for (String line : patternLayoutResult.split(LINE_SEPARATOR)) {
                if (!line.contains(trackingId)) {
                    sb.append("Exception [");
                    sb.append(TRACKING_ID);
                    sb.append(":");
                    sb.append(trackingId);
                    sb.append("] ");

                }
                sb.append(line);
                sb.append(LINE_SEPARATOR);
            }

            return sb.toString();
        }

        return patternLayoutResult;
    }

并在 logback.xml

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="mypackage.CustomLoggingLayout">
                <thePattern>%d{dd.MM.yyyy HH:mm:ss} %-5p [trackingId:%X{trackingId}] %c{1}:%L - %m%n</thePattern>
                <Pattern></Pattern>
            </layout>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

现在 stackTrace 看起来像:

Exception [trackingId:d3746a12a86e46f991a338b4317045f5] at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154)
Exception [trackingId:d3746a12a86e46f991a338b4317045f5] at org.glassfish.jersey.jdkhttp.JdkHttpHandlerContainer.handle(JdkHttpHandlerContainer.java:161)
Exception [trackingId:d3746a12a86e46f991a338b4317045f5] at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
Exception [trackingId:d3746a12a86e46f991a338b4317045f5] at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83)
Exception [trackingId:d3746a12a86e46f991a338b4317045f5] at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:82)
Exception [trackingId:d3746a12a86e46f991a338b4317045f5] at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:700)
Exception [trackingId:d3746a12a86e46f991a338b4317045f5] at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
Exception [trackingId:d3746a12a86e46f991a338b4317045f5] at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:672)
Exception [trackingId:d3746a12a86e46f991a338b4317045f5] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
Exception [trackingId:d3746a12a86e46f991a338b4317045f5] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
Exception [trackingId:d3746a12a86e46f991a338b4317045f5] at java.lang.Thread.run(Thread.java:748)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM