Skip to content
This repository has been archived by the owner on Jul 31, 2023. It is now read-only.

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 #694.
  • Loading branch information
rakyll committed Apr 16, 2018
1 parent 5bb1e81 commit a8312a3
Show file tree
Hide file tree
Showing 12 changed files with 126 additions and 103 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
19 changes: 9 additions & 10 deletions plugin/ochttp/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,20 +76,20 @@ 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,
trace.WithSampler(h.StartOptions.Sampler),
trace.WithSpanKind(trace.SpanKindServer),
)
if ok {
span.AddLink(trace.Link{
TraceID: sc.TraceID,
Expand All @@ -99,9 +99,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
14 changes: 6 additions & 8 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 Expand Up @@ -278,7 +276,7 @@ func TestEndToEnd(t *testing.T) {
t.Errorf("Span name: %q; want %q", got, want)
}
default:
t.Fatalf("server or client span missing")
t.Fatalf("server or client span missing; kind = %v", sp.SpanKind)
}
}

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, true, 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, parent != nil, 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 a8312a3

Please sign in to comment.