diff options
| author | Hana Kim <hakim@google.com> | 2018-02-13 17:18:08 -0500 |
|---|---|---|
| committer | Hyang-Ah Hana Kim <hyangah@gmail.com> | 2018-02-15 19:33:20 +0000 |
| commit | 1ae22d8cfe3e5a22370d51fb75fe78ab99d8a269 (patch) | |
| tree | ba8322e97dbd82269c41bd5bb45b2e02ce076d2e /src/internal/trace/parser.go | |
| parent | 864ac315bbdfd4ee4508d5754cc7b1be8c25ec8c (diff) | |
| download | go-1ae22d8cfe3e5a22370d51fb75fe78ab99d8a269.tar.xz | |
internal/trace: link user span start and end events
Also add testdata for version 1.11 including UserTaskSpan test trace.
Change-Id: I673fb29bb3aee96a14fadc0ab860d4f5832143f5
Reviewed-on: https://go-review.googlesource.com/93795
Reviewed-by: Heschi Kreinick <heschi@google.com>
Diffstat (limited to 'src/internal/trace/parser.go')
| -rw-r--r-- | src/internal/trace/parser.go | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/src/internal/trace/parser.go b/src/internal/trace/parser.go index e6e1a4d171..155c23940a 100644 --- a/src/internal/trace/parser.go +++ b/src/internal/trace/parser.go @@ -55,6 +55,9 @@ type Event struct { // for blocking GoSysCall: the associated GoSysExit // for GoSysExit: the next GoStart // for GCMarkAssistStart: the associated GCMarkAssistDone + // for UserTaskCreate: the UserTaskEnd + // for UsetTaskEnd: the UserTaskCreate + // for UserSpan: the corresponding span start or end event Link *Event } @@ -584,7 +587,8 @@ func postProcessTrace(ver int, events []*Event) error { gs := make(map[uint64]gdesc) ps := make(map[int]pdesc) - tasks := make(map[uint64]*Event) // task id to task events + tasks := make(map[uint64]*Event) // task id to task creation events + activeSpans := make(map[uint64][]*Event) // goroutine id to stack of spans gs[0] = gdesc{state: gRunning} var evGC, evSTW *Event @@ -729,6 +733,15 @@ func postProcessTrace(ver int, events []*Event) error { g.evStart = nil g.state = gDead p.g = 0 + + if ev.Type == EvGoEnd { // flush all active spans + spans := activeSpans[ev.G] + for _, s := range spans { + s.Link = ev + } + delete(activeSpans, ev.G) + } + case EvGoSched, EvGoPreempt: if err := checkRunning(p, g, ev, false); err != nil { return err @@ -799,6 +812,32 @@ func postProcessTrace(ver int, events []*Event) error { case EvUserTaskEnd: if prevEv, ok := tasks[ev.Args[0]]; ok { prevEv.Link = ev + ev.Link = prevEv + } + case EvUserSpan: + mode := ev.Args[1] + spans := activeSpans[ev.G] + if mode == 0 { // span start + activeSpans[ev.G] = append(spans, ev) // push + } else if mode == 1 { // span end + n := len(spans) + if n > 0 { // matching span start event is in the trace. + s := spans[n-1] + if s.Args[0] != ev.Args[0] || s.SArgs[0] != ev.SArgs[0] { // task id, span name mismatch + return fmt.Errorf("misuse of span in goroutine %d: span end %q when the inner-most active span start event is %q", ev.G, ev, s) + } + // Link span start event with span end event + s.Link = ev + ev.Link = s + + if n > 1 { + activeSpans[ev.G] = spans[:n-1] + } else { + delete(activeSpans, ev.G) + } + } + } else { + return fmt.Errorf("invalid user span mode: %q", ev) } } |
