Skip to content

Commit

Permalink
make carrier as interface instead of http.Request.
Browse files Browse the repository at this point in the history
  • Loading branch information
rghetia committed Aug 26, 2019
1 parent 107023d commit a579ac4
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 21 deletions.
6 changes: 2 additions & 4 deletions api/propagation/propagator.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
package propagation // import "go.opentelemetry.io/api/propagation"

import (
"net/http"

"go.opentelemetry.io/api/core"
"go.opentelemetry.io/api/tag"
)
Expand All @@ -31,8 +29,8 @@ import (
// Typically, a plugin for transport like HTTP uses this interface to allow user
// to configure appropriate propagators.
type TextFormatPropagator interface {
Extractor(req *http.Request) Extractor
Injector(req *http.Request) Injector
Extractor(carrier interface{}) Extractor
Injector(carrier interface{}) Injector
}

type Injector interface {
Expand Down
56 changes: 41 additions & 15 deletions propagation/http_textformat_propagator.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,26 +35,46 @@ const (
traceparentHeader = "traceparent"
)

type textFormatPropagator struct{}
type httpTraceContextPropagator struct{}

var _ apipropagation.TextFormatPropagator = textFormatPropagator{}
var _ apipropagation.TextFormatPropagator = httpTraceContextPropagator{}

func (t textFormatPropagator) Extractor(req *http.Request) apipropagation.Extractor {
return textFormatExtractor{req: req}
// Extractor implements Extractor method of TextFormatPropagator interface.
//
// It creates Extractor object and binds carrier to the object. The carrier
// is expected to be *http.Request. If the carrier type is not *http.Request
// then an empty extractor is returned which will extract nothing.
func (t httpTraceContextPropagator) Extractor(carrier interface{}) apipropagation.Extractor {
req, ok := carrier.(*http.Request)
if ok {
return textFormatExtractor{req: req}
}
return textFormatExtractor{}
}

func (t textFormatPropagator) Injector(req *http.Request) apipropagation.Injector {
return textFormatInjector{req: req}
// Injector implements Injector method of TextFormatPropagator interface.
//
// It creates Injector object and binds carrier to the object. The carrier
// is expected to be of type *http.Request. If the carrier type is not *http.Request
// then an empty injector is returned which will inject nothing.
func (t httpTraceContextPropagator) Injector(carrier interface{}) apipropagation.Injector {
req, ok := carrier.(*http.Request)
if ok {
return textFormatInjector{req: req}
}
return textFormatInjector{}
}

// TextFormatPropagator creates a new propagator. The propagator is then used
// to create Injector and Extrator associated with a specific request. Injectors
// and Extractors respectively provides method to inject and extract SpanContext
// into/from the http request. Inject method encodes SpanContext into W3C
// TraceContext Header and injects the header in the request. Extract extracts
// the header and decodes SpanContext.
func TextFormatPropagator() textFormatPropagator {
return textFormatPropagator{}
// HttpTraceContextPropagator creates a new propagator that propagates SpanContext
// in W3C TraceContext format.
//
// The propagator is then used to create Injector and Extractor associated with a
// specific request. Injectors and Extractors respectively provides method to
// inject and extract SpanContext into/from the http request. Inject method encodes
// SpanContext into W3C TraceContext Header and injects the header in the request.
// Extract extracts the header and decodes SpanContext.
func HttpTraceContextPropagator() httpTraceContextPropagator {
return httpTraceContextPropagator{}
}

type textFormatExtractor struct {
Expand All @@ -66,6 +86,9 @@ var _ apipropagation.Extractor = textFormatExtractor{}
// Extract implements Extract method of trace.Extractor interface. It extracts
// W3C TraceContext Header and decodes SpanContext from the Header.
func (tfe textFormatExtractor) Extract() (sc core.SpanContext, tm tag.Map) {
if tfe.req == nil {
return core.EmptySpanContext(), tag.NewEmptyMap()
}
h, ok := getRequestHeader(tfe.req, traceparentHeader, false)
if !ok {
return core.EmptySpanContext(), tag.NewEmptyMap()
Expand Down Expand Up @@ -136,10 +159,13 @@ type textFormatInjector struct {

var _ apipropagation.Injector = textFormatInjector{}

// Inject implements Inject method of trace.Injector interface. It encodes
// Inject implements Inject method of propagation.Injector interface. It encodes
// SpanContext into W3C TraceContext Header and injects the header into
// the associated request.
func (tfi textFormatInjector) Inject(sc core.SpanContext, tm tag.Map) {
if tfi.req == nil {
return
}
if sc.IsValid() {
h := fmt.Sprintf("%.2x-%.16x%.16x-%.16x-%.2x",
supportedVersion,
Expand Down
52 changes: 50 additions & 2 deletions propagation/http_textformat_propagator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ var (
)

func TestExtractTraceContextFromHTTPReq(t *testing.T) {
propagator := propagation.TextFormatPropagator()
propagator := propagation.HttpTraceContextPropagator()
tests := []struct {
name string
header string
Expand Down Expand Up @@ -86,8 +86,33 @@ func TestExtractTraceContextFromHTTPReq(t *testing.T) {
}
}

func TestExtractTraceContextFromInvalidCarrier(t *testing.T) {
propagator := propagation.HttpTraceContextPropagator()
tests := []struct {
name string
header string
wantSc core.SpanContext
}{
{
name: "valid header on invalid carrier",
header: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
wantSc: core.EmptySpanContext(),
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
e := propagator.Extractor(tt.header)
gotSc, _ := e.Extract()
if diff := cmp.Diff(gotSc, tt.wantSc); diff != "" {
t.Errorf("Extract Tracecontext: %s: -got +want %s", tt.name, diff)
}
})
}
}

func TestInjectTraceContextToHTTPReq(t *testing.T) {
propagator := propagation.TextFormatPropagator()
propagator := propagation.HttpTraceContextPropagator()
tests := []struct {
name string
sc core.SpanContext
Expand Down Expand Up @@ -129,3 +154,26 @@ func TestInjectTraceContextToHTTPReq(t *testing.T) {
})
}
}

func TestInjectTraceContextToInvalidCarrier(t *testing.T) {
propagator := propagation.HttpTraceContextPropagator()
tests := []struct {
name string
sc core.SpanContext
}{
{
name: "valid spancontext to invalid carrier",
sc: core.SpanContext{
TraceID: traceID,
SpanID: spanID,
TraceOptions: core.TraceOptionSampled,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
i := propagator.Injector("")
i.Inject(tt.sc, tag.NewEmptyMap())
})
}
}

0 comments on commit a579ac4

Please sign in to comment.