Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTPReporter: Adds b3:0 header and unit test for custom headers using HTTPDoer #176

Merged
merged 2 commits into from
Sep 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions reporter/http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ type httpReporter struct {
reqCallback RequestCallbackFn
reqTimeout time.Duration
serializer reporter.SpanSerializer
doNotSample bool
}

// Send implements reporter
Expand Down Expand Up @@ -152,6 +153,9 @@ func (r *httpReporter) sendBatch() error {
r.logger.Printf("failed when creating the request: %s\n", err.Error())
return err
}
if r.doNotSample {
req.Header.Set("b3", "0")
}
req.Header.Set("Content-Type", r.serializer.ContentType())
if r.reqCallback != nil {
r.reqCallback(req)
Expand Down Expand Up @@ -237,6 +241,17 @@ func Serializer(serializer reporter.SpanSerializer) ReporterOption {
}
}

// AllowSamplingReporterCalls if set to true will remove the b3:0 header on
// outgoing calls to the Zipkin collector.
// By default we send b3:0 header to mitigate trace reporting amplification in
// service mesh environments where the sidecar proxies might trace the call
// we do here towards the Zipkin collector.
func AllowSamplingReporterCalls(allow bool) ReporterOption {
return func(r *httpReporter) {
r.doNotSample = !allow
}
}

// NewReporter returns a new HTTP Reporter.
// url should be the endpoint to send the spans to, e.g.
// http://localhost:9411/api/v2/spans
Expand All @@ -256,6 +271,7 @@ func NewReporter(url string, opts ...ReporterOption) reporter.Reporter {
batchMtx: &sync.Mutex{},
serializer: reporter.JSONSerializer{},
reqTimeout: defaultTimeout,
doNotSample: true,
}

for _, opt := range opts {
Expand Down
89 changes: 89 additions & 0 deletions reporter/http/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"io/ioutil"
"net/http"
"net/http/httptest"
"reflect"
"sync/atomic"
"testing"
"time"
Expand Down Expand Up @@ -167,3 +168,91 @@ func TestSpanIsReportedAfterBatchSize(t *testing.T) {
t.Errorf("unexpected number of spans received\nhave: %d, want: %d", aNumSpans, eNumSpans)
}
}

func TestSpanCustomHeaders(t *testing.T) {
serializer := reporter.JSONSerializer{}

hc := headerClient{
headers: http.Header{
"Key1": []string{"val1a", "val1b"},
"Key2": []string{"val2"},
},
}
var haveHeaders http.Header
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
haveHeaders = r.Header
}))
defer ts.Close()

spans := generateSpans(1)

rep := zipkinhttp.NewReporter(
ts.URL,
zipkinhttp.Serializer(serializer),
zipkinhttp.Client(hc),
)
for _, span := range spans {
rep.Send(*span)
}
rep.Close()

for _, key := range []string{"Key1", "Key2"} {
if want, have := hc.headers[key], haveHeaders[key]; !reflect.DeepEqual(want, have) {
t.Errorf("header %s: want: %v, have: %v\n", key, want, have)
}
}
}

func TestB3SamplingHeader(t *testing.T) {
serializer := reporter.JSONSerializer{}

var haveHeaders map[string][]string
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
haveHeaders = r.Header
}))
defer ts.Close()

spans := generateSpans(1)

rep := zipkinhttp.NewReporter(
ts.URL,
zipkinhttp.Serializer(serializer),
zipkinhttp.AllowSamplingReporterCalls(true),
)
for _, span := range spans {
rep.Send(*span)
}
rep.Close()

if len(haveHeaders["B3"]) > 0 {
codefromthecrypt marked this conversation as resolved.
Show resolved Hide resolved
t.Errorf("Expected B3 header to not exist, got %v", haveHeaders["B3"])
}

rep = zipkinhttp.NewReporter(
ts.URL,
zipkinhttp.Serializer(serializer),
)
for _, span := range spans {
rep.Send(*span)
}
rep.Close()

if want, have := []string{"0"}, haveHeaders["B3"]; !reflect.DeepEqual(want, have) {
t.Errorf("B3 header: want: %v, have %v", want, have)
}

}

type headerClient struct {
client http.Client
headers map[string][]string
}

func (h headerClient) Do(req *http.Request) (*http.Response, error) {
for key, item := range h.headers {
for _, val := range item {
req.Header.Add(key, val)
}
}
return h.client.Do(req)
}