in runtime/src/main/java/com/google/cloud/verticals/foundations/dataharmonization/exceptions/WhistleRuntimeException.java [118:180]
public static ImmutableList<StackTraceElement> generateStackTrace(StackFrame stackFrame) {
StackFrame cursor = stackFrame;
ImmutableList.Builder<StackTraceElement> elements = ImmutableList.builder();
Source callSiteToLastFn =
cursor != null && cursor.getDebugInfo() != null
? cursor.getDebugInfo().getCallSiteToNextStackFrame()
: DebugInfo.UNKNOWN_SOURCE;
// Go down the stack, looking for frames that the user should care about (i.e. skipping ones in
// OMITTED_FUNCTION_TYPES. Each frame should (might) have a callsite info indicating where
// it transitioned-into (called) the frame above it. We retain that information until the next
// frame that we care about. For example, assuming we omit blocks, and have a stack like
//
// Frame | callsite to next
// func1 n/a
// ↑
// blockA x.wstl:9
// ↑
// funcA x.wstl:4 - funcA calls blockA, we don't care about that.
// We want a stack like:
// at x.func1
// at x.funcA(x.wstl:9)
int steps = 0;
while (cursor != null && steps < MAX_STACK_TRACE_ELEMS) {
DebugInfo info = cursor.getDebugInfo();
StackTraceElement element;
boolean skip;
if (info == null) {
skip = cursor.inheritsParentVars();
element = new StackTraceElement(NO_DEBUG_INFO, cursor.getName(), "", -1);
} else {
skip = OMITTED_FUNCTION_TYPES.contains(info.getFunctionInfo().getType());
element = formatElement(info, cursor, callSiteToLastFn);
}
if (!skip) {
elements.add(element);
// We only want to get the callsite that lead to this element if it's from a frame that
// actually has that information (i.e. not something present in OMITTED_CALLSITE_SOURCES).
boolean wasCalled = cursor.getParent() != null;
boolean callerHadDebugInfo = wasCalled && cursor.getParent().getDebugInfo() != null;
boolean callerWasNotNative =
callerHadDebugInfo
&& !OMITTED_CALLSITE_SOURCES.contains(
cursor.getParent().getDebugInfo().getFunctionInfo().getType());
callSiteToLastFn =
callerWasNotNative
? cursor.getParent().getDebugInfo().getCallSiteToNextStackFrame()
: DebugInfo.UNKNOWN_SOURCE;
}
// Steps count guards against weird scenarios of cycles or infinite loops when stack is mocked
// in tests.
steps++;
cursor = cursor.getParent();
}
return elements.build();
}