3

Similar to the question: How to dump goroutine stacktraces?

I took over a go program but it's fairly complex and I am not able to manually follow the code flow by reading code as some methods are executed and I have no idea why.

Is there a way I could print out all the methods that were executed after main.go was run?

I am aware of: https://golang.org/pkg/net/http/pprof/ but I am able to see only goroutines run, not the specific methods I am unable to backtrace/reverse engineer.

Lukas Lukac
  • 7,766
  • 10
  • 65
  • 75
  • `pprof` is a complete profiler. It will generate complete profiles, including all function calls and the memory/CPU usage of each. It is covered well [on the Go blog](https://blog.golang.org/profiling-go-programs). – Adrian Mar 22 '18 at 20:03
  • 1
    Have you tried to step through the program using `delve`? – kostix Mar 22 '18 at 20:05
  • 2
    pprof is a _sampling_ profiler, so it only records where samples were taken. – JimB Mar 22 '18 at 20:23
  • i will give another chance @Adrian to the: http://localhost:6060/debug/pprof/goroutine?debug=2 if you say that everything what was executed must be there, maybe I got lost in the bunch of text with 0x72, 0x0, 0x0, 0x0... is there a way to display it with some -h flag? The debugger doesn't work for me because it's a blockchain ethereum madness also running some C libraries or so. – Lukas Lukac Mar 22 '18 at 20:27
  • No, I didn't say it would all be in the goroutine output. Read the documentation I linked in my first comment. – Adrian Mar 22 '18 at 20:29
  • Adrian will do, will take a while though is a massive doc, will get back to you once done. @JimB u mean not everything could be recorded because "Some profilers operate by sampling. A sampling profiler probes the target program's call stack at regular intervals using operating system interrupts. Sampling profiles are typically less numerically accurate and specific, but allow the target program to run at near full speed." ? Or am I completely lost? – Lukas Lukac Mar 22 '18 at 20:33
  • 1
    @EnchanterIO: yes, pprof (and most profilers) don't trace and time of every function call, they record the number of times each function was sampled. You need to exercise the code you want profiled for some extended period of time. – JimB Mar 22 '18 at 20:36

1 Answers1

2

When I'm not sure how a method got called, I find the easiest is to debug.PrintStack() at the start of it. If that scrolls past too fast, make it panic.

I think if you printed all the methods executed, the signal would get lost in the noise.

Another helpful way is to write a unit test that just calls a part of the code you are interested in. Run it and watch what happens. Put some print statements in. Once you figure out what's happening, add some checks to your unit test (to make it a real test), and you've improved the code already.

Once you have a unit test (or any entry point), you can also step into it with delve.

Michael Feather's "Working Effectively With Legacy Code" is pretty good, it gives lots of strategies to attack legacy code, and refactor it to goodness.

Finally, I've found it's difficult to make Go really confusing, so I'm usually really glad if the complex code I inherit is in Go :-)

Graham King
  • 5,710
  • 3
  • 25
  • 23
  • thx Gragam. I tried already the debug.PrintStack like the first thing actually but it didn't print anything maybe I did something wrong. Will try again. Yea unit testing is definitely the best approach to this issue and I will mock the troublemaking libraries and then debug part of it. I read this book already few years ago :) I have to do something else right now but will get back to this question/answer/comments in few days and resolve it or update it with progress. – Lukas Lukac Mar 24 '18 at 11:17
  • 1
    Does `fmt.Println` print anything? Maybe your program's stdout is going to a log file or the systemd journal. Or maybe the method where you put debug.PrintStack is not being called. – Graham King Mar 25 '18 at 20:54