// ProfileLabels returns printable labels for a profile. func ProfileLabels(rpt *Report) []string { label := []string{} prof := rpt.prof o := rpt.options if len(prof.Mapping) > 0 { if prof.Mapping[0].File != "" { label = append(label, "File: "+filepath.Base(prof.Mapping[0].File)) } if prof.Mapping[0].BuildID != "" { label = append(label, "Build ID: "+prof.Mapping[0].BuildID) } } label = append(label, prof.Comments...) if o.SampleType != "" { label = append(label, "Type: "+o.SampleType) } if prof.TimeNanos != 0 { const layout = "Jan 2, 2006 at 3:04pm (MST)" label = append(label, "Time: "+time.Unix(0, prof.TimeNanos).Format(layout)) } if prof.DurationNanos != 0 { duration := measurement.Label(prof.DurationNanos, "nanoseconds") totalNanos, totalUnit := measurement.Scale(rpt.total, o.SampleUnit, "nanoseconds") var ratio string if totalUnit == "ns" && totalNanos != 0 { ratio = "(" + percentage(int64(totalNanos), prof.DurationNanos) + ")" } label = append(label, fmt.Sprintf("Duration: %s, Total samples = %s %s", duration, rpt.formatValue(rpt.total), ratio)) } return label }
// printTags collects all tags referenced in the profile and prints // them in a sorted table. func printTags(w io.Writer, rpt *Report) error { p := rpt.prof // Hashtable to keep accumulate tags as key,value,count. tagMap := make(map[string]map[string]int64) for _, s := range p.Sample { for key, vals := range s.Label { for _, val := range vals { if valueMap, ok := tagMap[key]; ok { valueMap[val] = valueMap[val] + s.Value[0] continue } valueMap := make(map[string]int64) valueMap[val] = s.Value[0] tagMap[key] = valueMap } } for key, vals := range s.NumLabel { for _, nval := range vals { val := measurement.Label(nval, key) if valueMap, ok := tagMap[key]; ok { valueMap[val] = valueMap[val] + s.Value[0] continue } valueMap := make(map[string]int64) valueMap[val] = s.Value[0] tagMap[key] = valueMap } } } tagKeys := make([]*graph.Tag, 0, len(tagMap)) for key := range tagMap { tagKeys = append(tagKeys, &graph.Tag{Name: key}) } for _, tagKey := range graph.SortTags(tagKeys, true) { var total int64 key := tagKey.Name tags := make([]*graph.Tag, 0, len(tagMap[key])) for t, c := range tagMap[key] { total += c tags = append(tags, &graph.Tag{Name: t, Flat: c}) } fmt.Fprintf(w, "%s: Total %d\n", key, total) for _, t := range graph.SortTags(tags, true) { if total > 0 { fmt.Fprintf(w, " %8d (%s): %s\n", t.Flat, percentage(t.Flat, total), t.Name) } else { fmt.Fprintf(w, " %8d: %s\n", t.Flat, t.Name) } } fmt.Fprintln(w) } return nil }
func tagGroupLabel(g []*Tag) (label string, flat, cum int64) { if len(g) == 1 { t := g[0] return measurement.Label(t.Value, t.Unit), t.Flat, t.Cum } min := g[0] max := g[0] f := min.Flat c := min.Cum for _, t := range g[1:] { if v, _ := measurement.Scale(t.Value, t.Unit, min.Unit); int64(v) < min.Value { min = t } if v, _ := measurement.Scale(t.Value, t.Unit, max.Unit); int64(v) > max.Value { max = t } f += t.Flat c += t.Cum } return measurement.Label(min.Value, min.Unit) + ".." + measurement.Label(max.Value, max.Unit), f, c }
func (rpt *Report) formatTags(s *profile.Sample) (string, bool) { var labels []string for key, vals := range s.Label { for _, v := range vals { labels = append(labels, key+":"+v) } } for key, nvals := range s.NumLabel { for _, v := range nvals { labels = append(labels, measurement.Label(v, key)) } } if len(labels) == 0 { return "", false } sort.Strings(labels) return strings.Join(labels, `\n`), true }
func formatTag(v int64, key string) string { return measurement.Label(v, key) }