Skip to content

Commit 1ae22d8

Browse files
committed
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 <[email protected]>
1 parent 864ac31 commit 1ae22d8

File tree

7 files changed

+81
-17
lines changed

7 files changed

+81
-17
lines changed

src/internal/trace/mkcanned.bash

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ if [ $# != 1 ]; then
1414
fi
1515

1616
go test -run ClientServerParallel4 -trace "testdata/http_$1_good" net/http
17-
go test -run 'TraceStress$|TraceStressStartStop$' runtime/trace -savetraces
17+
go test -run 'TraceStress$|TraceStressStartStop$|TestUserTaskSpan$' runtime/trace -savetraces
1818
mv ../../runtime/trace/TestTraceStress.trace "testdata/stress_$1_good"
1919
mv ../../runtime/trace/TestTraceStressStartStop.trace "testdata/stress_start_stop_$1_good"
20+
mv ../../runtime/trace/TestUserTaskSpan.trace "testdata/user_task_span_$1_good"

src/internal/trace/parser.go

+40-1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ type Event struct {
5555
// for blocking GoSysCall: the associated GoSysExit
5656
// for GoSysExit: the next GoStart
5757
// for GCMarkAssistStart: the associated GCMarkAssistDone
58+
// for UserTaskCreate: the UserTaskEnd
59+
// for UsetTaskEnd: the UserTaskCreate
60+
// for UserSpan: the corresponding span start or end event
5861
Link *Event
5962
}
6063

@@ -584,7 +587,8 @@ func postProcessTrace(ver int, events []*Event) error {
584587

585588
gs := make(map[uint64]gdesc)
586589
ps := make(map[int]pdesc)
587-
tasks := make(map[uint64]*Event) // task id to task events
590+
tasks := make(map[uint64]*Event) // task id to task creation events
591+
activeSpans := make(map[uint64][]*Event) // goroutine id to stack of spans
588592
gs[0] = gdesc{state: gRunning}
589593
var evGC, evSTW *Event
590594

@@ -729,6 +733,15 @@ func postProcessTrace(ver int, events []*Event) error {
729733
g.evStart = nil
730734
g.state = gDead
731735
p.g = 0
736+
737+
if ev.Type == EvGoEnd { // flush all active spans
738+
spans := activeSpans[ev.G]
739+
for _, s := range spans {
740+
s.Link = ev
741+
}
742+
delete(activeSpans, ev.G)
743+
}
744+
732745
case EvGoSched, EvGoPreempt:
733746
if err := checkRunning(p, g, ev, false); err != nil {
734747
return err
@@ -799,6 +812,32 @@ func postProcessTrace(ver int, events []*Event) error {
799812
case EvUserTaskEnd:
800813
if prevEv, ok := tasks[ev.Args[0]]; ok {
801814
prevEv.Link = ev
815+
ev.Link = prevEv
816+
}
817+
case EvUserSpan:
818+
mode := ev.Args[1]
819+
spans := activeSpans[ev.G]
820+
if mode == 0 { // span start
821+
activeSpans[ev.G] = append(spans, ev) // push
822+
} else if mode == 1 { // span end
823+
n := len(spans)
824+
if n > 0 { // matching span start event is in the trace.
825+
s := spans[n-1]
826+
if s.Args[0] != ev.Args[0] || s.SArgs[0] != ev.SArgs[0] { // task id, span name mismatch
827+
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)
828+
}
829+
// Link span start event with span end event
830+
s.Link = ev
831+
ev.Link = s
832+
833+
if n > 1 {
834+
activeSpans[ev.G] = spans[:n-1]
835+
} else {
836+
delete(activeSpans, ev.G)
837+
}
838+
}
839+
} else {
840+
return fmt.Errorf("invalid user span mode: %q", ev)
802841
}
803842
}
804843

2.71 KB
Binary file not shown.
361 KB
Binary file not shown.
Binary file not shown.
Binary file not shown.

src/runtime/trace/annotation_test.go

+39-15
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ func TestUserTaskSpan(t *testing.T) {
1414
bgctx, cancel := context.WithCancel(context.Background())
1515
defer cancel()
1616

17-
// TODO(hyangah): test pre-existing spans don't cause troubles
17+
preExistingSpanEnd := StartSpan(bgctx, "pre-existing span")
1818

1919
buf := new(bytes.Buffer)
2020
if err := Start(buf); err != nil {
@@ -27,17 +27,27 @@ func TestUserTaskSpan(t *testing.T) {
2727
wg.Add(1)
2828
go func() {
2929
defer wg.Done()
30-
defer end() // EvUserTaskEnd("span0")
30+
defer end() // EvUserTaskEnd("task0")
3131

3232
WithSpan(ctx, "span0", func(ctx context.Context) {
3333
// EvUserSpanCreate("span0", start)
34-
Log(ctx, "key0", "0123456789abcdef") // EvUserLog("task0", "key0", "0....f")
34+
WithSpan(ctx, "span1", func(ctx context.Context) {
35+
Log(ctx, "key0", "0123456789abcdef") // EvUserLog("task0", "key0", "0....f")
36+
})
3537
// EvUserSpan("span0", end)
3638
})
3739
}()
40+
3841
wg.Wait()
42+
43+
preExistingSpanEnd()
44+
postExistingSpanEnd := StartSpan(bgctx, "post-existing span")
45+
3946
// End of traced execution
4047
Stop()
48+
49+
postExistingSpanEnd()
50+
4151
saveTrace(t, buf, "TestUserTaskSpan")
4252
res, err := trace.Parse(buf, "")
4353
if err != nil {
@@ -46,9 +56,10 @@ func TestUserTaskSpan(t *testing.T) {
4656

4757
// Check whether we see all user annotation related records in order
4858
type testData struct {
49-
typ byte
50-
strs []string
51-
args []uint64
59+
typ byte
60+
strs []string
61+
args []uint64
62+
setLink bool
5263
}
5364

5465
var got []testData
@@ -58,27 +69,40 @@ func TestUserTaskSpan(t *testing.T) {
5869
switch e.Type {
5970
case trace.EvUserTaskCreate:
6071
taskName := e.SArgs[0]
61-
got = append(got, testData{trace.EvUserTaskCreate, []string{taskName}, nil})
72+
got = append(got, testData{trace.EvUserTaskCreate, []string{taskName}, nil, e.Link != nil})
73+
if e.Link != nil && e.Link.Type != trace.EvUserTaskEnd {
74+
t.Errorf("Unexpected linked event %q->%q", e, e.Link)
75+
}
6276
tasks[e.Args[0]] = taskName
6377
case trace.EvUserLog:
6478
key, val := e.SArgs[0], e.SArgs[1]
6579
taskName := tasks[e.Args[0]]
66-
got = append(got, testData{trace.EvUserLog, []string{taskName, key, val}, nil})
80+
got = append(got, testData{trace.EvUserLog, []string{taskName, key, val}, nil, e.Link != nil})
6781
case trace.EvUserTaskEnd:
6882
taskName := tasks[e.Args[0]]
69-
got = append(got, testData{trace.EvUserTaskEnd, []string{taskName}, nil})
83+
got = append(got, testData{trace.EvUserTaskEnd, []string{taskName}, nil, e.Link != nil})
84+
if e.Link != nil && e.Link.Type != trace.EvUserTaskCreate {
85+
t.Errorf("Unexpected linked event %q->%q", e, e.Link)
86+
}
7087
case trace.EvUserSpan:
7188
taskName := tasks[e.Args[0]]
7289
spanName := e.SArgs[0]
73-
got = append(got, testData{trace.EvUserSpan, []string{taskName, spanName}, []uint64{e.Args[1]}})
90+
got = append(got, testData{trace.EvUserSpan, []string{taskName, spanName}, []uint64{e.Args[1]}, e.Link != nil})
91+
if e.Link != nil && (e.Link.Type != trace.EvUserSpan || e.Link.SArgs[0] != spanName) {
92+
t.Errorf("Unexpected linked event %q->%q", e, e.Link)
93+
}
7494
}
7595
}
7696
want := []testData{
77-
{trace.EvUserTaskCreate, []string{"task0"}, nil},
78-
{trace.EvUserSpan, []string{"task0", "span0"}, []uint64{0}},
79-
{trace.EvUserLog, []string{"task0", "key0", "0123456789abcdef"}, nil},
80-
{trace.EvUserSpan, []string{"task0", "span0"}, []uint64{1}},
81-
{trace.EvUserTaskEnd, []string{"task0"}, nil},
97+
{trace.EvUserTaskCreate, []string{"task0"}, nil, true},
98+
{trace.EvUserSpan, []string{"task0", "span0"}, []uint64{0}, true},
99+
{trace.EvUserSpan, []string{"task0", "span1"}, []uint64{0}, true},
100+
{trace.EvUserLog, []string{"task0", "key0", "0123456789abcdef"}, nil, false},
101+
{trace.EvUserSpan, []string{"task0", "span1"}, []uint64{1}, true},
102+
{trace.EvUserSpan, []string{"task0", "span0"}, []uint64{1}, true},
103+
{trace.EvUserTaskEnd, []string{"task0"}, nil, true},
104+
{trace.EvUserSpan, []string{"", "pre-existing span"}, []uint64{1}, false},
105+
{trace.EvUserSpan, []string{"", "post-existing span"}, []uint64{0}, false},
82106
}
83107
if !reflect.DeepEqual(got, want) {
84108
t.Errorf("Got user span related events %+v\nwant: %+v", got, want)

0 commit comments

Comments
 (0)