diff --git a/internal/driver/cli.go b/internal/driver/cli.go index b97ef85169..7b8c3fc607 100644 --- a/internal/driver/cli.go +++ b/internal/driver/cli.go @@ -37,6 +37,7 @@ type source struct { HTTPHostport string HTTPDisableBrowser bool Comment string + AllFrames bool } // parseFlags parses the command lines through the specified flags package @@ -51,7 +52,8 @@ func parseFlags(o *plugin.Options) (*source, []string, error) { flagSymbolize := flag.String("symbolize", "", "Options for profile symbolization") flagBuildID := flag.String("buildid", "", "Override build id for first mapping") flagTimeout := flag.Int("timeout", -1, "Timeout in seconds for fetching a profile") - flagAddComment := flag.String("add_comment", "", "Annotation string to record in the profile") + flagAddComment := flag.String("add_comment", "", "Free-form annotation to add to the profile") + flagAllFrames := flag.Bool("all_frames", false, "Ignore drop_frames and keep_frames regexps") // CPU profile options flagSeconds := flag.Int("seconds", -1, "Length of time for dynamic profiles") // Heap profile options @@ -145,6 +147,7 @@ func parseFlags(o *plugin.Options) (*source, []string, error) { HTTPHostport: *flagHTTP, HTTPDisableBrowser: *flagNoBrowser, Comment: *flagAddComment, + AllFrames: *flagAllFrames, } if err := source.addBaseProfiles(*flagBase, *flagDiffBase); err != nil { @@ -338,6 +341,8 @@ var usageMsgVars = "\n\n" + " Port is optional and a randomly available port by default.\n" + " -no_browser Skip opening a browser for the interactive web UI.\n" + " -tools Search path for object tools\n" + + " -all_frames Ignore drop_frames and keep_frames regexps in the profile\n" + + " Rarely needed, mainly used for debugging pprof itself\n" + "\n" + " Legacy convenience options:\n" + " -inuse_space Same as -sample_index=inuse_space\n" + diff --git a/internal/driver/driver_test.go b/internal/driver/driver_test.go index 50cf21e9f0..a815fb379b 100644 --- a/internal/driver/driver_test.go +++ b/internal/driver/driver_test.go @@ -61,6 +61,7 @@ func TestParse(t *testing.T) { {"text,files,flat", "heap"}, {"text,files,flat,focus=[12]00,taghide=[X3]00", "heap"}, {"text,inuse_objects,flat", "heap"}, + {"text,inuse_objects,flat,all_frames", "heap"}, {"text,lines,cum,hide=line[X3]0", "cpu"}, {"text,lines,cum,show=[12]00", "cpu"}, {"text,lines,cum,hide=line[X3]0,focus=[12]00", "cpu"}, @@ -270,6 +271,7 @@ func solutionFilename(source string, f *testFlags) string { name = addString(name, f, []string{"seconds"}) name = addString(name, f, []string{"call_tree"}) name = addString(name, f, []string{"text", "tree", "callgrind", "dot", "svg", "tags", "dot", "traces", "disasm", "peek", "weblist", "topproto", "comments"}) + name = addString(name, f, []string{"all_frames"}) if f.strings["focus"] != "" || f.strings["tagfocus"] != "" { name = append(name, "focus") } diff --git a/internal/driver/fetch.go b/internal/driver/fetch.go index 969c1dac11..6d967a2037 100644 --- a/internal/driver/fetch.go +++ b/internal/driver/fetch.go @@ -77,6 +77,11 @@ func fetchProfiles(s *source, o *plugin.Options) (*profile.Profile, error) { } } + if s.AllFrames { + p.DropFrames = "" + p.KeepFrames = "" + } + // Symbolize the merged profile. if err := o.Sym.Symbolize(s.Symbolize, m, p); err != nil { return nil, err diff --git a/internal/driver/testdata/pprof.heap.flat.inuse_objects.text.all_frames b/internal/driver/testdata/pprof.heap.flat.inuse_objects.text.all_frames new file mode 100644 index 0000000000..2211b18a50 --- /dev/null +++ b/internal/driver/testdata/pprof.heap.flat.inuse_objects.text.all_frames @@ -0,0 +1,11 @@ +Showing nodes accounting for 150, 100% of 150 total + flat flat% sum% cum cum% + 120 80.00% 80.00% 150 100% operator new (inline) + 30 20.00% 100% 30 20.00% pruneme (inline) + 0 0% 100% 30 20.00% line1000 + 0 0% 100% 50 33.33% line2000 + 0 0% 100% 50 33.33% line2001 (inline) + 0 0% 100% 150 100% line3000 + 0 0% 100% 110 73.33% line3001 (inline) + 0 0% 100% 130 86.67% line3002 (inline) + 0 0% 100% 30 20.00% malloc (inline)