How do I print a Groovy stack trace? The Java method, Thread.currentThread().getStackTrace() produces a huge stack trace, including a lot of the Groovy internals. I'm seeing a function called twice from a StreamingMarkupBuilder that looks like it should only be called once and I would like to see why Groovy thinks it should be calling it twice.
Solution:
org.codehaus.groovy.runtime.StackTraceUtils.sanitize(new Exception()).printStackTrace()
Original answer:
A Google search returns the following information:
Apparently, there is a method in org.codehaus.groovy.runtime.StackTraceUtils
called printSanitizedStackTrace
. There isn't much documentation for the method, though there is a method called sanitize
which is described as
remove all apparently groovy-internal trace entries from the exception instance This modifies the original instance and returns it, it does not clone
So I would try org.codehaus.groovy.runtime.StackTraceUtils.printSanitizedStackTrace(Throwable t)
(it is static)
and see if that works for you.
org.codehaus.groovy.runtime.StackTraceUtils.sanitize(new Exception(e)).printStackTrace()
where e
is the catch-ed Exception –
Decided I found this questions when searching for "spock print full stack trace"
.
My unit tests are written in Groovy, using the Spock testing framework and they're run in the context of a Gradle build.
The fix for me was as simple as adding exceptionFormat = 'full'
to my Gradle test task specification:
test {
testLogging {
exceptionFormat = 'full'
}
}
I have designed this simple code for stack trace printing, based on artificial simulation of a NullPointerException. This code produces the same output in both modes: from a Jenkinsfile (Pipeline) and from a normal .groovy script in a command line.
def getStackTrace() {
try {
null.class.toString() // simulate NPE
} catch (NullPointerException e) {
return e.getStackTrace()
}
return null
}
def printStackTrace() {
def stackTraceStr = ""
def callingFuncFound = false
for (StackTraceElement ste : getStackTrace()) {
if (callingFuncFound) {
stackTraceStr += ste.toString() + '\n'
}
if (!callingFuncFound && ste.toString().startsWith(this.class.name + '.printStackTrace(')) {
callingFuncFound = true
}
}
println(stackTraceStr)
}
Some explanations:
- The output is concatenated into a single string to avoid being mixed with "[Pipeline] echo" message prefix of Jenkins Pipeline's println()).
- The number of "unnecessary" upper stack trace elements related to the NPE is different in Jenkinsfile and in a normal command line. This is why I calculate callingFuncFound and don't use just something like e.getStackTrace()[2..-1] to skip them.
In my use-case I had to sanitize the stacktrace (Filter out any Jenkins / groovy elements):
import org.codehaus.groovy.runtime.StackTraceUtils
def check_response_code(int code, int divBy) {
try {
echo "Attempting to divide $code by $divBy"
code / divBy
} catch (Exception e) {
// Sanitize the exception
Throwable sanitizedException = StackTraceUtils.deepSanitize(e)
def filteredStackTrace = sanitizedException.stackTrace.findAll { element ->
!element.className.contains("com.cloudbees.groovy.cps.") &&
!element.className.contains("org.jenkinsci.plugins.") &&
!element.className.contains("org.kohsuke.groovy.sandbox.") &&
!element.className.contains("jenkins.util.") &&
!element.className.contains("hudson.remoting.") &&
!element.className.contains("jenkins.security.") &&
!element.className.contains("___cps")
}
sanitizedException.stackTrace = filteredStackTrace as StackTraceElement[]
// Print the sanitized stack trace
def sw = new StringWriter()
def pw = new PrintWriter(sw)
sanitizedException.printStackTrace(pw)
echo sw.toString()
}
}
NOTE: It may require to allow few method signatures in the <jenkins_url>/scriptAproval such as deepSanitize()
© 2022 - 2025 — McMap. All rights reserved.