Skip to content

Commit

Permalink
Deprecate NewSpanXXX in the favor of StartSpan
Browse files Browse the repository at this point in the history
Required to support the Go execution tracer spans.

Fixes census-instrumentation#694.
  • Loading branch information
rakyll committed Apr 16, 2018
1 parent 5bb1e81 commit 808d94c
Show file tree
Hide file tree
Showing 12 changed files with 122 additions and 102 deletions.
3 changes: 1 addition & 2 deletions exporter/stackdriver/stackdriver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,13 @@ func TestExport(t *testing.T) {

trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})

span := trace.NewSpan("custom-span", nil, trace.StartOptions{})
_, span := trace.StartSpan(context.Background(), "custom-span")
time.Sleep(10 * time.Millisecond)
span.End()

// Test HTTP spans

handler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {

_, backgroundSpan := trace.StartSpan(context.Background(), "BackgroundWork")
spanContext := backgroundSpan.SpanContext()
time.Sleep(10 * time.Millisecond)
Expand Down
7 changes: 3 additions & 4 deletions exporter/stackdriver/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,12 +155,11 @@ func (e *statsExporter) Flush() {
}

func (e *statsExporter) uploadStats(vds []*view.Data) error {
span := trace.NewSpan(
ctx, span := trace.StartSpan(
context.Background(),
"go.opencensus.io/exporter/stackdriver.uploadStats",
nil,
trace.StartOptions{Sampler: trace.NeverSample()},
trace.WithSampler(trace.NeverSample()),
)
ctx := trace.WithSpan(context.Background(), span)
defer span.End()

for _, vd := range vds {
Expand Down
7 changes: 5 additions & 2 deletions exporter/stackdriver/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,14 @@ func (e *traceExporter) uploadSpans(spans []*trace.SpanData) {
req.Spans = append(req.Spans, protoFromSpanData(span, e.projectID))
}
// Create a never-sampled span to prevent traces associated with exporter.
span := trace.NewSpan("go.opencensus.io/exporter/stackdriver.uploadSpans", nil, trace.StartOptions{Sampler: trace.NeverSample()})
ctx, span := trace.StartSpan( // TODO: add timeouts
context.Background(),
"go.opencensus.io/exporter/stackdriver.uploadSpans",
trace.WithSampler(trace.NeverSample()),
)
defer span.End()
span.AddAttributes(trace.Int64Attribute("num_spans", int64(len(spans))))

ctx := trace.WithSpan(context.Background(), span) // TODO: add timeouts
err := e.client.BatchWriteSpans(ctx, &req)
if err != nil {
span.SetStatus(trace.Status{Code: 2, Message: err.Error()})
Expand Down
12 changes: 7 additions & 5 deletions exporter/stackdriver/trace_proto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,21 @@ func (t *testExporter) ExportSpan(s *trace.SpanData) {
}

func TestExportTrace(t *testing.T) {
ctx := context.Background()

var te testExporter
trace.RegisterExporter(&te)
defer trace.UnregisterExporter(&te)

span0 := trace.NewSpanWithRemoteParent(
ctx, span0 := trace.StartSpan(
ctx,
"span0",
trace.SpanContext{
trace.WithRemoteParent(trace.SpanContext{
TraceID: traceID,
SpanID: spanID,
TraceOptions: 1,
},
trace.StartOptions{})
ctx := trace.WithSpan(context.Background(), span0)
}),
)
{
ctx1, span1 := trace.StartSpan(ctx, "span1")
{
Expand Down
3 changes: 1 addition & 2 deletions exporter/stackdriver/trace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,8 @@ func TestBundling(t *testing.T) {
}
trace.RegisterExporter(exporter)

trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
for i := 0; i < 35; i++ {
_, span := trace.StartSpan(context.Background(), "span")
_, span := trace.StartSpan(context.Background(), "span", trace.WithSampler(trace.AlwaysSample()))
span.End()
}

Expand Down
5 changes: 1 addition & 4 deletions plugin/ocgrpc/grpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,7 @@ func TestClientHandler(t *testing.T) {
t.Fatal(err)
}

span := trace.NewSpan("/foo", nil, trace.StartOptions{
Sampler: trace.AlwaysSample(),
})
ctx = trace.WithSpan(ctx, span)
ctx, _ = trace.StartSpan(ctx, "/foo", trace.WithSampler(trace.AlwaysSample()))

var handler ClientHandler
ctx = handler.TagRPC(ctx, &stats.RPCTagInfo{
Expand Down
27 changes: 13 additions & 14 deletions plugin/ocgrpc/trace_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,9 @@ const traceContextKey = "grpc-trace-bin"
func (c *ClientHandler) traceTagRPC(ctx context.Context, rti *stats.RPCTagInfo) context.Context {
name := strings.TrimPrefix(rti.FullMethodName, "/")
name = strings.Replace(name, "/", ".", -1)
span := trace.NewSpan(name, trace.FromContext(ctx), trace.StartOptions{
Sampler: c.StartOptions.Sampler,
SpanKind: trace.SpanKindClient,
}) // span is ended by traceHandleRPC
ctx = trace.WithSpan(ctx, span)
ctx, span := trace.StartSpan(ctx, name,
trace.WithSampler(c.StartOptions.Sampler),
trace.WithSpanKind(trace.SpanKindClient)) // span is ended by traceHandleRPC
traceContextBinary := propagation.Binary(span.SpanContext())
return metadata.AppendToOutgoingContext(ctx, traceContextKey, string(traceContextBinary))
}
Expand All @@ -52,11 +50,6 @@ func (c *ClientHandler) traceTagRPC(ctx context.Context, rti *stats.RPCTagInfo)
//
// It returns ctx, with the new trace span added.
func (s *ServerHandler) traceTagRPC(ctx context.Context, rti *stats.RPCTagInfo) context.Context {
opts := trace.StartOptions{
Sampler: s.StartOptions.Sampler,
SpanKind: trace.SpanKindServer,
}

md, _ := metadata.FromIncomingContext(ctx)
name := strings.TrimPrefix(rti.FullMethodName, "/")
name = strings.Replace(name, "/", ".", -1)
Expand All @@ -72,15 +65,21 @@ func (s *ServerHandler) traceTagRPC(ctx context.Context, rti *stats.RPCTagInfo)
traceContextBinary := []byte(traceContext[0])
parent, haveParent = propagation.FromBinary(traceContextBinary)
if haveParent && !s.IsPublicEndpoint {
span := trace.NewSpanWithRemoteParent(name, parent, opts)
return trace.WithSpan(ctx, span)
ctx, _ := trace.StartSpan(ctx, name,
trace.WithRemoteParent(parent),
trace.WithSpanKind(trace.SpanKindServer),
trace.WithSampler(s.StartOptions.Sampler),
)
return ctx
}
}
span := trace.NewSpan(name, nil, opts)
ctx, span := trace.StartSpan(ctx, name,
trace.WithSpanKind(trace.SpanKindServer),
trace.WithSampler(s.StartOptions.Sampler))
if haveParent {
span.AddLink(trace.Link{TraceID: parent.TraceID, SpanID: parent.SpanID, Type: trace.LinkTypeChild})
}
return trace.WithSpan(ctx, span)
return ctx
}

func traceHandleRPC(ctx context.Context, rs stats.RPCStats) {
Expand Down
16 changes: 6 additions & 10 deletions plugin/ochttp/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,20 +76,17 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}

func (h *Handler) startTrace(w http.ResponseWriter, r *http.Request) (*http.Request, func()) {
opts := trace.StartOptions{
Sampler: h.StartOptions.Sampler,
SpanKind: trace.SpanKindServer,
}

name := spanNameFromURL(r.URL)
ctx := r.Context()
var span *trace.Span
sc, ok := h.extractSpanContext(r)
if ok && !h.IsPublicEndpoint {
span = trace.NewSpanWithRemoteParent(name, sc, opts)
ctx = trace.WithSpan(ctx, span)
ctx, span = trace.StartSpan(ctx, name,
trace.WithRemoteParent(sc),
trace.WithSampler(h.StartOptions.Sampler),
trace.WithSpanKind(trace.SpanKindServer))
} else {
span = trace.NewSpan(name, nil, opts)
ctx, span = trace.StartSpan(ctx, name)
if ok {
span.AddLink(trace.Link{
TraceID: sc.TraceID,
Expand All @@ -99,9 +96,8 @@ func (h *Handler) startTrace(w http.ResponseWriter, r *http.Request) (*http.Requ
})
}
}
ctx = trace.WithSpan(ctx, span)
span.AddAttributes(requestAttrs(r)...)
return r.WithContext(trace.WithSpan(r.Context(), span)), span.End
return r.WithContext(ctx), span.End
}

func (h *Handler) extractSpanContext(r *http.Request) (trace.SpanContext, bool) {
Expand Down
7 changes: 4 additions & 3 deletions plugin/ochttp/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,11 @@ func (t *traceTransport) RoundTrip(req *http.Request) (*http.Response, error) {
name := spanNameFromURL(req.URL)
// TODO(jbd): Discuss whether we want to prefix
// outgoing requests with Sent.
parent := trace.FromContext(req.Context())
span := trace.NewSpan(name, parent, t.startOptions)
req = req.WithContext(trace.WithSpan(req.Context(), span))
_, span := trace.StartSpan(req.Context(), name,
trace.WithSampler(t.startOptions.Sampler),
trace.WithSpanKind(trace.SpanKindClient))

req = req.WithContext(trace.WithSpan(req.Context(), span))
if t.format != nil {
t.format.SpanContextToRequest(span.SpanContext(), req)
}
Expand Down
12 changes: 5 additions & 7 deletions plugin/ochttp/trace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ func (t testPropagator) SpanContextToRequest(sc trace.SpanContext, req *http.Req
}

func TestTransport_RoundTrip(t *testing.T) {
parent := trace.NewSpan("parent", nil, trace.StartOptions{})
ctx := context.Background()
ctx, parent := trace.StartSpan(ctx, "parent")
tests := []struct {
name string
parent *trace.Span
Expand Down Expand Up @@ -221,12 +222,9 @@ func TestEndToEnd(t *testing.T) {
url := serveHTTP(tt.handler, serverDone, serverReturn)

// Start a root Span in the client.
root := trace.NewSpan(
"top-level",
nil,
trace.StartOptions{})
ctx := trace.WithSpan(context.Background(), root)

ctx, root := trace.StartSpan(
context.Background(),
"top-level")
// Make the request.
req, err := http.NewRequest(
http.MethodPost,
Expand Down
60 changes: 51 additions & 9 deletions trace/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,34 +123,76 @@ type StartOptions struct {
// SpanKind represents the kind of a span. If none is set,
// SpanKindUnspecified is used.
SpanKind int

remoteParent SpanContext
}

// StartOption apply changes to StartOptions.
type StartOption func(*StartOptions)

// WithSpanKind makes new spans to be created with the given kind.
func WithSpanKind(spanKind int) StartOption {
return func(o *StartOptions) {
o.SpanKind = spanKind
}
}

// WithSampler makes new spans to be be created with a custom sampler.
// Otherwise, the global sampler is used.
func WithSampler(sampler Sampler) StartOption {
return func(o *StartOptions) {
o.Sampler = sampler
}
}

// WithRemoteParent makes new spans to be the child of the given part.
func WithRemoteParent(parent SpanContext) StartOption {
return func(o *StartOptions) {
o.remoteParent = parent
}
}

// StartSpan starts a new child span of the current span in the context. If
// there is no span in the context, creates a new trace and span.
//
// This is provided as a convenience for WithSpan(ctx, NewSpan(...)). Use it
// if you require custom spans in addition to the default spans provided by
// ocgrpc, ochttp or similar framework integration.
func StartSpan(ctx context.Context, name string) (context.Context, *Span) {
parentSpan, _ := ctx.Value(contextKey{}).(*Span)
span := NewSpan(name, parentSpan, StartOptions{})
// If WithRemoteParent option is provided, started span will be a child
// of the given remote parent.
func StartSpan(ctx context.Context, name string, o ...StartOption) (context.Context, *Span) {
var opts StartOptions

var parent SpanContext
if p := FromContext(ctx); p != nil {
parent = p.spanContext
}
for _, op := range o {
op(&opts)
}

var span *Span
if (opts.remoteParent != SpanContext{}) {
span = startSpanInternal(name, opts.remoteParent != SpanContext{}, opts.remoteParent, true, opts)
} else {
span = startSpanInternal(name, parent != SpanContext{}, parent, false, opts)
}
return WithSpan(ctx, span), span
}

// NewSpan returns a new span.
//
// If parent is not nil, created span will be a child of the parent.
//
// Deprecated: Use StartSpan.
func NewSpan(name string, parent *Span, o StartOptions) *Span {
hasParent := false
var parentSpanContext SpanContext
if parent != nil {
hasParent = true
parentSpanContext = parent.SpanContext()
}
return startSpanInternal(name, hasParent, parentSpanContext, false, o)
return startSpanInternal(name, true, parentSpanContext, false, o)
}

// NewSpanWithRemoteParent returns a new span with the given parent SpanContext.
//
// Deprecated: Use StartSpan with WithRemoteParent.
func NewSpanWithRemoteParent(name string, parent SpanContext, o StartOptions) *Span {
return startSpanInternal(name, true, parent, true, o)
}
Expand Down
Loading

0 comments on commit 808d94c

Please sign in to comment.