From 817009da40b8adaaf2498f30cd5026b1eaf02cf8 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Fri, 19 Jan 2024 19:25:04 +0000 Subject: [PATCH] [release-branch.go1.22] cmd/trace/v2: emit user log annotations in all views This was an oversight in porting over cmd/trace to the new trace format and API. Fixes #65153. Change-Id: I883d302f95956fcc9abb60aa53165acb6d099d67 Reviewed-on: https://go-review.googlesource.com/c/go/+/557175 LUCI-TryBot-Result: Go LUCI Reviewed-by: Michael Pratt (cherry picked from commit 7cb98c1da1d38447a272c50b2a33634ebb845aa4) Reviewed-on: https://go-review.googlesource.com/c/go/+/557817 Reviewed-by: Cherry Mui Auto-Submit: Michael Knyszek --- src/cmd/trace/v2/gen.go | 35 ++++++++++++++++++++++++++++++++ src/cmd/trace/v2/goroutinegen.go | 5 ++++- src/cmd/trace/v2/procgen.go | 5 ++++- src/cmd/trace/v2/threadgen.go | 5 ++++- 4 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/cmd/trace/v2/gen.go b/src/cmd/trace/v2/gen.go index ad1599db92..f6a4bb643b 100644 --- a/src/cmd/trace/v2/gen.go +++ b/src/cmd/trace/v2/gen.go @@ -31,6 +31,9 @@ type generator interface { ProcRange(ctx *traceContext, ev *tracev2.Event) ProcTransition(ctx *traceContext, ev *tracev2.Event) + // User annotations. + Log(ctx *traceContext, ev *tracev2.Event) + // Finish indicates the end of the trace and finalizes generation. Finish(ctx *traceContext) } @@ -69,6 +72,8 @@ func runGenerator(ctx *traceContext, g generator, parsed *parsedTrace, opts *gen case tracev2.ResourceGoroutine: g.GoroutineTransition(ctx, ev) } + case tracev2.EventLog: + g.Log(ctx, ev) } } for i, task := range opts.tasks { @@ -357,3 +362,33 @@ type completedRange struct { endStack tracev2.Stack arg any } + +type logEventGenerator[R resource] struct { + // getResource is a function to extract a resource ID from a Log event. + getResource func(*tracev2.Event) R +} + +// Log implements a log event handler. It expects ev to be one such event. +func (g *logEventGenerator[R]) Log(ctx *traceContext, ev *tracev2.Event) { + id := g.getResource(ev) + if id == R(noResource) { + // We have nowhere to put this in the UI. + return + } + + // Construct the name to present. + log := ev.Log() + name := log.Message + if log.Category != "" { + name = "[" + log.Category + "] " + name + } + + // Emit an instant event. + ctx.Instant(traceviewer.InstantEvent{ + Name: name, + Ts: ctx.elapsed(ev.Time()), + Category: "user event", + Resource: uint64(id), + Stack: ctx.Stack(viewerFrames(ev.Stack())), + }) +} diff --git a/src/cmd/trace/v2/goroutinegen.go b/src/cmd/trace/v2/goroutinegen.go index eb1aea9bfa..c76bd8487a 100644 --- a/src/cmd/trace/v2/goroutinegen.go +++ b/src/cmd/trace/v2/goroutinegen.go @@ -14,6 +14,7 @@ type goroutineGenerator struct { globalRangeGenerator globalMetricGenerator stackSampleGenerator[tracev2.GoID] + logEventGenerator[tracev2.GoID] gStates map[tracev2.GoID]*gState[tracev2.GoID] focus tracev2.GoID @@ -22,9 +23,11 @@ type goroutineGenerator struct { func newGoroutineGenerator(ctx *traceContext, focus tracev2.GoID, filter map[tracev2.GoID]struct{}) *goroutineGenerator { gg := new(goroutineGenerator) - gg.stackSampleGenerator.getResource = func(ev *tracev2.Event) tracev2.GoID { + rg := func(ev *tracev2.Event) tracev2.GoID { return ev.Goroutine() } + gg.stackSampleGenerator.getResource = rg + gg.logEventGenerator.getResource = rg gg.gStates = make(map[tracev2.GoID]*gState[tracev2.GoID]) gg.focus = focus gg.filter = filter diff --git a/src/cmd/trace/v2/procgen.go b/src/cmd/trace/v2/procgen.go index 30ed568dad..41e379527f 100644 --- a/src/cmd/trace/v2/procgen.go +++ b/src/cmd/trace/v2/procgen.go @@ -18,6 +18,7 @@ type procGenerator struct { globalMetricGenerator procRangeGenerator stackSampleGenerator[tracev2.ProcID] + logEventGenerator[tracev2.ProcID] gStates map[tracev2.GoID]*gState[tracev2.ProcID] inSyscall map[tracev2.ProcID]*gState[tracev2.ProcID] @@ -26,9 +27,11 @@ type procGenerator struct { func newProcGenerator() *procGenerator { pg := new(procGenerator) - pg.stackSampleGenerator.getResource = func(ev *tracev2.Event) tracev2.ProcID { + rg := func(ev *tracev2.Event) tracev2.ProcID { return ev.Proc() } + pg.stackSampleGenerator.getResource = rg + pg.logEventGenerator.getResource = rg pg.gStates = make(map[tracev2.GoID]*gState[tracev2.ProcID]) pg.inSyscall = make(map[tracev2.ProcID]*gState[tracev2.ProcID]) return pg diff --git a/src/cmd/trace/v2/threadgen.go b/src/cmd/trace/v2/threadgen.go index c2d2071926..e1cae2b2cf 100644 --- a/src/cmd/trace/v2/threadgen.go +++ b/src/cmd/trace/v2/threadgen.go @@ -17,6 +17,7 @@ type threadGenerator struct { globalRangeGenerator globalMetricGenerator stackSampleGenerator[tracev2.ThreadID] + logEventGenerator[tracev2.ThreadID] gStates map[tracev2.GoID]*gState[tracev2.ThreadID] threads map[tracev2.ThreadID]struct{} @@ -24,9 +25,11 @@ type threadGenerator struct { func newThreadGenerator() *threadGenerator { tg := new(threadGenerator) - tg.stackSampleGenerator.getResource = func(ev *tracev2.Event) tracev2.ThreadID { + rg := func(ev *tracev2.Event) tracev2.ThreadID { return ev.Thread() } + tg.stackSampleGenerator.getResource = rg + tg.logEventGenerator.getResource = rg tg.gStates = make(map[tracev2.GoID]*gState[tracev2.ThreadID]) tg.threads = make(map[tracev2.ThreadID]struct{}) return tg -- 2.48.1