if ctx.mode != defaultTraceview {
continue
}
- ctx.emitInstant(ev, "proc start")
+ ctx.emitInstant(ev, "proc start", "")
case trace.EvProcStop:
if ctx.mode != defaultTraceview {
continue
}
- ctx.emitInstant(ev, "proc stop")
+ ctx.emitInstant(ev, "proc stop", "")
case trace.EvGCStart:
ctx.emitSlice(ev, "GC")
case trace.EvGCDone:
case trace.EvGoUnblock:
ctx.emitArrow(ev, "unblock")
case trace.EvGoSysCall:
- ctx.emitInstant(ev, "syscall")
+ ctx.emitInstant(ev, "syscall", "")
case trace.EvGoSysExit:
ctx.emitArrow(ev, "sysexit")
+ case trace.EvUserLog:
+ ctx.emitInstant(ev, formatUserLog(ev), "user event")
+ case trace.EvUserTaskCreate:
+ ctx.emitInstant(ev, "task start", "user event")
+ case trace.EvUserTaskEnd:
+ ctx.emitInstant(ev, "task end", "user event")
}
// Emit any counter updates.
ctx.emitThreadCounters(ev)
taskName := fmt.Sprintf("Task %s(%d)", task.name, task.id)
ctx.emit(&ViewerEvent{Name: "thread_name", Phase: "M", Pid: 0, Tid: taskRow, Arg: &NameArg{"Tasks"}})
ctx.emit(&ViewerEvent{Name: "thread_sort_index", Phase: "M", Pid: 0, Tid: taskRow, Arg: &SortIndexArg{-3}})
- ctx.emit(&ViewerEvent{Category: "task", Name: taskName, Phase: "b", Time: float64(task.firstTimestamp()) / 1e3, Tid: taskRow, ID: task.id, Cname: "bad"})
- ctx.emit(&ViewerEvent{Category: "task", Name: taskName, Phase: "e", Time: float64(task.lastTimestamp()) / 1e3, Tid: taskRow, ID: task.id, Cname: "bad"})
+ tBegin := &ViewerEvent{Category: "task", Name: taskName, Phase: "b", Time: float64(task.firstTimestamp()) / 1e3, Tid: taskRow, ID: task.id, Cname: "bad"}
+ if task.create != nil {
+ tBegin.Stack = ctx.stack(task.create.Stk)
+ }
+ ctx.emit(tBegin)
+
+ tEnd := &ViewerEvent{Category: "task", Name: taskName, Phase: "e", Time: float64(task.lastTimestamp()) / 1e3, Tid: taskRow, ID: task.id, Cname: "bad"}
+ if task.end != nil {
+ tEnd.Stack = ctx.stack(task.end.Stk)
+ }
+ ctx.emit(tEnd)
+
// Spans
for _, s := range task.spans {
ctx.emitSpan(s)
ctx.prevThreadStats = ctx.threadStats
}
-func (ctx *traceContext) emitInstant(ev *trace.Event, name string) {
+func (ctx *traceContext) emitInstant(ev *trace.Event, name, category string) {
var arg interface{}
if ev.Type == trace.EvProcStart {
type Arg struct {
}
arg = &Arg{ev.Args[0]}
}
- ctx.emit(&ViewerEvent{Name: name, Phase: "I", Scope: "t", Time: ctx.time(ev), Tid: ctx.proc(ev), Stack: ctx.stack(ev.Stk), Arg: arg})
+ ctx.emit(&ViewerEvent{
+ Name: name,
+ Category: category,
+ Phase: "I",
+ Scope: "t",
+ Time: ctx.time(ev),
+ Tid: ctx.proc(ev),
+ Stack: ctx.stack(ev.Stk),
+ Arg: arg})
}
func (ctx *traceContext) emitArrow(ev *trace.Event, name string) {
if ev.P == trace.NetpollP || ev.P == trace.TimerP || ev.P == trace.SyscallP {
// Trace-viewer discards arrows if they don't start/end inside of a slice or instant.
// So emit a fake instant at the start of the arrow.
- ctx.emitInstant(&trace.Event{P: ev.P, Ts: ev.Ts}, "unblock")
+ ctx.emitInstant(&trace.Event{P: ev.P, Ts: ev.Ts}, "unblock", "")
}
ctx.arrowSeq++