diff --git a/tracing/opencensus/endpoint.go b/tracing/opencensus/endpoint.go index 9cc2dcee5..70c4e87e6 100644 --- a/tracing/opencensus/endpoint.go +++ b/tracing/opencensus/endpoint.go @@ -31,14 +31,25 @@ func TraceEndpoint(name string, options ...EndpointOption) endpoint.Middleware { return func(next endpoint.Endpoint) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (response interface{}, err error) { - if name == TraceEndpointDefaultName && cfg.GetSpanName != nil { - name = cfg.GetSpanName(ctx) + var attributes []trace.Attribute + + if cfg.GetSpanDetails != nil { + var newName string + + newName, attributes = cfg.GetSpanDetails(ctx, name) + + if newName != "" { + name = newName + } } ctx, span := trace.StartSpan(ctx, name) if len(cfg.Attributes) > 0 { span.AddAttributes(cfg.Attributes...) } + if len(attributes) > 0 { + span.AddAttributes(attributes...) + } defer span.End() defer func() { diff --git a/tracing/opencensus/endpoint_options.go b/tracing/opencensus/endpoint_options.go index e94a5b566..a91dfb561 100644 --- a/tracing/opencensus/endpoint_options.go +++ b/tracing/opencensus/endpoint_options.go @@ -16,10 +16,12 @@ type EndpointOptions struct { // creation by our Endpoint middleware. Attributes []trace.Attribute - // GetSpanName holds the function to use for generating the span name - // from the information found in the incoming Request. - // Defaults to the name that the middleware was initialized with. - GetSpanName func(ctx context.Context) string + // GetSpanDetails holds the function to use for generating the span name + // based on the current name and from the information found in the incoming Request. + // It can also return additional attributes for the span. + // + // A returned empty name defaults to the name that the middleware was initialized with. + GetSpanDetails func(ctx context.Context, name string) (string, []trace.Attribute) } // EndpointOption allows for functional options to our OpenCensus endpoint @@ -49,3 +51,10 @@ func WithIgnoreBusinessError(val bool) EndpointOption { o.IgnoreBusinessError = val } } + +// WithSpanDetails extracts details from the request context (like span name and additional attributes). +func WithSpanDetails(fn func(ctx context.Context, name string) (string, []trace.Attribute)) EndpointOption { + return func(o *EndpointOptions) { + o.GetSpanDetails = fn + } +} diff --git a/tracing/opencensus/endpoint_test.go b/tracing/opencensus/endpoint_test.go index b2a512f01..813d6eee6 100644 --- a/tracing/opencensus/endpoint_test.go +++ b/tracing/opencensus/endpoint_test.go @@ -82,10 +82,16 @@ func TestTraceEndpoint(t *testing.T) { mw(passEndpoint)(ctx, failedResponse{err: err4}) // span6 - opts = opencensus.EndpointOptions{GetSpanName: func(ctx context.Context) string { - return span6 - }} - mw = opencensus.TraceEndpoint("", opencensus.WithEndpointConfig(opts)) + span6Attrs := []trace.Attribute{ + trace.StringAttribute("string", "value"), + trace.Int64Attribute("int64", 42), + } + mw = opencensus.TraceEndpoint( + "", + opencensus.WithSpanDetails(func(ctx context.Context, name string) (string, []trace.Attribute) { + return span6, span6Attrs + }), + ) mw(endpoint.Nop)(ctx, nil) // check span count @@ -169,4 +175,8 @@ func TestTraceEndpoint(t *testing.T) { if want, have := span6, span.Name; want != have { t.Errorf("incorrect span name, wanted %q, got %q", want, have) } + + if want, have := 2, len(span.Attributes); want != have { + t.Fatalf("incorrect attribute count, wanted %d, got %d", want, have) + } }