Source file src/runtime/trace/trace.go
1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package trace contains facilities for programs to generate traces 6 // for the Go execution tracer. 7 // 8 // # Tracing runtime activities 9 // 10 // The execution trace captures a wide range of execution events such as 11 // goroutine creation/blocking/unblocking, syscall enter/exit/block, 12 // GC-related events, changes of heap size, processor start/stop, etc. 13 // When CPU profiling is active, the execution tracer makes an effort to 14 // include those samples as well. 15 // A precise nanosecond-precision timestamp and a stack trace is 16 // captured for most events. The generated trace can be interpreted 17 // using `go tool trace`. 18 // 19 // Support for tracing tests and benchmarks built with the standard 20 // testing package is built into `go test`. For example, the following 21 // command runs the test in the current directory and writes the trace 22 // file (trace.out). 23 // 24 // go test -trace=trace.out 25 // 26 // This runtime/trace package provides APIs to add equivalent tracing 27 // support to a standalone program. See the Example that demonstrates 28 // how to use this API to enable tracing. 29 // 30 // There is also a standard HTTP interface to trace data. Adding the 31 // following line will install a handler under the /debug/pprof/trace URL 32 // to download a live trace: 33 // 34 // import _ "net/http/pprof" 35 // 36 // See the [net/http/pprof] package for more details about all of the 37 // debug endpoints installed by this import. 38 // 39 // # User annotation 40 // 41 // Package trace provides user annotation APIs that can be used to 42 // log interesting events during execution. 43 // 44 // There are three types of user annotations: log messages, regions, 45 // and tasks. 46 // 47 // [Log] emits a timestamped message to the execution trace along with 48 // additional information such as the category of the message and 49 // which goroutine called [Log]. The execution tracer provides UIs to filter 50 // and group goroutines using the log category and the message supplied 51 // in [Log]. 52 // 53 // A region is for logging a time interval during a goroutine's execution. 54 // By definition, a region starts and ends in the same goroutine. 55 // Regions can be nested to represent subintervals. 56 // For example, the following code records four regions in the execution 57 // trace to trace the durations of sequential steps in a cappuccino making 58 // operation. 59 // 60 // trace.WithRegion(ctx, "makeCappuccino", func() { 61 // 62 // // orderID allows to identify a specific order 63 // // among many cappuccino order region records. 64 // trace.Log(ctx, "orderID", orderID) 65 // 66 // trace.WithRegion(ctx, "steamMilk", steamMilk) 67 // trace.WithRegion(ctx, "extractCoffee", extractCoffee) 68 // trace.WithRegion(ctx, "mixMilkCoffee", mixMilkCoffee) 69 // }) 70 // 71 // A task is a higher-level component that aids tracing of logical 72 // operations such as an RPC request, an HTTP request, or an 73 // interesting local operation which may require multiple goroutines 74 // working together. Since tasks can involve multiple goroutines, 75 // they are tracked via a [context.Context] object. [NewTask] creates 76 // a new task and embeds it in the returned [context.Context] object. 77 // Log messages and regions are attached to the task, if any, in the 78 // Context passed to [Log] and [WithRegion]. 79 // 80 // For example, assume that we decided to froth milk, extract coffee, 81 // and mix milk and coffee in separate goroutines. With a task, 82 // the trace tool can identify the goroutines involved in a specific 83 // cappuccino order. 84 // 85 // ctx, task := trace.NewTask(ctx, "makeCappuccino") 86 // trace.Log(ctx, "orderID", orderID) 87 // 88 // milk := make(chan bool) 89 // espresso := make(chan bool) 90 // 91 // go func() { 92 // trace.WithRegion(ctx, "steamMilk", steamMilk) 93 // milk <- true 94 // }() 95 // go func() { 96 // trace.WithRegion(ctx, "extractCoffee", extractCoffee) 97 // espresso <- true 98 // }() 99 // go func() { 100 // defer task.End() // When assemble is done, the order is complete. 101 // <-espresso 102 // <-milk 103 // trace.WithRegion(ctx, "mixMilkCoffee", mixMilkCoffee) 104 // }() 105 // 106 // The trace tool computes the latency of a task by measuring the 107 // time between the task creation and the task end and provides 108 // latency distributions for each task type found in the trace. 109 package trace 110 111 import ( 112 "io" 113 "runtime" 114 "sync" 115 "sync/atomic" 116 ) 117 118 // Start enables tracing for the current program. 119 // While tracing, the trace will be buffered and written to w. 120 // Start returns an error if tracing is already enabled. 121 func Start(w io.Writer) error { 122 tracing.Lock() 123 defer tracing.Unlock() 124 125 if err := runtime.StartTrace(); err != nil { 126 return err 127 } 128 go func() { 129 for { 130 data := runtime.ReadTrace() 131 if data == nil { 132 break 133 } 134 w.Write(data) 135 } 136 }() 137 tracing.enabled.Store(true) 138 return nil 139 } 140 141 // Stop stops the current tracing, if any. 142 // Stop only returns after all the writes for the trace have completed. 143 func Stop() { 144 tracing.Lock() 145 defer tracing.Unlock() 146 tracing.enabled.Store(false) 147 148 runtime.StopTrace() 149 } 150 151 var tracing struct { 152 sync.Mutex // gate mutators (Start, Stop) 153 enabled atomic.Bool 154 } 155