Friday, January 30, 2015

Print Golang Stacktrace

Some IDEs are good at letting you drill down into function definitions.

That's great when you know the starting point.

What about the times when you know exactly where your code broke and you want to find the starting point, as well as all the stops along the way?

Here's one way to do it using runtime/pprof

Output Stack Trace

Add Imports


import (
 "runtime/pprof"
 "os"
)


Generate Stack Trace

Put this on what ever line you want to generate the stack trace from:

pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)


In this example, I put that WriteTo statement on line 222 in file /Users/lex/dev/go/project/src/github.com/company/repo/server/session.go.

Ouput

The output will look something like this:

goroutine profile: total 9
1 @ 0x18ce8c 0x18cc3b 0x189be3 0x3c807 0x3c529 0x3cfe2 0x3ceb1 0x3ce57 0x2cab2 0x1a0060 0x19ed07 0x25c437 0x15af96 0x15aea2 0x16b1f0 0x2cb12 0x1a0060 0x19ed07 0x25c437 0x15af96 0x15aea2 0x15f206 0x2cab2 0x1a0060 0x19ed07 0x25c437 0x15af96 0x15aea2 0x15ea7e 0x2cb12 0x1a0060 0x19ed07
# 0x18ce8c runtime/pprof.writeRuntimeProfile+0xcc        /usr/local/Cellar/go/1.3.3/libexec/src/pkg/runtime/pprof/pprof.go:540
# 0x18cc3b runtime/pprof.writeGoroutine+0x9b        /usr/local/Cellar/go/1.3.3/libexec/src/pkg/runtime/pprof/pprof.go:502
# 0x189be3 runtime/pprof.(*Profile).WriteTo+0xd3        /usr/local/Cellar/go/1.3.3/libexec/src/pkg/runtime/pprof/pprof.go:229
# 0x3c807  github.com/company/repo/server.(*sessionContext).User+0x1f7   /Users/lex/dev/go/project/src/github.com/company/repo/server/session.go:222
# 0x3c529  github.com/company/repo/server.(*sessionContext).UserID+0x39   /Users/lex/dev/go/project/src/github.com/company/repo/server/session.go:193
# 0x3cfe2  github.com/company/repo/server.(*sessionContext).refreshSessionRenderVars+0x42 /Users/lex/dev/go/project/src/github.com/company/repo/server/session.go:285
# 0x3ceb1  github.com/company/repo/server.(*sessionContext).SetSessionRenderVars+0x51 /Users/lex/dev/go/project/src/github.com/company/repo/server/session.go:274
# 0x3ce57  github.com/company/repo/server.SetSessionRenderVars+0x37   /Users/lex/dev/go/project/src/github.com/company/repo/server/session.go:269
# 0x2cab2  runtime.call32+0x32          /usr/local/Cellar/go/1.3.3/libexec/src/pkg/runtime/asm_amd64.s:361
# 0x1a0060 reflect.Value.call+0x1210         /usr/local/Cellar/go/1.3.3/libexec/src/pkg/reflect/value.go:563
# 0x19ed07 reflect.Value.Call+0xd7          /usr/local/Cellar/go/1.3.3/libexec/src/pkg/reflect/value.go:411
# 0x25c437 github.com/codegangsta/inject.(*injector).Invoke+0x3b7      /Users/lex/dev/go/project/src/github.com/codegangsta/inject/inject.go:102
# 0x15af96 github.com/company/martini.(*context).run+0x86      /Users/lex/dev/go/project/src/github.com/company/martini/martini.go:163
# 0x15aea2 github.com/company/martini.(*context).Next+0x32      /Users/lex/dev/go/project/src/github.com/company/martini/martini.go:154
# 0x16b1f0 github.com/company/martini-sessions.func·002+0x230      /Users/lex/dev/go/project/src/github.com/company/martini-sessions/sessions.go:93
# 0x2cb12  runtime.call64+0x32          /usr/local/Cellar/go/1.3.3/libexec/src/pkg/runtime/asm_amd64.s:362
# 0x1a0060 reflect.Value.call+0x1210         /usr/local/Cellar/go/1.3.3/libexec/src/pkg/reflect/value.go:563
# 0x19ed07 reflect.Value.Call+0xd7          /usr/local/Cellar/go/1.3.3/libexec/src/pkg/reflect/value.go:411
# 0x25c437 github.com/codegangsta/inject.(*injector).Invoke+0x3b7      /Users/lex/dev/go/project/src/github.com/codegangsta/inject/inject.go:102
# 0x15af96 github.com/company/martini.(*context).run+0x86      /Users/lex/dev/go/project/src/github.com/company/martini/martini.go:163
# 0x15aea2 github.com/company/martini.(*context).Next+0x32      /Users/lex/dev/go/project/src/github.com/company/martini/martini.go:154
# 0x15f206 github.com/company/martini.func·004+0x76       /Users/lex/dev/go/project/src/github.com/company/martini/recovery.go:140
# 0x2cab2  runtime.call32+0x32          /usr/local/Cellar/go/1.3.3/libexec/src/pkg/runtime/asm_amd64.s:361
# 0x1a0060 reflect.Value.call+0x1210         /usr/local/Cellar/go/1.3.3/libexec/src/pkg/reflect/value.go:563
# 0x19ed07 reflect.Value.Call+0xd7          /usr/local/Cellar/go/1.3.3/libexec/src/pkg/reflect/value.go:411
# 0x25c437 github.com/codegangsta/inject.(*injector).Invoke+0x3b7      /Users/lex/dev/go/project/src/github.com/codegangsta/inject/inject.go:102
# 0x15af96 github.com/company/martini.(*context).run+0x86      /Users/lex/dev/go/project/src/github.com/company/martini/martini.go:163
# 0x15aea2 github.com/company/martini.(*context).Next+0x32      /Users/lex/dev/go/project/src/github.com/company/martini/martini.go:154
# 0x15ea7e github.com/company/martini.func·001+0x1ae       /Users/lex/dev/go/project/src/github.com/company/martini/logger.go:16
# 0x2cb12  runtime.call64+0x32          /usr/local/Cellar/go/1.3.3/libexec/src/pkg/runtime/asm_amd64.s:362
# 0x1a0060 reflect.Value.call+0x1210         /usr/local/Cellar/go/1.3.3/libexec/src/pkg/reflect/value.go:563
# 0x19ed07 reflect.Value.Call+0xd7          /usr/local/Cellar/go/1.3.3/libexec/src/pkg/reflect/value.go:411

. . .


Notes

There will be several sections of traces.

You'll probably only be interested in the first one.

References

http://golang.org/pkg/runtime/debug/#PrintStack


Share this article



This work is licensed under the Creative Commons Attribution 3.0 Unported License.The output will look something like this:

js-pre-commit-git-hook && go-pre-commit-git-hook


Notes

Put the scripts in your $PATH and make them executable.

Create a .jshintrc file with your desired jshint configuration settings.

References



Share this article



This work is licensed under the Creative Commons Attribution 3.0 Unported License.