Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

original stack trace for JsonEncoder #808

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package ch.qos.logback.classic.encoder;

import ch.qos.logback.classic.spi.IThrowableProxy;
import ch.qos.logback.classic.spi.StackTraceElementProxy;

import static ch.qos.logback.classic.encoder.JsonEncoder.CAUSE_ATTR_NAME;
import static ch.qos.logback.classic.encoder.JsonEncoder.CLASS_NAME_ATTR_NAME;
import static ch.qos.logback.classic.encoder.JsonEncoder.CLOSE_ARRAY;
import static ch.qos.logback.classic.encoder.JsonEncoder.CLOSE_OBJ;
import static ch.qos.logback.classic.encoder.JsonEncoder.METHOD_NAME_ATTR_NAME;
import static ch.qos.logback.classic.encoder.JsonEncoder.OPEN_ARRAY;
import static ch.qos.logback.classic.encoder.JsonEncoder.OPEN_OBJ;
import static ch.qos.logback.classic.encoder.JsonEncoder.QUOTE;
import static ch.qos.logback.classic.encoder.JsonEncoder.QUOTE_COL;
import static ch.qos.logback.classic.encoder.JsonEncoder.STEP_ARRAY_NAME_ATTRIBUTE;
import static ch.qos.logback.classic.encoder.JsonEncoder.SUPPRESSED_ATTR_NAME;
import static ch.qos.logback.classic.encoder.JsonEncoder.VALUE_SEPARATOR;
import static ch.qos.logback.classic.encoder.JsonEncoder.appenderMember;
import static ch.qos.logback.classic.encoder.JsonEncoder.appenderMemberWithIntValue;
import static ch.qos.logback.classic.encoder.JsonEncoder.nullSafeStr;

class ArrayThrowableEncoder extends ThrowableEncoder {

private static final String FILE_NAME_ATTR_NAME = "fileName";
private static final String LINE_NUMBER_ATTR_NAME = "lineNumber";

@Override
void encodeStackTrace(StringBuilder sb, IThrowableProxy itp) {
appendSTEPArray(sb, itp.getStackTraceElementProxyArray(), itp.getCommonFrames());

IThrowableProxy cause = itp.getCause();
if (cause != null) {
sb.append(VALUE_SEPARATOR);
appendThrowableProxy(sb, CAUSE_ATTR_NAME, cause);
}

IThrowableProxy[] suppressedArray = itp.getSuppressed();
if (suppressedArray != null && suppressedArray.length != 0) {
sb.append(VALUE_SEPARATOR);
sb.append(QUOTE).append(SUPPRESSED_ATTR_NAME).append(QUOTE_COL);
sb.append(OPEN_ARRAY);
boolean first = true;
for (IThrowableProxy suppressedITP : suppressedArray) {
if (first) {
first = false;
} else {
sb.append(VALUE_SEPARATOR);
}
appendThrowableProxy(sb, null, suppressedITP);
}
sb.append(CLOSE_ARRAY);
}
}

private void appendSTEPArray(StringBuilder sb, StackTraceElementProxy[] stepArray, int commonFrames) {
sb.append(QUOTE).append(STEP_ARRAY_NAME_ATTRIBUTE).append(QUOTE_COL).append(OPEN_ARRAY);

int len = stepArray != null ? stepArray.length : 0;

if (commonFrames >= len) {
commonFrames = 0;
}

for (int i = 0; i < len - commonFrames; i++) {
if (i != 0)
sb.append(VALUE_SEPARATOR);

StackTraceElementProxy step = stepArray[i];

sb.append(OPEN_OBJ);
StackTraceElement ste = step.getStackTraceElement();

appenderMember(sb, CLASS_NAME_ATTR_NAME, nullSafeStr(ste.getClassName()));
sb.append(VALUE_SEPARATOR);

appenderMember(sb, METHOD_NAME_ATTR_NAME, nullSafeStr(ste.getMethodName()));
sb.append(VALUE_SEPARATOR);

appenderMember(sb, FILE_NAME_ATTR_NAME, nullSafeStr(ste.getFileName()));
sb.append(VALUE_SEPARATOR);

appenderMemberWithIntValue(sb, LINE_NUMBER_ATTR_NAME, ste.getLineNumber());
sb.append(CLOSE_OBJ);

}

sb.append(CLOSE_ARRAY);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
package ch.qos.logback.classic.encoder;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.IThrowableProxy;
import ch.qos.logback.classic.spi.LoggerContextVO;
import ch.qos.logback.classic.spi.StackTraceElementProxy;
import ch.qos.logback.core.CoreConstants;
import ch.qos.logback.core.encoder.EncoderBase;
import org.slf4j.Marker;
Expand Down Expand Up @@ -73,8 +71,6 @@ public class JsonEncoder extends EncoderBase<ILoggingEvent> {

public static final String THROWABLE_ATTR_NAME = "throwable";

private static final String CYCLIC_THROWABLE_ATTR_NAME = "cyclic";

public static final String CAUSE_ATTR_NAME = "cause";

public static final String SUPPRESSED_ATTR_NAME = "suppressed";
Expand All @@ -83,25 +79,23 @@ public class JsonEncoder extends EncoderBase<ILoggingEvent> {

public static final String CLASS_NAME_ATTR_NAME = "className";
public static final String METHOD_NAME_ATTR_NAME = "methodName";
private static final String FILE_NAME_ATTR_NAME = "fileName";
private static final String LINE_NUMBER_ATTR_NAME = "lineNumber";

public static final String STEP_ARRAY_NAME_ATTRIBUTE = "stepArray";

private static final char OPEN_OBJ = '{';
private static final char CLOSE_OBJ = '}';
private static final char OPEN_ARRAY = '[';
private static final char CLOSE_ARRAY = ']';
static final char OPEN_OBJ = '{';
static final char CLOSE_OBJ = '}';
static final char OPEN_ARRAY = '[';
static final char CLOSE_ARRAY = ']';

private static final char QUOTE = DOUBLE_QUOTE_CHAR;
static final char QUOTE = DOUBLE_QUOTE_CHAR;
private static final char SP = ' ';
private static final char ENTRY_SEPARATOR = COLON_CHAR;

private static final String COL_SP = ": ";

private static final String QUOTE_COL = "\":";
static final String QUOTE_COL = "\":";

private static final char VALUE_SEPARATOR = COMMA_CHAR;
static final char VALUE_SEPARATOR = COMMA_CHAR;

private boolean withSequenceNumber = true;

Expand All @@ -119,6 +113,7 @@ public class JsonEncoder extends EncoderBase<ILoggingEvent> {
private boolean withMessage = true;
private boolean withArguments = true;
private boolean withThrowable = true;
private boolean withPlainStackTrace = false;
private boolean withFormattedMessage = false;


Expand Down Expand Up @@ -191,7 +186,7 @@ public byte[] encode(ILoggingEvent event) {
appendArgumentArray(sb, event);

if (withThrowable)
appendThrowableProxy(sb, THROWABLE_ATTR_NAME, event.getThrowableProxy());
ThrowableEncoder.appendThrowableProxy(sb, event.getThrowableProxy(), withPlainStackTrace);

sb.append(CLOSE_OBJ);
sb.append(CoreConstants.JSON_LINE_SEPARATOR);
Expand Down Expand Up @@ -239,105 +234,11 @@ private void appendMap(StringBuilder sb, String attrName, Map<String, String> ma
sb.append(CLOSE_OBJ);
}

private void appendThrowableProxy(StringBuilder sb, String attributeName, IThrowableProxy itp) {

// in the nominal case, attributeName != null. However, attributeName will be null for suppressed
// IThrowableProxy array, in which case no attribute name is needed
if (attributeName != null) {
sb.append(QUOTE).append(attributeName).append(QUOTE_COL);
if (itp == null) {
sb.append(NULL_STR);
return;
}
}

sb.append(OPEN_OBJ);

appenderMember(sb, CLASS_NAME_ATTR_NAME, nullSafeStr(itp.getClassName()));

sb.append(VALUE_SEPARATOR);
appenderMember(sb, MESSAGE_ATTR_NAME, jsonEscape(itp.getMessage()));

if (itp.isCyclic()) {
sb.append(VALUE_SEPARATOR);
appenderMember(sb, CYCLIC_THROWABLE_ATTR_NAME, jsonEscape("true"));
}

sb.append(VALUE_SEPARATOR);
appendSTEPArray(sb, itp.getStackTraceElementProxyArray(), itp.getCommonFrames());

if (itp.getCommonFrames() != 0) {
sb.append(VALUE_SEPARATOR);
appenderMemberWithIntValue(sb, COMMON_FRAMES_COUNT_ATTR_NAME, itp.getCommonFrames());
}

IThrowableProxy cause = itp.getCause();
if (cause != null) {
sb.append(VALUE_SEPARATOR);
appendThrowableProxy(sb, CAUSE_ATTR_NAME, cause);
}

IThrowableProxy[] suppressedArray = itp.getSuppressed();
if (suppressedArray != null && suppressedArray.length != 0) {
sb.append(VALUE_SEPARATOR);
sb.append(QUOTE).append(SUPPRESSED_ATTR_NAME).append(QUOTE_COL);
sb.append(OPEN_ARRAY);
boolean first = true;
for (IThrowableProxy suppressedITP : suppressedArray) {
if (first) {
first = false;
} else {
sb.append(VALUE_SEPARATOR);
}
appendThrowableProxy(sb, null, suppressedITP);
}
sb.append(CLOSE_ARRAY);
}

sb.append(CLOSE_OBJ);

}

private void appendSTEPArray(StringBuilder sb, StackTraceElementProxy[] stepArray, int commonFrames) {
sb.append(QUOTE).append(STEP_ARRAY_NAME_ATTRIBUTE).append(QUOTE_COL).append(OPEN_ARRAY);

int len = stepArray != null ? stepArray.length : 0;

if (commonFrames >= len) {
commonFrames = 0;
}

for (int i = 0; i < len - commonFrames; i++) {
if (i != 0)
sb.append(VALUE_SEPARATOR);

StackTraceElementProxy step = stepArray[i];

sb.append(OPEN_OBJ);
StackTraceElement ste = step.getStackTraceElement();

appenderMember(sb, CLASS_NAME_ATTR_NAME, nullSafeStr(ste.getClassName()));
sb.append(VALUE_SEPARATOR);

appenderMember(sb, METHOD_NAME_ATTR_NAME, nullSafeStr(ste.getMethodName()));
sb.append(VALUE_SEPARATOR);

appenderMember(sb, FILE_NAME_ATTR_NAME, nullSafeStr(ste.getFileName()));
sb.append(VALUE_SEPARATOR);

appenderMemberWithIntValue(sb, LINE_NUMBER_ATTR_NAME, ste.getLineNumber());
sb.append(CLOSE_OBJ);

}

sb.append(CLOSE_ARRAY);
}

private void appenderMember(StringBuilder sb, String key, String value) {
static void appenderMember(StringBuilder sb, String key, String value) {
sb.append(QUOTE).append(key).append(QUOTE_COL).append(QUOTE).append(value).append(QUOTE);
}

private void appenderMemberWithIntValue(StringBuilder sb, String key, int value) {
static void appenderMemberWithIntValue(StringBuilder sb, String key, int value) {
sb.append(QUOTE).append(key).append(QUOTE_COL).append(value);
}

Expand Down Expand Up @@ -405,13 +306,13 @@ private String jsonEscapedToString(Object o) {
return jsonEscapeString(o.toString());
}

private String nullSafeStr(String s) {
static String nullSafeStr(String s) {
if (s == null)
return NULL_STR;
return s;
}

private String jsonEscape(String s) {
static String jsonEscape(String s) {
if (s == null)
return NULL_STR;
return jsonEscapeString(s);
Expand Down Expand Up @@ -512,8 +413,15 @@ public void setWithThrowable(boolean withThrowable) {
this.withThrowable = withThrowable;
}

/**
* @param withPlainStackTrace
* @since 1.5.7
*/
public void setWithPlainStackTrace(boolean withPlainStackTrace) {
this.withPlainStackTrace = withPlainStackTrace;
}

public void setWithFormattedMessage(boolean withFormattedMessage) {
this.withFormattedMessage = withFormattedMessage;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package ch.qos.logback.classic.encoder;

import ch.qos.logback.classic.spi.IThrowableProxy;
import ch.qos.logback.classic.spi.StackTraceElementProxy;

import static ch.qos.logback.classic.encoder.JsonEncoder.appenderMember;

class PlainStackTraceThrowableEncoder extends ThrowableEncoder {
public static final String STACKTRACE_NAME_ATTRIBUTE = "stackTrace";

@Override
void encodeStackTrace(StringBuilder sb, IThrowableProxy itp) {
appenderMember(sb, STACKTRACE_NAME_ATTRIBUTE, getOriginalStackTrace(itp));
}

private static String getOriginalStackTrace(IThrowableProxy throwableProxy) {
StringBuilder sb = new StringBuilder();
getOriginalStackTrace(throwableProxy, sb, 0);
return sb.toString();
}

private static void getOriginalStackTrace(IThrowableProxy throwable, StringBuilder sb, int depth) {
if (throwable == null) {
return;
}
if (depth > 0) {
sb.append("Caused by: ");
}
sb.append(throwable.getClassName()).append(": ").append(throwable.getMessage()).append(NEWLINE);
for (StackTraceElementProxy step : throwable.getStackTraceElementProxyArray()) {
sb.append(TAB).append(step.getSTEAsString()).append(NEWLINE);
}
getOriginalStackTrace(throwable.getCause(), sb, depth + 1);
}
}
Loading