Skip to content

Commit

Permalink
cmd/trace/v2: emit regions in the goroutine-oriented task view
Browse files Browse the repository at this point in the history
This change emits regions in the goroutine-oriented task view (the
/trace endpoint with the taskid query variable set) in the same way the
old cmd/trace does.

For #60773.
Fixes #63960.

Change-Id: If6c3e7072c694c84a7d2d6c34df668f48d3acc2a
Reviewed-on: https://go-review.googlesource.com/c/go/+/543995
Reviewed-by: Michael Pratt <mpratt@google.com>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
  • Loading branch information
mknyszek authored and gopherbot committed Nov 21, 2023
1 parent 28f8734 commit 4e3ac99
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 1 deletion.
53 changes: 53 additions & 0 deletions src/cmd/trace/v2/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ func runGenerator(ctx *traceContext, g generator, parsed *parsedTrace, opts *gen
}
for i, task := range opts.tasks {
emitTask(ctx, task, i)
if opts.mode&traceviewer.ModeGoroutineOriented != 0 {
for _, region := range task.Regions {
emitRegion(ctx, region)
}
}
}
g.Finish(ctx)
}
Expand Down Expand Up @@ -130,6 +135,54 @@ func emitTask(ctx *traceContext, task *trace.UserTaskSummary, sortIndex int) {
}
}

// emitRegion emits goroutine-based slice events to the UI. The caller
// must be emitting for a goroutine-oriented trace.
//
// TODO(mknyszek): Make regions part of the regular generator loop and
// treat them like ranges so that we can emit regions in traces oriented
// by proc or thread.
func emitRegion(ctx *traceContext, region *trace.UserRegionSummary) {
if region.Name == "" {
return
}
// Collect information about the region.
var startStack, endStack tracev2.Stack
goroutine := tracev2.NoGoroutine
startTime, endTime := ctx.startTime, ctx.endTime
if region.Start != nil {
startStack = region.Start.Stack()
startTime = region.Start.Time()
goroutine = region.Start.Goroutine()
}
if region.End != nil {
endStack = region.End.Stack()
endTime = region.End.Time()
goroutine = region.End.Goroutine()
}
if goroutine == tracev2.NoGoroutine {
return
}
arg := struct {
TaskID uint64 `json:"taskid"`
}{
TaskID: uint64(region.TaskID),
}
ctx.AsyncSlice(traceviewer.AsyncSliceEvent{
SliceEvent: traceviewer.SliceEvent{
Name: region.Name,
Ts: ctx.elapsed(startTime),
Dur: endTime.Sub(startTime),
Resource: uint64(goroutine),
Stack: ctx.Stack(viewerFrames(startStack)),
EndStack: ctx.Stack(viewerFrames(endStack)),
Arg: arg,
},
Category: "Region",
Scope: fmt.Sprintf("%x", region.TaskID),
TaskColorIndex: uint64(region.TaskID),
})
}

// Building blocks for generators.

// stackSampleGenerator implements a generic handler for stack sample events.
Expand Down
46 changes: 45 additions & 1 deletion src/internal/trace/traceviewer/emitter.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ type Emitter struct {
resources map[uint64]string
focusResource uint64
tasks map[uint64]task
asyncSliceSeq uint64
}

type task struct {
Expand Down Expand Up @@ -376,7 +377,6 @@ func (e *Emitter) slice(s SliceEvent, sectionID uint64, cname string) {
Arg: s.Arg,
Cname: cname,
})

}

type SliceEvent struct {
Expand All @@ -389,6 +389,50 @@ type SliceEvent struct {
Arg any
}

func (e *Emitter) AsyncSlice(s AsyncSliceEvent) {
if !e.tsWithinRange(s.Ts) && !e.tsWithinRange(s.Ts+s.Dur) {
return
}
if e.filter != nil && !e.filter(s.Resource) {
return
}
cname := ""
if s.TaskColorIndex != 0 {
cname = pickTaskColor(s.TaskColorIndex)
}
e.asyncSliceSeq++
e.OptionalEvent(&format.Event{
Category: s.Category,
Name: s.Name,
Phase: "b",
Time: viewerTime(s.Ts),
TID: s.Resource,
ID: e.asyncSliceSeq,
Scope: s.Scope,
Stack: s.Stack,
Cname: cname,
})
e.OptionalEvent(&format.Event{
Category: s.Category,
Name: s.Name,
Phase: "e",
Time: viewerTime(s.Ts + s.Dur),
TID: s.Resource,
ID: e.asyncSliceSeq,
Scope: s.Scope,
Stack: s.EndStack,
Arg: s.Arg,
Cname: cname,
})
}

type AsyncSliceEvent struct {
SliceEvent
Category string
Scope string
TaskColorIndex uint64 // Take on the same color as the task with this ID.
}

func (e *Emitter) Instant(i InstantEvent) {
if !e.tsWithinRange(i.Ts) {
return
Expand Down

0 comments on commit 4e3ac99

Please sign in to comment.