Skip to content

Commit

Permalink
Merge pull request #525 from scireum/feature/mko/SIRI-960
Browse files Browse the repository at this point in the history
Adds a method which prints the stack trace of a throwable without error msg
  • Loading branch information
mko-sci authored May 17, 2024
2 parents 394aacb + e504791 commit b7c851c
Showing 1 changed file with 74 additions and 30 deletions.
104 changes: 74 additions & 30 deletions src/main/java/sirius/kernel/health/Exceptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

package sirius.kernel.health;

import com.google.common.base.Throwables;
import sirius.kernel.async.CallContext;
import sirius.kernel.commons.Explain;
import sirius.kernel.commons.Strings;
Expand All @@ -17,6 +18,7 @@
import sirius.kernel.nls.NLS;

import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -121,11 +123,11 @@ protected ErrorHandler(boolean processError) {
* one can add <tt>%s (%s)</tt> to the message provided here to output the actual error and
* exception type if needed.
*
* @param e the exception which needs to be attached to this error handler
* @param throwable the exception which needs to be attached to this error handler
* @return <tt>this</tt> in order to fluently call more methods on this handler
*/
public ErrorHandler error(Throwable e) {
this.ex = e;
public ErrorHandler error(Throwable throwable) {
this.ex = throwable;
return this;
}

Expand Down Expand Up @@ -251,14 +253,14 @@ public HandledException handle() {
IGNORED_EXCEPTIONS_LOG.INFO(result);
}
return result;
} catch (Exception t) {
} catch (Exception exception) {
// We call as few external methods a possible here, since things are really messed up right now
t.printStackTrace();
exception.printStackTrace();
return new HandledException("Kernel Panic: Exception-Handling threw another exception: "
+ t.getMessage()
+ exception.getMessage()
+ " ("
+ t.getClass().getName()
+ ")", Collections.emptyMap(), t);
+ exception.getClass().getName()
+ ")", Collections.emptyMap(), exception);
}
}

Expand Down Expand Up @@ -325,19 +327,19 @@ private String computeLocation(HandledException result) {

/*
* Adds the exception message and the exception class to the given params array. Handles null values for
* e gracefully
* the throwable gracefully
*/
private Object[] extendParams(Throwable e, Object[] params) {
private Object[] extendParams(Throwable throwable, Object[] params) {
Object[] newParams;
if (params == null) {
newParams = new Object[2];
} else {
newParams = new Object[params.length + 2];
System.arraycopy(params, 0, newParams, 0, params.length);
}
if (e != null) {
newParams[newParams.length - 2] = e.getMessage();
newParams[newParams.length - 1] = e.getClass().getName();
if (throwable != null) {
newParams[newParams.length - 2] = throwable.getMessage();
newParams[newParams.length - 1] = throwable.getClass().getName();
} else {
newParams[newParams.length - 2] = NLS.get("HandledException.unknownError");
newParams[newParams.length - 1] = "UnknownError";
Expand Down Expand Up @@ -391,24 +393,24 @@ public static ErrorHandler handle() {
/**
* Boilerplate method the directly handle the given exception without a special message or logger
*
* @param e the exception to handle
* @param throwable the exception to handle
* @return a <tt>HandledException</tt> which notifies surrounding calls that an error occurred, which has
* already been taken care of.
*/
public static HandledException handle(Throwable e) {
return handle().error(e).handle();
public static HandledException handle(Throwable throwable) {
return handle().error(throwable).handle();
}

/**
* Boilerplate method the directly handle the given exception without a special message
*
* @param log the logger used to log the exception
* @param e the exception to handle
* @param log the logger used to log the exception
* @param throwable the exception to handle
* @return a <tt>HandledException</tt> which notifies surrounding calls that an error occurred, which has
* already been taken care of.
*/
public static HandledException handle(Log log, Throwable e) {
return handle().error(e).to(log).handle();
public static HandledException handle(Log log, Throwable throwable) {
return handle().error(throwable).to(log).handle();
}

/**
Expand All @@ -431,11 +433,11 @@ public static ErrorHandler createHandled() {
* exception is wanted to be ignored. Additionally, the <tt>ignoredExceptions</tt> logger can be turned on,
* to still see those exceptions.
*
* @param t the exception to be ignored. This exception will be discarded unless the <tt>ignoredExceptions</tt>
* logger is set to INFO.
* @param throwable the exception to be ignored. This exception will be discarded unless the <tt>ignoredExceptions</tt>
* logger is set to INFO.
*/
public static void ignore(Throwable t) {
IGNORED_EXCEPTIONS_LOG.INFO(t);
public static void ignore(Throwable throwable) {
IGNORED_EXCEPTIONS_LOG.INFO(throwable);
}

/**
Expand All @@ -461,8 +463,8 @@ public static void logDeprecatedMethodUse() {
List<Tuple<String, String>> mdc = CallContext.getCurrent().getMDC();
if (mdc != null) {
msg.append("\n---------------------------------------------------\n");
for (Tuple<String, String> t : mdc) {
msg.append(t.getFirst()).append(": ").append(t.getSecond()).append("\n");
for (Tuple<String, String> tuple : mdc) {
msg.append(tuple.getFirst()).append(": ").append(tuple.getSecond()).append("\n");
}
}

Expand All @@ -472,15 +474,15 @@ public static void logDeprecatedMethodUse() {
/**
* Retrieves the actual root {@link Throwable} which ended in the given exception.
*
* @param e the throwable to begin with
* @param throwable the throwable to begin with
* @return the root {@link Throwable} of the given one
*/
public static Throwable getRootCause(@Nullable Throwable e) {
if (e == null) {
public static Throwable getRootCause(@Nullable Throwable throwable) {
if (throwable == null) {
return null;
}

Throwable cause = e;
Throwable cause = throwable;

int circuitBreaker = 11;
while (circuitBreaker > 0 && cause.getCause() != null && !cause.equals(cause.getCause())) {
Expand All @@ -490,4 +492,46 @@ public static Throwable getRootCause(@Nullable Throwable e) {

return cause;
}

/**
* Generates a stack trace for the given throwable and its causes without the error messages.
*
* @param throwable the throwable to generate the stack trace for
* @return a string representation of the stack trace without the error message
*/
public static String buildStackTraceWithoutErrorMessage(Throwable throwable) {
StringBuilder stringBuilder = new StringBuilder();

stringBuilder.append(throwable.getClass().getName()).append(":").append("\n");
appendStackTrace(stringBuilder, throwable);

try {
// The first element of the causal chain is always the throwable followed by its cause hierarchy.
// Therefore, the first element is skipped.
Throwables.getCausalChain(throwable).stream().skip(1).forEach(cause -> {
stringBuilder.append("Caused by: ").append(cause.getClass().getName()).append(":").append("\n");
appendStackTrace(stringBuilder, cause);
});
} catch (IllegalArgumentException exception) {
// This happens if the causal chain has a circular reference.
stringBuilder.append("Warning: Circular reference detected in causal chain. Skipping causes: ")
.append(exception.getMessage());
}

return stringBuilder.toString();
}

/**
* Appends the stack trace of the given throwable to the given string builder.
*
* @param stringBuilder the string builder to append the stack trace to
* @param throwable the throwable to append the stack trace of
*/
private static void appendStackTrace(StringBuilder stringBuilder, Throwable throwable) {
Arrays.stream(throwable.getStackTrace())
.forEach(stackTraceElement -> stringBuilder.append("\t")
.append("at ")
.append(stackTraceElement)
.append("\n"));
}
}

0 comments on commit b7c851c

Please sign in to comment.