// Like StartSpan, but begins a root span for a new trace if no trace is active // in the supplied context and tracing is enabled for the process. func Trace( parent context.Context, desc string) (ctx context.Context, report ReportFunc) { // If tracing is disabled, this is a no-op. if !*fEnabled { ctx = parent report = func(err error) {} return } // Is this context already being traced? If so, simply add a span. if parent.Value(traceStateKey) != nil { ctx, report = StartSpan(parent, desc) return } // Set up a new trace state. ts := new(traceState) baseReport := ts.CreateSpan(desc) // Log when finished. report = func(err error) { baseReport(err) ts.Log() } // Set up the context. ctx = context.WithValue(parent, traceStateKey, ts) return }
// Begin a span within the current trace. Return a new context that should be // used for operations that logically occur within the span, and a report // function that must be called with the outcome of the logical operation // represented by the span. // // If no trace is active, no span will be created but ctx and report will still // be valid. func StartSpan( parent context.Context, desc string) (ctx context.Context, report ReportFunc) { // Look for the trace state. val := parent.Value(traceStateKey) if val == nil { // Nothing to do. ctx = parent report = func(err error) {} return } ts := val.(*traceState) // Set up the report function. report = ts.CreateSpan(desc) // For now we don't do anything interesting with the context. In the future, // we may use it to record span hierarchy. ctx = parent return }