// TestTeeTracerSpanRefs verifies that ChildOf/FollowsFrom relations are // reflected correctly in the underlying spans. func TestTeeTracerSpanRefs(t *testing.T) { r1 := basictracer.NewInMemoryRecorder() t1 := basictracer.NewWithOptions(basictracer.Options{ Recorder: r1, ShouldSample: func(traceID uint64) bool { return true }, // always sample }) r2 := basictracer.NewInMemoryRecorder() t2 := basictracer.NewWithOptions(basictracer.Options{ Recorder: r2, ShouldSample: func(traceID uint64) bool { return true }, // always sample }) tr := NewTeeTracer(t1, t2) root := tr.StartSpan("x") child := tr.StartSpan("x", opentracing.ChildOf(root.Context())) child.Finish() root.Finish() for _, spans := range [][]basictracer.RawSpan{r1.GetSpans(), r2.GetSpans()} { if e, a := 2, len(spans); a != e { t.Fatalf("expected %d, got %d", e, a) } if e, a := spans[0].Context.TraceID, spans[1].Context.TraceID; a != e { t.Errorf("expected %d, got %d", e, a) } if e, a := spans[1].Context.SpanID, spans[0].ParentSpanID; a != e { t.Errorf("expected %d, got %d", e, a) } } }
// ChildSpan opens a span as a child of the current span in the context (if // there is one). // // Returns the new context and the new span (if any). The span should be // closed via FinishSpan. func ChildSpan(ctx context.Context, opName string) (context.Context, opentracing.Span) { span := opentracing.SpanFromContext(ctx) if span == nil { return ctx, nil } newSpan := span.Tracer().StartSpan(opName, opentracing.ChildOf(span.Context())) return opentracing.ContextWithSpan(ctx, newSpan), newSpan }
// AnnotateCtxWithSpan annotates the given context with the information in // AmbientContext (see AnnotateCtx) and opens a span. // // If the given context has a span, the new span is a child of that span. // Otherwise, the Tracer in AmbientContext is used to create a new root span. // // The caller is responsible for closing the span (via Span.Finish). func (ac *AmbientContext) AnnotateCtxWithSpan( ctx context.Context, opName string, ) (context.Context, opentracing.Span) { if ac.tags != nil { ctx = copyTagChain(ctx, ac.tags) } var span opentracing.Span if parentSpan := opentracing.SpanFromContext(ctx); parentSpan != nil { tracer := parentSpan.Tracer() span = tracer.StartSpan(opName, opentracing.ChildOf(parentSpan.Context())) } else { if ac.Tracer == nil { panic("no tracer in AmbientContext for root span") } span = ac.Tracer.StartSpan(opName) } return opentracing.ContextWithSpan(ctx, span), span }
func (r rpcServerOption) Apply(o *opentracing.StartSpanOptions) { if r.clientContext != nil { opentracing.ChildOf(r.clientContext).Apply(o) } SpanKindRPCServer.Apply(o) }
// resetForNewSQLTxn (re)initializes the txnState for a new transaction. // It creates a new client.Txn and initializes it using the session defaults. // txnState.State will be set to Open. func (ts *txnState) resetForNewSQLTxn(e *Executor, s *Session) { if ts.sp != nil { panic(fmt.Sprintf("txnState.reset() called on ts with active span. How come "+ "finishSQLTxn() wasn't called previously? ts: %+v", ts)) } // Reset state vars to defaults. ts.retrying = false ts.retryIntent = false ts.autoRetry = false ts.commitSeen = false // Discard previously collected spans. We start collecting anew on // every fresh SQL txn. ts.CollectedSpans = nil // Create a context for this transaction. It will include a // root span that will contain everything executed as part of the // upcoming SQL txn, including (automatic or user-directed) retries. // The span is closed by finishSQLTxn(). // TODO(andrei): figure out how to close these spans on server shutdown? ctx := s.context var sp opentracing.Span if traceSQL { var err error sp, err = tracing.JoinOrNewSnowball("coordinator", nil, func(sp basictracer.RawSpan) { ts.CollectedSpans = append(ts.CollectedSpans, sp) }) if err != nil { log.Warningf(ctx, "unable to create snowball tracer: %s", err) return } } else if traceSQLFor7881 { var err error sp, _, err = tracing.NewTracerAndSpanFor7881(func(sp basictracer.RawSpan) { ts.CollectedSpans = append(ts.CollectedSpans, sp) }) if err != nil { log.Fatalf(ctx, "couldn't create a tracer for debugging #7881: %s", err) } } else { if parentSp := opentracing.SpanFromContext(ctx); parentSp != nil { // Create a child span for this SQL txn. tracer := parentSp.Tracer() sp = tracer.StartSpan("sql txn", opentracing.ChildOf(parentSp.Context())) } else { // Create a root span for this SQL txn. tracer := e.cfg.AmbientCtx.Tracer sp = tracer.StartSpan("sql txn") } } // Put the new span in the context. ts.sp = sp ctx = opentracing.ContextWithSpan(ctx, sp) ts.Ctx = ctx ts.mon.Start(ctx, &s.mon, mon.BoundAccount{}) ts.txn = client.NewTxn(ts.Ctx, *e.cfg.DB) ts.txn.Proto.Isolation = s.DefaultIsolationLevel ts.State = Open // Discard the old schemaChangers, if any. ts.schemaChangers = schemaChangerCollection{} }