Example #1
0
// ForkCtxSpan checks if ctx has a Span open; if it does, it creates a new Span
// that follows from the original Span. This allows the resulting context to be
// used in an async task that might outlive the original operation.
//
// Returns the new context and the new span (if any). The span should be
// closed via FinishSpan.
func ForkCtxSpan(ctx context.Context, opName string) (context.Context, opentracing.Span) {
	if span := opentracing.SpanFromContext(ctx); span != nil {
		if span.BaggageItem(Snowball) == "1" {
			// If we are doing snowball tracing, the span might outlive the snowball
			// tracer (calling the record function when it is no longer legal to do
			// so). Return a context with no span in this case.
			return opentracing.ContextWithSpan(ctx, nil), nil
		}
		tr := span.Tracer()
		newSpan := tr.StartSpan(opName, opentracing.FollowsFrom(span.Context()))
		return opentracing.ContextWithSpan(ctx, newSpan), newSpan
	}
	return ctx, nil
}
Example #2
0
// JoinOrNew creates a new Span joined to the provided DelegatingCarrier or
// creates Span from the given tracer.
func JoinOrNew(tr opentracing.Tracer, carrier *Span, opName string) (opentracing.Span, error) {
	if carrier != nil {
		wireContext, err := tr.Extract(basictracer.Delegator, carrier)
		switch err {
		case nil:
			sp := tr.StartSpan(opName, opentracing.FollowsFrom(wireContext))
			sp.LogEvent(opName)
			return sp, nil
		case opentracing.ErrSpanContextNotFound:
		default:
			return nil, err
		}
	}
	return tr.StartSpan(opName), nil
}
Example #3
0
// JoinOrNew creates a new Span joined to the provided DelegatingCarrier or
// creates Span from the given tracer.
func JoinOrNew(
	tr opentracing.Tracer, carrier *SpanContextCarrier, opName string,
) (opentracing.Span, error) {
	if carrier != nil {
		wireContext, err := tr.Extract(basictracer.Delegator, carrier)
		switch err {
		case nil:
			sp := tr.StartSpan(opName, opentracing.FollowsFrom(wireContext))

			// Copy baggage items to tags so they show up in the Lightstep UI.
			sp.Context().ForeachBaggageItem(func(k, v string) bool { sp.SetTag(k, v); return true })

			sp.LogFields(otlog.String("event", opName))
			return sp, nil
		case opentracing.ErrSpanContextNotFound:
		default:
			return nil, err
		}
	}
	return tr.StartSpan(opName), nil
}
Example #4
0
func TestTeeTracer(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)

	span := tr.StartSpan("x")
	span.LogKV("k1", "v1", "k2", "v2")
	span.SetTag("tag", "value")
	span.SetBaggageItem("baggage", "baggage-value")
	if e, a := "baggage-value", span.BaggageItem("baggage"); a != e {
		t.Errorf("expected %s, got %s", e, a)
	}

	spanCtx := span.Context()
	var ctxBuffer bytes.Buffer
	if err := tr.Inject(spanCtx, opentracing.Binary, &ctxBuffer); err != nil {
		t.Fatal(err)
	}

	decodedCtx, err := tr.Extract(opentracing.Binary, &ctxBuffer)
	if err != nil {
		t.Fatal(err)
	}
	span2 := tr.StartSpan("y", opentracing.FollowsFrom(decodedCtx))
	span2.LogEvent("event2")
	if e, a := "baggage-value", span2.BaggageItem("baggage"); a != e {
		t.Errorf("expected %s, got %s", e, a)
	}
	span.Finish()
	span2.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 := "x", spans[0].Operation; a != e {
			t.Errorf("expected %s, got %s", e, a)
		}
		if e, a := (opentracing.Tags{"tag": "value"}), spans[0].Tags; !reflect.DeepEqual(a, e) {
			t.Errorf("expected %s, got %s", e, a)
		}
		if e, a := "k1:v1", spans[0].Logs[0].Fields[0].String(); a != e {
			t.Errorf("expected %s, got %s", e, a)
		}
		if e, a := "k2:v2", spans[0].Logs[0].Fields[1].String(); a != e {
			t.Errorf("expected %s, got %s", e, a)
		}
		if e, a := 1, len(spans[0].Context.Baggage); a != e {
			t.Errorf("expected %d, got %d", e, a)
		}

		if e, a := "y", spans[1].Operation; a != e {
			t.Errorf("expected %s, got %s", e, a)
		}
		if e, a := opentracing.Tags(nil), spans[1].Tags; !reflect.DeepEqual(a, e) {
			t.Errorf("expected %s, got %s", e, a)
		}
		if e, a := "event:event2", spans[1].Logs[0].Fields[0].String(); a != e {
			t.Errorf("expected %s, got %s", e, a)
		}
		if e, a := 1, len(spans[1].Context.Baggage); a != e {
			t.Errorf("expected %d, got %d", e, a)
		}
	}
}