Skip to content

Commit

Permalink
Collect and send extra HTTP headers to the agent
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrey Slotin committed Aug 13, 2020
1 parent 9b06afa commit 7fa630e
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 8 deletions.
58 changes: 55 additions & 3 deletions instrumentation_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,34 @@ func TracingHandlerFunc(sensor *Sensor, pathTemplate string, handler http.Handle
span := tracer.StartSpan("g.http", opts...)
defer span.Finish()

var collectableHTTPHeaders []string
if t, ok := tracer.(Tracer); ok {
params := collectHTTPParams(req, t.Options().Secrets)
opts := t.Options()
collectableHTTPHeaders = opts.CollectableHTTPHeaders

params := collectHTTPParams(req, opts.Secrets)
if len(params) > 0 {
span.SetTag("http.params", params.Encode())
}
}

collectedHeaders := make(map[string]string)
// make sure collected headers are sent in case of panic/error
defer func() {
// Be sure to capture any kind of panic / error
if len(collectedHeaders) > 0 {
span.SetTag("http.header", collectedHeaders)
}
}()

// collect request headers
for _, h := range collectableHTTPHeaders {
if v := req.Header.Get(h); v != "" {
collectedHeaders[h] = v
}
}

defer func() {
// Be sure to capture any kind of panic/error
if err := recover(); err != nil {
if e, ok := err.(error); ok {
span.SetTag("http.error", e.Error())
Expand All @@ -94,6 +113,13 @@ func TracingHandlerFunc(sensor *Sensor, pathTemplate string, handler http.Handle
ctx = ContextWithSpan(ctx, span)
w3ctrace.TracingHandlerFunc(handler)(wrapped, req.WithContext(ctx))

// collect response headers
for _, h := range collectableHTTPHeaders {
if v := wrapped.Header().Get(h); v != "" {
collectedHeaders[h] = v
}
}

if wrapped.Status > 0 {
if wrapped.Status > http.StatusInternalServerError {
span.SetTag("http.error", http.StatusText(wrapped.Status))
Expand Down Expand Up @@ -136,20 +162,46 @@ func RoundTripper(sensor *Sensor, original http.RoundTripper) http.RoundTripper
req = cloneRequest(ContextWithSpan(ctx, span), req)
sensor.Tracer().Inject(span.Context(), ot.HTTPHeaders, ot.HTTPHeadersCarrier(req.Header))

var collectableHTTPHeaders []string
if t, ok := sensor.Tracer().(Tracer); ok {
params := collectHTTPParams(req, t.Options().Secrets)
opts := t.Options()
collectableHTTPHeaders = opts.CollectableHTTPHeaders

params := collectHTTPParams(req, opts.Secrets)
if len(params) > 0 {
span.SetTag("http.params", params.Encode())
}
}

collectedHeaders := make(map[string]string)
// make sure collected headers are sent in case of panic/error
defer func() {
if len(collectedHeaders) > 0 {
span.SetTag("http.header", collectedHeaders)
}
}()

// collect request headers
for _, h := range collectableHTTPHeaders {
if v := req.Header.Get(h); v != "" {
collectedHeaders[h] = v
}
}

resp, err := original.RoundTrip(req)
if err != nil {
span.SetTag("http.error", err.Error())
span.LogFields(otlog.Error(err))
return resp, err
}

// collect response headers
for _, h := range collectableHTTPHeaders {
if v := resp.Header.Get(h); v != "" {
collectedHeaders[h] = v
}
}

span.SetTag(string(ext.HTTPStatusCode), resp.StatusCode)

return resp, err
Expand Down
28 changes: 23 additions & 5 deletions instrumentation_http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@ func TestTracingHandlerFunc_Write(t *testing.T) {
}, recorder))

h := instana.TracingHandlerFunc(s, "/{action}", func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("X-Response", "true")
w.Header().Set("X-Custom-Header-2", "response")
fmt.Fprintln(w, "Ok")
})

req := httptest.NewRequest(http.MethodGet, "/test?q=term", nil)
req.Header.Set("Authorization", "Basic blah")
req.Header.Set("X-Custom-Header-1", "request")

rec := httptest.NewRecorder()
h.ServeHTTP(rec, req)
Expand All @@ -48,11 +52,15 @@ func TestTracingHandlerFunc_Write(t *testing.T) {
data := span.Data.(instana.HTTPSpanData)

assert.Equal(t, instana.HTTPSpanTags{
Host: "example.com",
Status: http.StatusOK,
Method: "GET",
Path: "/test",
Params: "q=term",
Host: "example.com",
Status: http.StatusOK,
Method: "GET",
Path: "/test",
Params: "q=term",
Headers: map[string]string{
"x-custom-header-1": "request",
"x-custom-header-2": "response",
},
PathTemplate: "/{action}",
}, data.Tags)

Expand Down Expand Up @@ -337,11 +345,17 @@ func TestRoundTripper(t *testing.T) {
return &http.Response{
Status: http.StatusText(http.StatusNotImplemented),
StatusCode: http.StatusNotImplemented,
Header: http.Header{
"X-Response": []string{"true"},
"X-Custom-Header-2": []string{"response"},
},
}, nil
}))

ctx := instana.ContextWithSpan(context.Background(), parentSpan)
req := httptest.NewRequest("GET", "http://user:[email protected]/hello?q=term&sensitive_key=s3cr3t&myPassword=qwerty&SECRET_VALUE=1", nil)
req.Header.Set("X-Custom-Header-1", "request")
req.Header.Set("Authorization", "Basic blah")

_, err := rt.RoundTrip(req.WithContext(ctx))
require.NoError(t, err)
Expand Down Expand Up @@ -369,6 +383,10 @@ func TestRoundTripper(t *testing.T) {
Status: http.StatusNotImplemented,
URL: "http://example.com/hello",
Params: "SECRET_VALUE=%3Credacted%3E&myPassword=%3Credacted%3E&q=term&sensitive_key=%3Credacted%3E",
Headers: map[string]string{
"x-custom-header-1": "request",
"x-custom-header-2": "response",
},
}, data.Tags)
}

Expand Down
3 changes: 3 additions & 0 deletions sensor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ const TestServiceName = "test_service"
func TestMain(m *testing.M) {
instana.InitSensor(&instana.Options{
Service: TestServiceName,
Tracer: instana.TracerOptions{
CollectableHTTPHeaders: []string{"x-custom-header-1", "x-custom-header-2"},
},
})

os.Exit(m.Run())
Expand Down

0 comments on commit 7fa630e

Please sign in to comment.