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

allow inline stacktrace generation #807

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
Expand Up @@ -112,10 +112,15 @@ public class ShortenedThrowableConverter extends ThrowableHandlingConverter {
private static final String OPTION_VALUE_ROOT_FIRST = "rootFirst";
private static final String OPTION_VALUE_INLINE_HASH = "inlineHash";

private static final String OPTION_VALUE_INLINE_STACK = "inline";

private static final int OPTION_INDEX_MAX_DEPTH = 0;
private static final int OPTION_INDEX_SHORTENED_CLASS_NAME = 1;
private static final int OPTION_INDEX_MAX_LENGTH = 2;

/** String sequence to use to delimit lines instead of {@link CoreConstants#LINE_SEPARATOR} when {@link #inline} is active */
public static final String INLINE_SEPARATOR = "\\n";

private AtomicInteger errorCount = new AtomicInteger();

/**
Expand Down Expand Up @@ -160,6 +165,11 @@ public class ShortenedThrowableConverter extends ThrowableHandlingConverter {
*/
private boolean inlineHash;

/**
* True to use "\\n" sequence instead of {@link CoreConstants#LINE_SEPARATOR}
*/
private boolean inline;

MarneusCalgarXP marked this conversation as resolved.
Show resolved Hide resolved
private StackElementFilter stackElementFilter;

private StackHasher stackHasher;
Expand Down Expand Up @@ -217,13 +227,16 @@ private void parseOptions() {
* Remaining options are either
* - "rootFirst" - indicating that stacks should be printed root-cause first
* - "inlineHash" - indicating that hexadecimal error hashes should be computed and inlined
* - "inline" - indicating that the whole stack trace should be inlined, using "\\n" as separator
* - evaluator name - name of evaluators that will determine if the stacktrace is ignored
* - exclusion pattern - pattern for stack trace elements to exclude
*/
if (OPTION_VALUE_ROOT_FIRST.equals(option)) {
setRootCauseFirst(true);
} else if (OPTION_VALUE_INLINE_HASH.equals(option)) {
setInlineHash(true);
} else if (OPTION_VALUE_INLINE_STACK.equals(option)) {
setInline(true);
} else {
@SuppressWarnings("rawtypes")
Map evaluatorMap = (Map) getContext().getObject(CoreConstants.EVALUATOR_MAP);
Expand Down Expand Up @@ -282,12 +295,18 @@ public String convert(ILoggingEvent event) {
appendRootCauseLast(builder, null, ThrowableProxyUtil.REGULAR_EXCEPTION_INDENT, throwableProxy, stackHashes);
}
if (builder.length() > maxLength) {
builder.setLength(maxLength - ELLIPSIS.length() - CoreConstants.LINE_SEPARATOR.length());
builder.append(ELLIPSIS).append(CoreConstants.LINE_SEPARATOR);
builder.setLength(maxLength - ELLIPSIS.length() - getLineSeparator().length());
builder.append(ELLIPSIS).append(getLineSeparator());
}
return builder.toString();
}

private String getLineSeparator() {
return isInline()
? INLINE_SEPARATOR
: CoreConstants.LINE_SEPARATOR;
}

/**
* Return true if any evaluator returns true, indicating that
* the stack trace should not be logged.
Expand Down Expand Up @@ -467,7 +486,7 @@ private void appendPlaceHolder(StringBuilder builder, int indent, int consecutiv
.append(consecutiveExcluded)
.append(" ")
.append(message)
.append(CoreConstants.LINE_SEPARATOR);
.append(getLineSeparator());
}

/**
Expand Down Expand Up @@ -506,7 +525,7 @@ private void appendStackTraceElement(StringBuilder builder, int indent, StackTra
if (shouldAppendPackagingData(step, previousStep)) {
appendPackagingData(builder, step);
}
builder.append(CoreConstants.LINE_SEPARATOR);
builder.append(getLineSeparator());
}

/**
Expand Down Expand Up @@ -547,7 +566,7 @@ private void appendFirstLine(StringBuilder builder, String prefix, int indent, I
builder.append(abbreviator.abbreviate(throwableProxy.getClassName()))
.append(": ")
.append(throwableProxy.getMessage())
.append(CoreConstants.LINE_SEPARATOR);
.append(getLineSeparator());
}

private void indent(StringBuilder builder, int indent) {
Expand Down Expand Up @@ -606,6 +625,14 @@ public void setInlineHash(boolean inlineHash) {
this.inlineHash = inlineHash;
}

public boolean isInline() {
return inline;
}

public void setInline(boolean inlineHash) {
this.inline = inlineHash;
}

protected void setStackHasher(StackHasher stackHasher) {
this.stackHasher = stackHasher;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,17 +315,19 @@ public void testOptions() throws EvaluationException {
assertThat(converter.getShortenedClassNameLength()).isEqualTo(ShortenedThrowableConverter.FULL_CLASS_NAME_LENGTH);
assertThat(converter.getMaxLength()).isEqualTo(ShortenedThrowableConverter.FULL_MAX_LENGTH);
assertThat(converter.isRootCauseFirst()).isTrue();
assertThat(converter.isInline()).isFalse();
assertThat(converter.getEvaluators().get(0)).isEqualTo(evaluator);
assertThat(converter.getExcludes().get(0)).isEqualTo("regex");

// test short values
converter.setOptionList(Arrays.asList("short", "short", "short", "rootFirst", "inlineHash", "evaluator", "regex"));
converter.setOptionList(Arrays.asList("short", "short", "short", "rootFirst", "inlineHash", "inline", "evaluator", "regex"));
converter.start();

assertThat(converter.getMaxDepthPerThrowable()).isEqualTo(ShortenedThrowableConverter.SHORT_MAX_DEPTH_PER_THROWABLE);
assertThat(converter.getShortenedClassNameLength()).isEqualTo(ShortenedThrowableConverter.SHORT_CLASS_NAME_LENGTH);
assertThat(converter.getMaxLength()).isEqualTo(ShortenedThrowableConverter.SHORT_MAX_LENGTH);

assertThat(converter.isInline()).isTrue();

// test numeric values
converter.setOptionList(Arrays.asList("1", "2", "3"));
converter.start();
Expand Down Expand Up @@ -424,6 +426,30 @@ public void test_inline_hash_root_cause_first() {
}
}

@Test
public void test_inline_stack() {
try {
StackTraceElementGenerator.generateCausedBy();
fail("Exception must have been thrown");
} catch (RuntimeException e) {
// GIVEN
StackHasher mockedHasher = Mockito.mock(StackHasher.class);
ShortenedThrowableConverter converter = new ShortenedThrowableConverter();
converter.setInline(true);
converter.setRootCauseFirst(true);
converter.start();
converter.setStackHasher(mockedHasher);

// WHEN
String formatted = converter.convert(createEvent(e));

// THEN
// verify we have expected stack hashes inlined
assertThat(formatted).doesNotContain(CoreConstants.LINE_SEPARATOR);
assertThat(formatted).contains(ShortenedThrowableConverter.INLINE_SEPARATOR);
}
}

@Test
public void test_inline_hash_with_suppressed() {
try {
Expand Down