func generate(interactive bool, prof *profile.Profile, obj plugin.ObjTool, ui plugin.UI, f *flags) error { o, postProcess, err := parseOptions(f) if err != nil { return err } var w io.Writer if *f.flagOutput == "" { w = os.Stdout } else { ui.PrintErr("Generating report in ", *f.flagOutput) outputFile, err := os.Create(*f.flagOutput) if err != nil { return err } defer outputFile.Close() w = outputFile } if prof.Empty() { return fmt.Errorf("profile is empty") } value, stype, unit := sampleFormat(prof, f) o.SampleType = stype rpt := report.New(prof, *o, value, unit) // Do not apply filters if we're just generating a proto, so we // still have all the data. if o.OutputFormat != report.Proto { // Delay applying focus/ignore until after creating the report so // the report reflects the total number of samples. if err := preprocess(prof, ui, f); err != nil { return err } } if postProcess == nil { return report.Generate(w, rpt, obj) } var dot bytes.Buffer if err = report.Generate(&dot, rpt, obj); err != nil { return err } return postProcess(&dot, w, ui) }
// filter filters the report with a focus regex. If no focus is provided, // it reports back with the entire set of calls. // Focus regex works on the package, type and function names. Filtered // results will include parent samples from the call graph. func (r *report) filter(cum bool, focus *regexp.Regexp) []string { r.mu.Lock() defer r.mu.Unlock() if r.p == nil { return nil } c := r.p.Copy() c.FilterSamplesByName(focus, nil, nil) rpt := goreport.NewDefault(c, goreport.Options{ OutputFormat: goreport.Text, CumSort: cum, PrintAddresses: true, }) buf := bytes.NewBuffer(nil) goreport.Generate(buf, rpt, nil) return strings.Split(buf.String(), "\n") }