diff options
| author | Hana Kim <hakim@google.com> | 2018-01-25 15:13:12 -0500 |
|---|---|---|
| committer | Hyang-Ah Hana Kim <hyangah@gmail.com> | 2018-02-20 19:44:53 +0000 |
| commit | fdcf4f712b7c160fe76a15b4b405be9916be558b (patch) | |
| tree | 9a320f16b8f0d4f98d365d4b591f79b489c040df /src/cmd/trace/annotations.go | |
| parent | d6856036bf2887de51f6408c7e283b66b57f7fa7 (diff) | |
| download | go-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.go | 73 |
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" |
