0

I'm trying to get a call tree with go tool trace, but it shows only top 80 functions and doesn't seem to support pprof's flags like --nodecount, etc. How can I make the traces show all nodes? And if trace isn't designed for that, how can I get a full call tree regardless of function's execution time, since pprof can miss it if it doens't run long enough?

  • 1
    The main goal of `trace` is not to make a call graph, its main goal is performance improvement related. You might find https://github.com/ofabry/go-callvis useful, it uses static code analysis to make a callgraph – Dylan Reimerink Jan 13 '22 at 18:11
  • Thanks, seems like a reasonable solution, but it will build a tree with all possible options what is an overkill to me. I need a complete tree, but for a specific scenario, so is it even possible or go tools aren't supposed for this? – DENIS KOVALENKO Jan 13 '22 at 19:30
  • 1
    You can ask go-callvis to limit what it draws with parameters. There are no standard go tools which are perfect for the job. pprof and trace are ultimately meant for performance optimization and runtime analysis. I am afraid you have to look into third party projects to get something you want. I guess more programmers are interested in performance than documentation :) – Dylan Reimerink Jan 14 '22 at 09:19

2 Answers2

1

go-callvis can be checked as it provides a very high level overview of the Go program using data from call graph and its relations with packages and types.

Typically it runs a pointer analysis to construct the call graph of the program and uses the data to generate output in dot format, which can be rendered with Graphviz tools. High level overview shall be as below.

enter image description here

Reference : https://github.com/ofabry/go-callvis

Karthik Balaguru
  • 7,424
  • 7
  • 48
  • 65
0

to show every function call, you have to add instrumentation to your code.

https://github.com/jbardin/gotrace does this automatically.

        files := []string{}
        e = filepath.Walk(copysrcdir, func(path string, info os.FileInfo, err error) error {
            if mioutil.IsRegularFile(path) && filepath.Ext(path) == ".go" {
                files = append(files, path)
            }
            return nil
        })
        errs.PanicOnError(e)

        var wg sync.WaitGroup
        for _, file := range files {
            wg.Add(1)
            go func(file string) {
                defer wg.Done()
                log.Println("adding trace to " + file)
                cmd := exec.Command("gotrace", "-w", "-timing", "-returns", file)
                e = cmd.Run()
                errs.PanicOnError(e)
            }(file)
        }
        wg.Wait()

You then compile the code with instrumentation and use that binary.

hbt
  • 1,011
  • 3
  • 16
  • 28