aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/trace/trace.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/trace/trace.go')
-rw-r--r--src/runtime/trace/trace.go99
1 files changed, 93 insertions, 6 deletions
diff --git a/src/runtime/trace/trace.go b/src/runtime/trace/trace.go
index 439f998c03..6cc9f8c7b9 100644
--- a/src/runtime/trace/trace.go
+++ b/src/runtime/trace/trace.go
@@ -5,6 +5,8 @@
// Package trace contains facilities for programs to generate trace
// for Go execution tracer.
//
+// Tracing runtime activities
+//
// The execution trace captures a wide range of execution events such as
// goroutine creation/blocking/unblocking, syscall enter/exit/block,
// GC-related events, changes of heap size, processor start/stop, etc.
@@ -12,8 +14,6 @@
// captured for most events. The generated trace can be interpreted
// using `go tool trace`.
//
-// Tracing a Go program
-//
// Support for tracing tests and benchmarks built with the standard
// testing package is built into `go test`. For example, the following
// command runs the test in the current directory and writes the trace
@@ -25,24 +25,101 @@
// support to a standalone program. See the Example that demonstrates
// how to use this API to enable tracing.
//
-// There is also a standard HTTP interface to profiling data. Adding the
-// following line will install handlers under the /debug/pprof/trace URL
-// to download live profiles:
+// There is also a standard HTTP interface to trace data. Adding the
+// following line will install a handler under the /debug/pprof/trace URL
+// to download a live trace:
//
// import _ "net/http/pprof"
//
-// See the net/http/pprof package for more details.
+// See the net/http/pprof package for more details about all of the
+// debug endpoints installed by this import.
+//
+// User annotation
+//
+// Package trace provides user annotation APIs that can be used to
+// log interesting events during execution.
+//
+// There are three types of user annotations: log messages, spans,
+// and tasks.
+//
+// Log emits a timestamped message to the execution trace along with
+// additional information such as the category of the message and
+// which goroutine called Log. The execution tracer provides UIs to filter
+// and group goroutines using the log category and the message supplied
+// in Log.
+//
+// A span is for logging a time interval during a goroutine's execution.
+// By definition, a span starts and ends in the same goroutine.
+// Spans can be nested to represent subintervals.
+// For example, the following code records four spans in the execution
+// trace to trace the durations of sequential steps in a cappuccino making
+// operation.
+//
+// trace.WithSpan(ctx, "makeCappuccino", func(ctx context.Context) {
+//
+// // orderID allows to identify a specific order
+// // among many cappuccino order span records.
+// trace.Log(ctx, "orderID", orderID)
+//
+// trace.WithSpan(ctx, "steamMilk", steamMilk)
+// trace.WithSpan(ctx, "extractCoffee", extractCoffee)
+// trace.WithSpan(ctx, "mixMilkCoffee", mixMilkCoffee)
+// })
+//
+// A task is a higher-level component that aids tracing of logical
+// operations such as an RPC request, an HTTP request, or an
+// interesting local operation which may require multiple goroutines
+// working together. Since tasks can involve multiple goroutines,
+// they are tracked via a context.Context object. NewContext creates
+// a new task and embeds it in the the returned context.Context object.
+// Log messages and spans are attached to the task, if any, in the
+// Context passed to Log and WithSpan.
+//
+// For example, assume that we decided to froth milk, extract coffee,
+// and mix milk and coffee in separate goroutines. With a task,
+// the trace tool can identify the goroutines involved in a specific
+// cappuccino order.
+//
+// ctx, taskEnd:= trace.NewContext(ctx, "makeCappuccino")
+// trace.Log(ctx, "orderID", orderID)
+//
+// milk := make(chan bool)
+// espresso := make(chan bool)
+//
+// go func() {
+// trace.WithSpan(ctx, "steamMilk", steamMilk)
+// milk<-true
+// })()
+// go func() {
+// trace.WithSpan(ctx, "extractCoffee", extractCoffee)
+// espresso<-true
+// })()
+// go func() {
+// defer taskEnd() // When assemble is done, the order is complete.
+// <-espresso
+// <-milk
+// trace.WithSpan(ctx, "mixMilkCoffee", mixMilkCoffee)
+// })()
+//
+// The trace tool computes the latency of a task by measuring the
+// time between the task creation and the task end and provides
+// latency distributions for each task type found in the trace.
package trace
import (
"io"
"runtime"
+ "sync"
+ "sync/atomic"
)
// Start enables tracing for the current program.
// While tracing, the trace will be buffered and written to w.
// Start returns an error if tracing is already enabled.
func Start(w io.Writer) error {
+ tracing.Lock()
+ defer tracing.Unlock()
+
if err := runtime.StartTrace(); err != nil {
return err
}
@@ -55,11 +132,21 @@ func Start(w io.Writer) error {
w.Write(data)
}
}()
+ atomic.StoreInt32(&tracing.enabled, 1)
return nil
}
// Stop stops the current tracing, if any.
// Stop only returns after all the writes for the trace have completed.
func Stop() {
+ tracing.Lock()
+ defer tracing.Unlock()
+ atomic.StoreInt32(&tracing.enabled, 0)
+
runtime.StopTrace()
}
+
+var tracing struct {
+ sync.Mutex // gate mutators (Start, Stop)
+ enabled int32 // accessed via atomic
+}