aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/trace/annotations.go
diff options
context:
space:
mode:
authorHana Kim <hakim@google.com>2018-01-25 15:13:12 -0500
committerHyang-Ah Hana Kim <hyangah@gmail.com>2018-02-20 19:44:53 +0000
commitfdcf4f712b7c160fe76a15b4b405be9916be558b (patch)
tree9a320f16b8f0d4f98d365d4b591f79b489c040df /src/cmd/trace/annotations.go
parentd6856036bf2887de51f6408c7e283b66b57f7fa7 (diff)
downloadgo-fdcf4f712b7c160fe76a15b4b405be9916be558b.tar.xz
cmd/trace: task-oriented view includes child tasks
R=go1.11 Change-Id: Ibb09e309c745eba811a0b53000c063bc10a055e1 Reviewed-on: https://go-review.googlesource.com/90218 Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Peter Weinberger <pjw@google.com>
Diffstat (limited to 'src/cmd/trace/annotations.go')
-rw-r--r--src/cmd/trace/annotations.go73
1 files changed, 66 insertions, 7 deletions
diff --git a/src/cmd/trace/annotations.go b/src/cmd/trace/annotations.go
index c69f62cae5..b9c14b140c 100644
--- a/src/cmd/trace/annotations.go
+++ b/src/cmd/trace/annotations.go
@@ -20,12 +20,13 @@ func init() {
// httpUserTasks reports all tasks found in the trace.
func httpUserTasks(w http.ResponseWriter, r *http.Request) {
- tasks, err := analyzeAnnotations()
+ res, err := analyzeAnnotations()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
+ tasks := res.tasks
summary := make(map[string]taskStats)
for _, task := range tasks {
stats, ok := summary[task.name]
@@ -62,11 +63,12 @@ func httpUserTask(w http.ResponseWriter, r *http.Request) {
return
}
- tasks, err := analyzeAnnotations()
+ res, err := analyzeAnnotations()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
+ tasks := res.tasks
type event struct {
WhenString string
@@ -139,21 +141,27 @@ func httpUserTask(w http.ResponseWriter, r *http.Request) {
}
}
+type annotationAnalysisResult struct {
+ tasks map[uint64]*taskDesc // tasks
+ gcEvents []*trace.Event // GCStartevents, sorted
+}
+
// analyzeAnnotations analyzes user annotation events and
// returns the task descriptors keyed by internal task id.
-func analyzeAnnotations() (map[uint64]*taskDesc, error) {
+func analyzeAnnotations() (annotationAnalysisResult, error) {
res, err := parseTrace()
if err != nil {
- return nil, fmt.Errorf("failed to parse trace: %v", err)
+ return annotationAnalysisResult{}, fmt.Errorf("failed to parse trace: %v", err)
}
events := res.Events
if len(events) == 0 {
- return nil, fmt.Errorf("empty trace")
+ return annotationAnalysisResult{}, fmt.Errorf("empty trace")
}
tasks := allTasks{}
activeSpans := map[uint64][]*trace.Event{} // goid to active span start events
+ var gcEvents []*trace.Event
for _, ev := range events {
goid := ev.G
@@ -164,6 +172,17 @@ func analyzeAnnotations() (map[uint64]*taskDesc, error) {
task := tasks.task(taskid)
task.addEvent(ev)
+ // retrieve parent task information
+ if typ == trace.EvUserTaskCreate {
+ if parentID := ev.Args[1]; parentID != 0 {
+ parentTask := tasks.task(parentID)
+ task.parent = parentTask
+ if parentTask != nil {
+ parentTask.children = append(parentTask.children, task)
+ }
+ }
+ }
+
if typ == trace.EvUserSpan {
mode := ev.Args[1]
spans := activeSpans[goid]
@@ -191,9 +210,12 @@ func analyzeAnnotations() (map[uint64]*taskDesc, error) {
taskid := spans[len(spans)-1].Args[0]
task := tasks.task(taskid)
task.addEvent(ev)
+
+ case trace.EvGCStart:
+ gcEvents = append(gcEvents, ev)
}
}
- return tasks, nil
+ return annotationAnalysisResult{tasks: tasks, gcEvents: gcEvents}, nil
}
// taskDesc represents a task.
@@ -206,6 +228,16 @@ type taskDesc struct {
create *trace.Event // Task create event
end *trace.Event // Task end event
+
+ parent *taskDesc
+ children []*taskDesc
+}
+
+func newTaskDesc(id uint64) *taskDesc {
+ return &taskDesc{
+ id: id,
+ goroutines: make(map[uint64][]*trace.Event),
+ }
}
func (task *taskDesc) String() string {
@@ -220,6 +252,14 @@ func (task *taskDesc) String() string {
for _, s := range task.spans {
fmt.Fprintf(wb, "\t\t%s(goid=%d)\n", s.name, s.goid)
}
+ if task.parent != nil {
+ fmt.Fprintf(wb, "\tparent: %s\n", task.parent.name)
+ }
+ fmt.Fprintf(wb, "\t%d children:\n", len(task.children))
+ for _, c := range task.children {
+ fmt.Fprintf(wb, "\t\t%s\n", c.name)
+ }
+
return wb.String()
}
@@ -297,6 +337,21 @@ func (task *taskDesc) complete() bool {
return task.create != nil && task.end != nil
}
+// descendents returns all the task nodes in the subtree rooted from this task.
+func (task *taskDesc) decendents() []*taskDesc {
+ if task == nil {
+ return nil
+ }
+ res := []*taskDesc{task}
+ for i := 0; len(res[i:]) > 0; i++ {
+ t := res[i]
+ for _, c := range t.children {
+ res = append(res, c)
+ }
+ }
+ return res
+}
+
// firstTimestamp returns the first timestamp of this task found in
// this trace. If the trace does not contain the task creation event,
// the first timestamp of the trace will be returned.
@@ -701,7 +756,11 @@ func describeEvent(ev *trace.Event) string {
case trace.EvGoEnd, trace.EvGoStop:
return "goroutine stopped"
case trace.EvUserLog:
- return fmt.Sprintf("%v=%v", ev.SArgs[0], ev.SArgs[1])
+ if k, v := ev.SArgs[0], ev.SArgs[1]; k == "" {
+ return v
+ } else {
+ return fmt.Sprintf("%v=%v", k, v)
+ }
case trace.EvUserSpan:
if ev.Args[1] == 0 {
duration := "unknown"