Skip to content

Commit

Permalink
Add integration tests covering the instrumentHTTP function
Browse files Browse the repository at this point in the history
  • Loading branch information
oleiade committed Jan 24, 2023
1 parent 82a9dd8 commit d255c80
Showing 1 changed file with 177 additions and 31 deletions.
208 changes: 177 additions & 31 deletions cmd/tests/tracing_module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,37 +56,7 @@ func TestTracingModuleClient(t *testing.T) {
jsonResults, err := afero.ReadFile(ts.FS, "results.json")
require.NoError(t, err)

gotHTTPDataPoints := false

for _, jsonLine := range bytes.Split(jsonResults, []byte("\n")) {
if len(jsonLine) == 0 {
continue
}

var line sampleEnvelope
require.NoError(t, json.Unmarshal(jsonLine, &line))

if line.Type != "Point" {
continue
}

// Filter metric samples which are not related to http
if !strings.HasPrefix(line.Metric, "http_") {
continue
}

gotHTTPDataPoints = true

anyTraceID, hasTraceID := line.Data.Metadata["trace_id"]
require.True(t, hasTraceID)

traceID, gotTraceID := anyTraceID.(string)
require.True(t, gotTraceID)

assert.Len(t, traceID, 32)
}

assert.True(t, gotHTTPDataPoints)
assertHasTraceIDMetadata(t, jsonResults)
}

func TestTracingClient_DoesNotInterfereWithHTTPModule(t *testing.T) {
Expand Down Expand Up @@ -128,6 +98,182 @@ func TestTracingClient_DoesNotInterfereWithHTTPModule(t *testing.T) {
assert.Equal(t, int64(2), atomic.LoadInt64(&gotInstrumentedRequests))
}

func TestTracingInstrumentHTTP_W3C(t *testing.T) {
t.Parallel()
tb := httpmultibin.NewHTTPMultiBin(t)

var gotRequests int64

tb.Mux.HandleFunc("/tracing", func(w http.ResponseWriter, r *http.Request) {
atomic.AddInt64(&gotRequests, 1)
assert.NotEmpty(t, r.Header.Get("traceparent"))
assert.Len(t, r.Header.Get("traceparent"), 55)
})

script := tb.Replacer.Replace(`
import http from "k6/http";
import { check } from "k6";
import tracing from "k6/experimental/tracing";
tracing.instrumentHTTP({
propagator: "w3c",
})
export default function () {
http.del("HTTPBIN_IP_URL/tracing");
http.get("HTTPBIN_IP_URL/tracing");
http.head("HTTPBIN_IP_URL/tracing");
http.options("HTTPBIN_IP_URL/tracing");
http.patch("HTTPBIN_IP_URL/tracing");
http.post("HTTPBIN_IP_URL/tracing");
http.put("HTTPBIN_IP_URL/tracing");
http.request("GET", "HTTPBIN_IP_URL/tracing");
};
`)

ts := getSingleFileTestState(t, script, []string{"--out", "json=results.json"}, 0)
cmd.ExecuteWithGlobalState(ts.GlobalState)

assert.Equal(t, int64(8), atomic.LoadInt64(&gotRequests))

jsonResults, err := afero.ReadFile(ts.FS, "results.json")
require.NoError(t, err)

assertHasTraceIDMetadata(t, jsonResults)
}

func TestTracingInstrumentHTTP_Jaeger(t *testing.T) {
t.Parallel()
tb := httpmultibin.NewHTTPMultiBin(t)

var gotRequests int64

tb.Mux.HandleFunc("/tracing", func(w http.ResponseWriter, r *http.Request) {
atomic.AddInt64(&gotRequests, 1)
assert.NotEmpty(t, r.Header.Get("uber-trace-id"))
assert.Len(t, r.Header.Get("uber-trace-id"), 45)
})

script := tb.Replacer.Replace(`
import http from "k6/http";
import { check } from "k6";
import tracing from "k6/experimental/tracing";
tracing.instrumentHTTP({
propagator: "jaeger",
})
export default function () {
http.del("HTTPBIN_IP_URL/tracing");
http.get("HTTPBIN_IP_URL/tracing");
http.head("HTTPBIN_IP_URL/tracing");
http.options("HTTPBIN_IP_URL/tracing");
http.patch("HTTPBIN_IP_URL/tracing");
http.post("HTTPBIN_IP_URL/tracing");
http.put("HTTPBIN_IP_URL/tracing");
http.request("GET", "HTTPBIN_IP_URL/tracing");
};
`)

ts := getSingleFileTestState(t, script, []string{"--out", "json=results.json"}, 0)
cmd.ExecuteWithGlobalState(ts.GlobalState)

assert.Equal(t, int64(8), atomic.LoadInt64(&gotRequests))

jsonResults, err := afero.ReadFile(ts.FS, "results.json")
require.NoError(t, err)

assertHasTraceIDMetadata(t, jsonResults)
}

func TestTracingInstrumentHTTP_FillsParams(t *testing.T) {
t.Parallel()
tb := httpmultibin.NewHTTPMultiBin(t)

var gotRequests int64

tb.Mux.HandleFunc("/tracing", func(w http.ResponseWriter, r *http.Request) {
atomic.AddInt64(&gotRequests, 1)

assert.NotEmpty(t, r.Header.Get("traceparent"))
assert.Len(t, r.Header.Get("traceparent"), 55)

assert.NotEmpty(t, r.Header.Get("X-Test-Header"))
assert.Equal(t, "test", r.Header.Get("X-Test-Header"))
})

script := tb.Replacer.Replace(`
import http from "k6/http";
import { check } from "k6";
import tracing from "k6/experimental/tracing";
tracing.instrumentHTTP({
propagator: "w3c",
})
const testHeaders = {
"X-Test-Header": "test",
}
export default function () {
http.del("HTTPBIN_IP_URL/tracing", null, { headers: testHeaders });
http.get("HTTPBIN_IP_URL/tracing", { headers: testHeaders });
http.head("HTTPBIN_IP_URL/tracing", { headers: testHeaders });
http.options("HTTPBIN_IP_URL/tracing", null, { headers: testHeaders });
http.patch("HTTPBIN_IP_URL/tracing", null, { headers: testHeaders });
http.post("HTTPBIN_IP_URL/tracing", null, { headers: testHeaders });
http.put("HTTPBIN_IP_URL/tracing", null, { headers: testHeaders });
http.request("GET", "HTTPBIN_IP_URL/tracing", null, { headers: testHeaders });
};
`)

ts := getSingleFileTestState(t, script, []string{"--out", "json=results.json"}, 0)
cmd.ExecuteWithGlobalState(ts.GlobalState)

assert.Equal(t, int64(8), atomic.LoadInt64(&gotRequests))

jsonResults, err := afero.ReadFile(ts.FS, "results.json")
require.NoError(t, err)

assertHasTraceIDMetadata(t, jsonResults)
}

// assertHasTraceIDMetadata checks that the trace_id metadata is present and has the correct format
// for all http metrics in the json results file.
func assertHasTraceIDMetadata(t *testing.T, jsonResults []byte) {
gotHTTPDataPoints := false

for _, jsonLine := range bytes.Split(jsonResults, []byte("\n")) {
if len(jsonLine) == 0 {
continue
}

var line sampleEnvelope
require.NoError(t, json.Unmarshal(jsonLine, &line))

if line.Type != "Point" {
continue
}

// Filter metric samples which are not related to http
if !strings.HasPrefix(line.Metric, "http_") {
continue
}

gotHTTPDataPoints = true

anyTraceID, hasTraceID := line.Data.Metadata["trace_id"]
require.True(t, hasTraceID)

traceID, gotTraceID := anyTraceID.(string)
require.True(t, gotTraceID)

assert.Len(t, traceID, 32)
}

assert.True(t, gotHTTPDataPoints)
}

// sampleEnvelope is a trimmed version of the struct found
// in output/json/wrapper.go
// TODO: use the json output's wrapper struct instead if it's ever exported
Expand Down

0 comments on commit d255c80

Please sign in to comment.