How do I print a Groovy stack trace?
Asked Answered
A

4

31

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.

Abdulabdulla answered 6/6, 2011 at 23:34 Comment(0)
R
28

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.

Refute answered 6/6, 2011 at 23:48 Comment(4)
Final solution: org.codehaus.groovy.runtime.StackTraceUtils.sanitize(new Exception()).printStackTrace(). For some reason printSanitizedStackTrace() doesn't work.Abdulabdulla
It could be that printSanitizedStackTrace() doesn't behave as you expect because you're expecting the output in System.out, while printSanitizedStackTrace() sends it to System.err. I tried adding a PrintWriter constructed from add System.out as the second parameter, after the Throwable object, but still didn't get anything like I was expecting in the output.Gerrard
This works for me: org.codehaus.groovy.runtime.StackTraceUtils.sanitize(new Exception(e)).printStackTrace() where e is the catch-ed ExceptionDecided
The link in the answer is brokenFifth
M
6

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'
  }
}
Mcginnis answered 26/4, 2018 at 9:46 Comment(1)
Thanks! This really helped fixing my spock unit test casesManasseh
Q
3

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:

  1. The output is concatenated into a single string to avoid being mixed with "[Pipeline] echo" message prefix of Jenkins Pipeline's println()).
  2. 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.
Quickie answered 16/2, 2021 at 19:18 Comment(0)
B
0

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()
    }
}

Console Output NOTE: It may require to allow few method signatures in the <jenkins_url>/scriptAproval such as deepSanitize()

Brutus answered 11/7, 2024 at 10:29 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.