解决ELK日志被截断的问题
问题1
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestLogger {
private static Logger logger = LoggerFactory.getLogger(TestLogger.class);
public static void main(String[] args) {
String test = "<xml>\n" +
" <appid>wx123456789</appid>\n" +
" <mch_id>123456789</mch_id>\n" +
" <nonce_str>6cefdb308e1e2e8aabd48cf79e546a02</nonce_str>\n" +
" <out_refund_no>123456789</out_refund_no>\n" +
" <out_trade_no>123456789</out_trade_no>\n" +
" <refund_fee>1</refund_fee>\n" +
" <total_fee>1</total_fee>\n" +
" <transaction_id>123456789</transaction_id>\n" +
" <sign>FE56DD4AA85C0EECA82C35595A69E153</sign>\n" +
"</xml>";
logger.info("test a,{}", test);
}
}
当我们的 message 中包含换行符时,会被 ELK 截断,影响我们排查问题。可以通过清除换行符来解决此问题。
String test2 = test.replaceAll("\r\n|\r|\n", "");
问题2
public class TestLogger2 {
private static Logger logger = LoggerFactory.getLogger(TestLogger2.class);
public static void main(String[] args) {
logger.error("test abc", new RuntimeException("test"));
}
}
异常信息被截断,解决方法如下
public class TestLogger3 {
private static Logger logger = LoggerFactory.getLogger(TestLogger3.class);
public static void main(String[] args) {
String test3 = stackTraceToString(new RuntimeException("test3"));
logger.error("test3 {}", test3);
}
/**
* 参考 {@link io.netty.util.internal.ThrowableUtil#stackTraceToString(java.lang.Throwable)}
*/
private static String stackTraceToString(Throwable cause) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
PrintStream pout = new PrintStream(out);
cause.printStackTrace(pout);
pout.flush();
try {
return out.toString();
} finally {
try {
out.close();
} catch (IOException ignore) {
}
}
}
}
我们自己将异常堆栈信息转换为字符串,就莫名其妙解决了这个问题,具体原因未找到。
Logback 内部通过 ThrowableProxyConverter 的 convert() 方法将异常转换为字符串。
Logback 的 convert() 方法和我们自己的 cause.printStackTrace(pout) 底层最终使用的换行符都是 System.getProperty("line.separator")。