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. 109package trace 110 111import ( 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. 121func 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. 143func Stop() { 144 tracing.Lock() 145 defer tracing.Unlock() 146 tracing.enabled.Store(false) 147 148 runtime.StopTrace() 149} 150 151var tracing struct { 152 sync.Mutex // gate mutators (Start, Stop) 153 enabled atomic.Bool 154} 155