// greetings prints a brief welcome and some overall profile // information before accepting interactive commands. func greetings(p *profile.Profile, ui plugin.UI) { ropt, err := reportOptions(p, pprofVariables) if err == nil { ui.Print(strings.Join(report.ProfileLabels(report.New(p, ropt)), "\n")) } ui.Print("Entering interactive mode (type \"help\" for commands, \"o\" for options)") }
func printCurrentOptions(p *profile.Profile, ui plugin.UI) { var args []string type groupInfo struct { set string values []string } groups := make(map[string]*groupInfo) for n, o := range pprofVariables { v := o.stringValue() comment := "" if g := o.group; g != "" { gi, ok := groups[g] if !ok { gi = &groupInfo{} groups[g] = gi } if o.boolValue() { gi.set = n } gi.values = append(gi.values, n) continue } switch { case n == "sample_index": st := sampleTypes(p) if v == "" { // Apply default (last sample index). v = st[len(st)-1] } // Add comments for all sample types in profile. comment = "[" + strings.Join(st, " | ") + "]" case n == "source_path": continue case n == "nodecount" && v == "-1": comment = "default" case v == "": // Add quotes for empty values. v = `""` } if comment != "" { comment = commentStart + " " + comment } args = append(args, fmt.Sprintf(" %-25s = %-20s %s", n, v, comment)) } for g, vars := range groups { sort.Strings(vars.values) comment := commentStart + " [" + strings.Join(vars.values, " | ") + "]" args = append(args, fmt.Sprintf(" %-25s = %-20s %s", g, vars.set, comment)) } sort.Strings(args) ui.Print(strings.Join(args, "\n")) }
// convertPerfData converts the file at path which should be in perf.data format // using the perf_to_profile tool and returns the file containing the // profile.proto formatted data. func convertPerfData(perfPath string, ui plugin.UI) (*os.File, error) { ui.Print(fmt.Sprintf( "Converting %s to a profile.proto... (May take a few minutes)", perfPath)) profile, err := newTempFile(os.TempDir(), "pprof_", ".pb.gz") if err != nil { return nil, err } deferDeleteTempFile(profile.Name()) cmd := exec.Command("perf_to_profile", perfPath, profile.Name()) if err := cmd.Run(); err != nil { profile.Close() return nil, fmt.Errorf("failed to convert perf.data file. Try github.com/google/perf_data_converter: %v", err) } return profile, nil }
// fetch fetches a profile from source, within the timeout specified, // producing messages through the ui. It returns the profile and the // url of the actual source of the profile for remote profiles. func fetch(source string, duration, timeout time.Duration, ui plugin.UI) (p *profile.Profile, src string, err error) { var f io.ReadCloser if sourceURL, timeout := adjustURL(source, duration, timeout); sourceURL != "" { ui.Print("Fetching profile over HTTP from " + sourceURL) if duration > 0 { ui.Print(fmt.Sprintf("Please wait... (%v)", duration)) } f, err = fetchURL(sourceURL, timeout) src = sourceURL } else { f, err = os.Open(source) } if err == nil { defer f.Close() p, err = profile.Parse(f) } return }
// commandHelp displays help and usage information for all Commands // and Variables or a specific Command or Variable. func commandHelp(args string, ui plugin.UI) { if args == "" { help := usage(false) help = help + ` : Clear focus/ignore/hide/tagfocus/tagignore type "help <cmd|option>" for more information ` ui.Print(help) return } if c := pprofCommands[args]; c != nil { ui.Print(c.help(args)) return } if v := pprofVariables[args]; v != nil { ui.Print(v.help + "\n") return } ui.PrintErr("Unknown command: " + args) }