[英]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 的模式。 所以我不得不使用它。 所以我所做的是
這是代碼
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.