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.

dromodel
  • 9,581
  • 12
  • 47
  • 65

3 Answers3

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.

Erik B
  • 40,889
  • 25
  • 119
  • 135
amccormack
  • 13,207
  • 10
  • 38
  • 61
  • 14
    Final solution: org.codehaus.groovy.runtime.StackTraceUtils.sanitize(new Exception()).printStackTrace(). For some reason printSanitizedStackTrace() doesn't work. – dromodel Nov 12 '12 at 17:27
  • 2
    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. – jonnybot Jul 09 '13 at 20:55
  • 3
    This works for me: ```org.codehaus.groovy.runtime.StackTraceUtils.sanitize(new Exception(e)).printStackTrace()``` where ```e``` is the catch-ed Exception – lrkwz Aug 22 '16 at 14:42
  • The link in the answer is broken – Marco Lackovic Jul 24 '20 at 13:13
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'
  }
}
Shorn
  • 19,077
  • 15
  • 90
  • 168
2

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.
Alexander Samoylov
  • 2,358
  • 2
  • 25
  • 28