From ed753f120894a846ee9a4dd130330ac265be7ee4 Mon Sep 17 00:00:00 2001 From: Robb Kidd Date: Fri, 28 Apr 2023 13:02:30 +0000 Subject: [PATCH 01/12] wip: experiments with BATS --- .github/workflows/kind.yml | 6 ++-- Makefile | 5 ++- test/e2e/gorillamux/verify.bats | 18 ++++++++++ test/e2e/nethttp/verify.bats | 18 ++++++++++ test/test_helpers/utilities.bash | 59 ++++++++++++++++++++++++++++++++ 5 files changed, 99 insertions(+), 7 deletions(-) create mode 100644 test/e2e/gorillamux/verify.bats create mode 100644 test/e2e/nethttp/verify.bats create mode 100644 test/test_helpers/utilities.bash diff --git a/.github/workflows/kind.yml b/.github/workflows/kind.yml index c4f01fa6e..19a35c331 100644 --- a/.github/workflows/kind.yml +++ b/.github/workflows/kind.yml @@ -68,9 +68,7 @@ jobs: kubectl wait --for=condition=Complete --timeout=60s job/sample-job - name: copy telemetry trace output run: | - kubectl cp -c filecp default/test-opentelemetry-collector-0:tmp/trace.json ./test/e2e/${{ matrix.library }}/traces.json.tmp - jq 'del(.resourceSpans[].scopeSpans[].spans[].endTimeUnixNano, .resourceSpans[].scopeSpans[].spans[].startTimeUnixNano) | .resourceSpans[].scopeSpans[].spans[].spanId|= (if . != "" then "xxxxx" else . end) | .resourceSpans[].scopeSpans[].spans[].traceId|= (if . != "" then "xxxxx" else . end) | .resourceSpans[].scopeSpans|=sort_by(.scope.name)' ./test/e2e/${{ matrix.library }}/traces.json.tmp | jq --sort-keys . > ./test/e2e/${{ matrix.library }}/traces.json - rm ./test/e2e/${{ matrix.library }}/traces.json.tmp + kubectl cp -c filecp default/test-opentelemetry-collector-0:tmp/trace.json ./test/e2e/${{ matrix.library }}/traces.json - name: verify output run: | - make check-clean-work-tree + bats ./test/e2e/$(LIBRARY)/verify.bats diff --git a/Makefile b/Makefile index f405190a7..68bbdd8bb 100644 --- a/Makefile +++ b/Makefile @@ -136,9 +136,8 @@ fixtures/%: kubectl wait --for=condition=Ready --timeout=60s pod/test-opentelemetry-collector-0 kubectl -n default create -f .github/workflows/e2e/k8s/sample-job.yml kubectl wait --for=condition=Complete --timeout=60s job/sample-job - kubectl cp -c filecp default/test-opentelemetry-collector-0:tmp/trace.json ./test/e2e/$(LIBRARY)/traces.json.tmp - jq 'del(.resourceSpans[].scopeSpans[].spans[].endTimeUnixNano, .resourceSpans[].scopeSpans[].spans[].startTimeUnixNano) | .resourceSpans[].scopeSpans[].spans[].spanId|= (if . != "" then "xxxxx" else . end) | .resourceSpans[].scopeSpans[].spans[].traceId|= (if . != "" then "xxxxx" else . end) | .resourceSpans[].scopeSpans|=sort_by(.scope.name)' ./test/e2e/$(LIBRARY)/traces.json.tmp | jq --sort-keys . > ./test/e2e/$(LIBRARY)/traces.json - rm ./test/e2e/$(LIBRARY)/traces.json.tmp + kubectl cp -c filecp default/test-opentelemetry-collector-0:tmp/trace.json ./test/e2e/$(LIBRARY)/traces.json + bats ./test/e2e/$(LIBRARY)/verify.bats kind delete cluster .PHONY: prerelease diff --git a/test/e2e/gorillamux/verify.bats b/test/e2e/gorillamux/verify.bats new file mode 100644 index 000000000..e9d64b4f3 --- /dev/null +++ b/test/e2e/gorillamux/verify.bats @@ -0,0 +1,18 @@ +#!/usr/bin/env bats + +load ../../test_helpers/utilities + +@test "go-auto :: includes service.name in resource attributes" { + result=$(resource_attributes_received | jq "select(.key == \"service.name\").value.stringValue") + assert_equal "$result" '"sample-app"' +} + +@test "gorillamux :: emits a span name '{http.method} {http.route}' (per semconv)" { + result=$(span_names_for "github.com/gorilla/mux") + assert_equal "$result" '"GET /hello"' +} + +@test "gorillamux :: trace ID present in all spans" { + result=$(spans_from_scope_named "github.com/gorilla/mux" | jq ".traceId") + assert_equal "$result" 'hey' +} diff --git a/test/e2e/nethttp/verify.bats b/test/e2e/nethttp/verify.bats new file mode 100644 index 000000000..2bc25d417 --- /dev/null +++ b/test/e2e/nethttp/verify.bats @@ -0,0 +1,18 @@ +#!/usr/bin/env bats + +load ../../test_helpers/utilities + +@test "go-auto :: includes service.name in resource attributes" { + result=$(resource_attributes_received | jq "select(.key == \"service.name\").value.stringValue") + assert_equal "$result" '"sample-app"' +} + +@test "net/http :: emits a span name '{http.method} {http.route}' (per semconv)" { + result=$(span_names_for "net/http") + assert_equal "$result" '"GET /hello"' +} + +@test "net/http :: trace ID present in all spans" { + result=$(spans_from_scope_named "net/http" | jq ".traceId") + assert_equal "$result" 'hey' +} diff --git a/test/test_helpers/utilities.bash b/test/test_helpers/utilities.bash new file mode 100644 index 000000000..e83cf91de --- /dev/null +++ b/test/test_helpers/utilities.bash @@ -0,0 +1,59 @@ +# DATA RETRIEVERS + +# Returns a list of span names emitted by a given library/scope + # $1 - library/scope name +span_names_for() { + spans_from_scope_named $1 | jq '.name' +} + +# Returns a list of attributes emitted by a given library/scope +span_attributes_for() { + # $1 - library/scope name + + spans_from_scope_named $1 | \ + jq ".attributes[]" +} + +# Returns a list of all resource attributes +resource_attributes_received() { + spans_received | jq ".resource.attributes[]?" +} + +# Returns an array of all spans emitted by a given library/scope + # $1 - library/scope name +spans_from_scope_named() { + spans_received | jq ".scopeSpans[] | select(.scope.name == \"$1\").spans[]" +} + +# Returns an array of all spans received +spans_received() { + jq ".resourceSpans[]?" "${BATS_TEST_DIRNAME}/traces.json" +} + +# Returns the content of the log file produced by a collector +# and located in the same directory as the BATS test file +# loading this helper script. +json_output() { + cat "${BATS_TEST_DIRNAME}/traces.json" +} + +# ASSERTION HELPERS + +# Fail and display details if the expected and actual values do not +# equal. Details include both values. +# +# Inspired by bats-assert * bats-support, but dramatically simplified +assert_equal() { + if [[ $1 != "$2" ]]; then + { + echo + echo "-- 💥 values are not equal 💥 --" + echo "expected : $2" + echo "actual : $1" + echo "--" + echo + } >&2 # output error to STDERR + return 1 + fi +} + From 35c328f658c39ece13e49ea724ee52718eb0be86 Mon Sep 17 00:00:00 2001 From: Robb Kidd Date: Fri, 28 Apr 2023 19:54:01 +0000 Subject: [PATCH 02/12] add a bats suite for gin instrumentation --- test/e2e/gin/verify.bats | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 test/e2e/gin/verify.bats diff --git a/test/e2e/gin/verify.bats b/test/e2e/gin/verify.bats new file mode 100644 index 000000000..a66e70b71 --- /dev/null +++ b/test/e2e/gin/verify.bats @@ -0,0 +1,18 @@ +#!/usr/bin/env bats + +load ../../test_helpers/utilities + +@test "go-auto :: includes service.name in resource attributes" { + result=$(resource_attributes_received | jq "select(.key == \"service.name\").value.stringValue") + assert_equal "$result" '"sample-app"' +} + +@test "gorillamux :: emits a span name '{http.method} {http.route}' (per semconv)" { + result=$(span_names_for "github.com/gin-gonic/gin") + assert_equal "$result" '"GET /hello"' +} + +@test "gorillamux :: trace ID present in all spans" { + result=$(spans_from_scope_named "github.com/gin-gonic/gin" | jq ".traceId") + assert_equal "$result" 'hey' +} From d6e77fb2b8b928aa04625dddda78e15d294c17e4 Mon Sep 17 00:00:00 2001 From: Robb Kidd Date: Fri, 28 Apr 2023 19:54:17 +0000 Subject: [PATCH 03/12] ensure CI runner has bats installed --- .github/workflows/kind.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/kind.yml b/.github/workflows/kind.yml index 19a35c331..1d976510c 100644 --- a/.github/workflows/kind.yml +++ b/.github/workflows/kind.yml @@ -22,6 +22,8 @@ jobs: uses: actions/setup-go@v4 with: go-version: "1.20" + - name: Setup BATS + uses: mig4/setup-bats@v1 - name: Build auto-instrumentation run: | IMG=otel-go-instrumentation:latest make docker-build From b94a84a26c1f632ce3e9be5a55c1e722f3494f2d Mon Sep 17 00:00:00 2001 From: Robb Kidd Date: Fri, 28 Apr 2023 20:05:27 +0000 Subject: [PATCH 04/12] workflow YAML is not shell :facepalm: --- .github/workflows/kind.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/kind.yml b/.github/workflows/kind.yml index 1d976510c..2397ab90a 100644 --- a/.github/workflows/kind.yml +++ b/.github/workflows/kind.yml @@ -73,4 +73,4 @@ jobs: kubectl cp -c filecp default/test-opentelemetry-collector-0:tmp/trace.json ./test/e2e/${{ matrix.library }}/traces.json - name: verify output run: | - bats ./test/e2e/$(LIBRARY)/verify.bats + bats ./test/e2e/${{ matrix.library }}/verify.bats From 62810db872b06706764fcac870de4a02e509f0d4 Mon Sep 17 00:00:00 2001 From: JamieDanielson Date: Tue, 2 May 2023 15:39:17 -0400 Subject: [PATCH 05/12] test: add assert_not_empty helper --- test/test_helpers/utilities.bash | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/test_helpers/utilities.bash b/test/test_helpers/utilities.bash index e83cf91de..4ddc8489c 100644 --- a/test/test_helpers/utilities.bash +++ b/test/test_helpers/utilities.bash @@ -57,3 +57,23 @@ assert_equal() { fi } +assert_not_empty() { + EMPTY=(\"\") + if [[ "$1" == "${EMPTY}" ]]; then + { + echo + echo "-- 💥 value is empty 💥 --" + echo "value : $1" + echo "--" + echo + } >&2 # output error to STDERR + return 1 + else + { + echo + echo "-- ✅ value is not empty ✅ --" + echo "value : $1" + } >&3 # output success to STDOUT + return 0 + fi +} From e4bccbb6c9727b92c924a71c99a4c071915080cb Mon Sep 17 00:00:00 2001 From: JamieDanielson Date: Tue, 2 May 2023 15:39:53 -0400 Subject: [PATCH 06/12] more assertions for nethttp --- test/e2e/nethttp/verify.bats | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/test/e2e/nethttp/verify.bats b/test/e2e/nethttp/verify.bats index 2bc25d417..f49b7c2ab 100644 --- a/test/e2e/nethttp/verify.bats +++ b/test/e2e/nethttp/verify.bats @@ -2,17 +2,36 @@ load ../../test_helpers/utilities +LIBRARY_NAME="net/http" + @test "go-auto :: includes service.name in resource attributes" { result=$(resource_attributes_received | jq "select(.key == \"service.name\").value.stringValue") assert_equal "$result" '"sample-app"' } -@test "net/http :: emits a span name '{http.method} {http.route}' (per semconv)" { - result=$(span_names_for "net/http") - assert_equal "$result" '"GET /hello"' +# TODO: span name should include http.method per spec +# @test "${LIBRARY_NAME} :: emits a span name '{http.method} {http.target}' (per semconv)" { +@test "${LIBRARY_NAME} :: emits a span name '{http.route}'" { + result=$(span_names_for ${LIBRARY_NAME}) + assert_equal "$result" '"/hello"' +} + +@test "${LIBRARY_NAME} :: includes http.method attribute" { + result=$(span_attributes_for ${LIBRARY_NAME} | jq "select(.key == \"http.method\").value.stringValue") + assert_equal "$result" '"GET"' } -@test "net/http :: trace ID present in all spans" { - result=$(spans_from_scope_named "net/http" | jq ".traceId") - assert_equal "$result" 'hey' +@test "${LIBRARY_NAME} :: includes http.target attribute" { + result=$(span_attributes_for ${LIBRARY_NAME} | jq "select(.key == \"http.target\").value.stringValue") + assert_equal "$result" '"/hello"' } + +@test "${LIBRARY_NAME} :: trace ID present in all spans" { + result=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".traceId") + assert_not_empty "$result" +} + +@test "${LIBRARY_NAME} :: span ID present in all spans" { + result=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".spanId") + assert_not_empty "$result" +} \ No newline at end of file From ee26ad862eaedfdd476e9de9beaa23a7ad3302e0 Mon Sep 17 00:00:00 2001 From: JamieDanielson Date: Tue, 2 May 2023 15:40:26 -0400 Subject: [PATCH 07/12] more assertions for gorillamux spans currently show net/http, will need review for lib name --- test/e2e/gorillamux/verify.bats | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/test/e2e/gorillamux/verify.bats b/test/e2e/gorillamux/verify.bats index e9d64b4f3..21c53533e 100644 --- a/test/e2e/gorillamux/verify.bats +++ b/test/e2e/gorillamux/verify.bats @@ -2,17 +2,38 @@ load ../../test_helpers/utilities +LIBRARY_NAME="github.com/gorilla/mux" +# TODO: spans currently show net/http as the library name +TEMP_LIBRARY_NAME="net/http" + @test "go-auto :: includes service.name in resource attributes" { result=$(resource_attributes_received | jq "select(.key == \"service.name\").value.stringValue") assert_equal "$result" '"sample-app"' } -@test "gorillamux :: emits a span name '{http.method} {http.route}' (per semconv)" { - result=$(span_names_for "github.com/gorilla/mux") - assert_equal "$result" '"GET /hello"' +# TODO: span name should include http.method per spec +# @test "${LIBRARY_NAME} :: emits a span name '{http.method} {http.target}' (per semconv)" { +@test "${LIBRARY_NAME} :: emits a span name '{http.route}'" { + result=$(span_names_for ${TEMP_LIBRARY_NAME}) + assert_equal "$result" '"/users/foo"' +} + +@test "${LIBRARY_NAME} :: includes http.method attribute" { + result=$(span_attributes_for ${TEMP_LIBRARY_NAME} | jq "select(.key == \"http.method\").value.stringValue") + assert_equal "$result" '"GET"' } -@test "gorillamux :: trace ID present in all spans" { - result=$(spans_from_scope_named "github.com/gorilla/mux" | jq ".traceId") - assert_equal "$result" 'hey' +@test "${LIBRARY_NAME} :: includes http.target attribute" { + result=$(span_attributes_for ${TEMP_LIBRARY_NAME} | jq "select(.key == \"http.target\").value.stringValue") + assert_equal "$result" '"/users/foo"' } + +@test "${LIBRARY_NAME} :: trace ID present in all spans" { + result=$(spans_from_scope_named ${TEMP_LIBRARY_NAME} | jq ".traceId") + assert_not_empty "$result" +} + +@test "${LIBRARY_NAME} :: span ID present in all spans" { + result=$(spans_from_scope_named ${TEMP_LIBRARY_NAME} | jq ".spanId") + assert_not_empty "$result" +} \ No newline at end of file From 69a0032e75fb242514fc5ec5cffd63d3173c5cde Mon Sep 17 00:00:00 2001 From: JamieDanielson Date: Tue, 2 May 2023 15:46:07 -0400 Subject: [PATCH 08/12] more assertions for gin --- test/e2e/gin/verify.bats | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/test/e2e/gin/verify.bats b/test/e2e/gin/verify.bats index a66e70b71..b3477e841 100644 --- a/test/e2e/gin/verify.bats +++ b/test/e2e/gin/verify.bats @@ -2,17 +2,36 @@ load ../../test_helpers/utilities +LIBRARY_NAME="github.com/gin-gonic/gin" + @test "go-auto :: includes service.name in resource attributes" { result=$(resource_attributes_received | jq "select(.key == \"service.name\").value.stringValue") assert_equal "$result" '"sample-app"' } -@test "gorillamux :: emits a span name '{http.method} {http.route}' (per semconv)" { - result=$(span_names_for "github.com/gin-gonic/gin") - assert_equal "$result" '"GET /hello"' +# TODO: span name should include http.method per spec +# @test "${LIBRARY_NAME} :: emits a span name '{http.method} {http.target}' (per semconv)" { +@test "${LIBRARY_NAME} :: emits a span name '{http.route}'" { + result=$(span_names_for ${LIBRARY_NAME}) + assert_equal "$result" '"/hello-gin"' +} + +@test "${LIBRARY_NAME} :: includes http.method attribute" { + result=$(span_attributes_for ${LIBRARY_NAME} | jq "select(.key == \"http.method\").value.stringValue") + assert_equal "$result" '"GET"' } -@test "gorillamux :: trace ID present in all spans" { - result=$(spans_from_scope_named "github.com/gin-gonic/gin" | jq ".traceId") - assert_equal "$result" 'hey' +@test "${LIBRARY_NAME} :: includes http.target attribute" { + result=$(span_attributes_for ${LIBRARY_NAME} | jq "select(.key == \"http.target\").value.stringValue") + assert_equal "$result" '"/hello-gin"' } + +@test "${LIBRARY_NAME} :: trace ID present in all spans" { + result=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".traceId") + assert_not_empty "$result" +} + +@test "${LIBRARY_NAME} :: span ID present in all spans" { + result=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".spanId") + assert_not_empty "$result" +} \ No newline at end of file From f8ed8cdca0e9fe9af60ddcf3809a03a69c178da8 Mon Sep 17 00:00:00 2001 From: Robb Kidd Date: Tue, 9 May 2023 15:17:45 -0400 Subject: [PATCH 09/12] update http expectations after span name update PR #143 updated these span names to include HTTP method per the spec. --- test/e2e/gin/verify.bats | 8 +++----- test/e2e/gorillamux/verify.bats | 8 +++----- test/e2e/nethttp/verify.bats | 8 +++----- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/test/e2e/gin/verify.bats b/test/e2e/gin/verify.bats index b3477e841..ebd840c30 100644 --- a/test/e2e/gin/verify.bats +++ b/test/e2e/gin/verify.bats @@ -9,11 +9,9 @@ LIBRARY_NAME="github.com/gin-gonic/gin" assert_equal "$result" '"sample-app"' } -# TODO: span name should include http.method per spec -# @test "${LIBRARY_NAME} :: emits a span name '{http.method} {http.target}' (per semconv)" { -@test "${LIBRARY_NAME} :: emits a span name '{http.route}'" { +@test "${LIBRARY_NAME} :: emits a span name '{http.method} {http.target}' (per semconv)" { result=$(span_names_for ${LIBRARY_NAME}) - assert_equal "$result" '"/hello-gin"' + assert_equal "$result" '"GET /hello-gin"' } @test "${LIBRARY_NAME} :: includes http.method attribute" { @@ -34,4 +32,4 @@ LIBRARY_NAME="github.com/gin-gonic/gin" @test "${LIBRARY_NAME} :: span ID present in all spans" { result=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".spanId") assert_not_empty "$result" -} \ No newline at end of file +} diff --git a/test/e2e/gorillamux/verify.bats b/test/e2e/gorillamux/verify.bats index 21c53533e..d8ac3e282 100644 --- a/test/e2e/gorillamux/verify.bats +++ b/test/e2e/gorillamux/verify.bats @@ -11,11 +11,9 @@ TEMP_LIBRARY_NAME="net/http" assert_equal "$result" '"sample-app"' } -# TODO: span name should include http.method per spec -# @test "${LIBRARY_NAME} :: emits a span name '{http.method} {http.target}' (per semconv)" { -@test "${LIBRARY_NAME} :: emits a span name '{http.route}'" { +@test "${LIBRARY_NAME} :: emits a span name '{http.method} {http.target}' (per semconv)" { result=$(span_names_for ${TEMP_LIBRARY_NAME}) - assert_equal "$result" '"/users/foo"' + assert_equal "$result" '"GET /users/foo"' } @test "${LIBRARY_NAME} :: includes http.method attribute" { @@ -36,4 +34,4 @@ TEMP_LIBRARY_NAME="net/http" @test "${LIBRARY_NAME} :: span ID present in all spans" { result=$(spans_from_scope_named ${TEMP_LIBRARY_NAME} | jq ".spanId") assert_not_empty "$result" -} \ No newline at end of file +} diff --git a/test/e2e/nethttp/verify.bats b/test/e2e/nethttp/verify.bats index f49b7c2ab..48d705410 100644 --- a/test/e2e/nethttp/verify.bats +++ b/test/e2e/nethttp/verify.bats @@ -9,11 +9,9 @@ LIBRARY_NAME="net/http" assert_equal "$result" '"sample-app"' } -# TODO: span name should include http.method per spec -# @test "${LIBRARY_NAME} :: emits a span name '{http.method} {http.target}' (per semconv)" { -@test "${LIBRARY_NAME} :: emits a span name '{http.route}'" { +@test "${LIBRARY_NAME} :: emits a span name '{http.method} {http.target}' (per semconv)" { result=$(span_names_for ${LIBRARY_NAME}) - assert_equal "$result" '"/hello"' + assert_equal "$result" '"GET /hello"' } @test "${LIBRARY_NAME} :: includes http.method attribute" { @@ -34,4 +32,4 @@ LIBRARY_NAME="net/http" @test "${LIBRARY_NAME} :: span ID present in all spans" { result=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".spanId") assert_not_empty "$result" -} \ No newline at end of file +} From dad1fb8061ed8b779f3602d7e850600ca11cc273 Mon Sep 17 00:00:00 2001 From: Robb Kidd Date: Thu, 11 May 2023 15:38:29 -0400 Subject: [PATCH 10/12] keep traces.json around + remove before verifying with e2e assertions + bring back redaction-jq as a function within the BATS utilities + assert no git difference with a BATS test --- .github/workflows/kind.yml | 5 ++-- Makefile | 3 +- test/e2e/gin/verify.bats | 17 +++++++---- test/e2e/gorillamux/verify.bats | 17 +++++++---- test/e2e/nethttp/verify.bats | 17 +++++++---- test/test_helpers/utilities.bash | 48 ++++++++++++++++++++++++++------ 6 files changed, 77 insertions(+), 30 deletions(-) diff --git a/.github/workflows/kind.yml b/.github/workflows/kind.yml index 2397ab90a..e20d9985c 100644 --- a/.github/workflows/kind.yml +++ b/.github/workflows/kind.yml @@ -70,7 +70,8 @@ jobs: kubectl wait --for=condition=Complete --timeout=60s job/sample-job - name: copy telemetry trace output run: | - kubectl cp -c filecp default/test-opentelemetry-collector-0:tmp/trace.json ./test/e2e/${{ matrix.library }}/traces.json - - name: verify output + kubectl cp -c filecp default/test-opentelemetry-collector-0:tmp/trace.json ./test/e2e/${{ matrix.library }}/traces-orig.json + rm -f ./test/e2e/${{ matrix.library }}/traces.json + - name: verify output and redact to traces.json run: | bats ./test/e2e/${{ matrix.library }}/verify.bats diff --git a/Makefile b/Makefile index 68bbdd8bb..ed058af7b 100644 --- a/Makefile +++ b/Makefile @@ -136,7 +136,8 @@ fixtures/%: kubectl wait --for=condition=Ready --timeout=60s pod/test-opentelemetry-collector-0 kubectl -n default create -f .github/workflows/e2e/k8s/sample-job.yml kubectl wait --for=condition=Complete --timeout=60s job/sample-job - kubectl cp -c filecp default/test-opentelemetry-collector-0:tmp/trace.json ./test/e2e/$(LIBRARY)/traces.json + kubectl cp -c filecp default/test-opentelemetry-collector-0:tmp/trace.json ./test/e2e/$(LIBRARY)/traces-orig.json + rm -f ./test/e2e/$(LIBRARY)/traces.json bats ./test/e2e/$(LIBRARY)/verify.bats kind delete cluster diff --git a/test/e2e/gin/verify.bats b/test/e2e/gin/verify.bats index ebd840c30..198590c16 100644 --- a/test/e2e/gin/verify.bats +++ b/test/e2e/gin/verify.bats @@ -24,12 +24,17 @@ LIBRARY_NAME="github.com/gin-gonic/gin" assert_equal "$result" '"/hello-gin"' } -@test "${LIBRARY_NAME} :: trace ID present in all spans" { - result=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".traceId") - assert_not_empty "$result" +@test "${LIBRARY_NAME} :: trace ID present and valid in all spans" { + trace_id=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".traceId") + assert_regex "$trace_id" ${MATCH_A_TRACE_ID} } -@test "${LIBRARY_NAME} :: span ID present in all spans" { - result=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".spanId") - assert_not_empty "$result" +@test "${LIBRARY_NAME} :: span ID present and valid in all spans" { + span_id=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".spanId") + assert_regex "$span_id" ${MATCH_A_SPAN_ID} +} + +@test "${LIBRARY_NAME} :: expected (redacted) trace output" { + redact_json + assert_equal "$(git --no-pager diff ${BATS_TEST_DIRNAME}/traces.json)" "" } diff --git a/test/e2e/gorillamux/verify.bats b/test/e2e/gorillamux/verify.bats index d8ac3e282..c8aa467ea 100644 --- a/test/e2e/gorillamux/verify.bats +++ b/test/e2e/gorillamux/verify.bats @@ -26,12 +26,17 @@ TEMP_LIBRARY_NAME="net/http" assert_equal "$result" '"/users/foo"' } -@test "${LIBRARY_NAME} :: trace ID present in all spans" { - result=$(spans_from_scope_named ${TEMP_LIBRARY_NAME} | jq ".traceId") - assert_not_empty "$result" +@test "${LIBRARY_NAME} :: trace ID present and valid in all spans" { + trace_id=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".traceId") + assert_regex "$trace_id" ${MATCH_A_TRACE_ID} } -@test "${LIBRARY_NAME} :: span ID present in all spans" { - result=$(spans_from_scope_named ${TEMP_LIBRARY_NAME} | jq ".spanId") - assert_not_empty "$result" +@test "${LIBRARY_NAME} :: span ID present and valid in all spans" { + span_id=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".spanId") + assert_regex "$span_id" ${MATCH_A_SPAN_ID} +} + +@test "${LIBRARY_NAME} :: expected (redacted) trace output" { + redact_json + assert_equal "$(git --no-pager diff ${BATS_TEST_DIRNAME}/traces.json)" "" } diff --git a/test/e2e/nethttp/verify.bats b/test/e2e/nethttp/verify.bats index 48d705410..ff9f6b3ee 100644 --- a/test/e2e/nethttp/verify.bats +++ b/test/e2e/nethttp/verify.bats @@ -24,12 +24,17 @@ LIBRARY_NAME="net/http" assert_equal "$result" '"/hello"' } -@test "${LIBRARY_NAME} :: trace ID present in all spans" { - result=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".traceId") - assert_not_empty "$result" +@test "${LIBRARY_NAME} :: trace ID present and valid in all spans" { + trace_id=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".traceId") + assert_regex "$trace_id" ${MATCH_A_TRACE_ID} } -@test "${LIBRARY_NAME} :: span ID present in all spans" { - result=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".spanId") - assert_not_empty "$result" +@test "${LIBRARY_NAME} :: span ID present and valid in all spans" { + span_id=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".spanId") + assert_regex "$span_id" ${MATCH_A_SPAN_ID} +} + +@test "${LIBRARY_NAME} :: expected (redacted) trace output" { + redact_json + assert_equal "$(git --no-pager diff ${BATS_TEST_DIRNAME}/traces.json)" "" } diff --git a/test/test_helpers/utilities.bash b/test/test_helpers/utilities.bash index 4ddc8489c..d0cf8aa3f 100644 --- a/test/test_helpers/utilities.bash +++ b/test/test_helpers/utilities.bash @@ -27,18 +27,41 @@ spans_from_scope_named() { # Returns an array of all spans received spans_received() { - jq ".resourceSpans[]?" "${BATS_TEST_DIRNAME}/traces.json" + json_output | jq ".resourceSpans[]?" } # Returns the content of the log file produced by a collector # and located in the same directory as the BATS test file # loading this helper script. json_output() { - cat "${BATS_TEST_DIRNAME}/traces.json" + cat "${BATS_TEST_DIRNAME}/traces-orig.json" +} + +redact_json() { + json_output | \ + jq --sort-keys ' + del( + .resourceSpans[].scopeSpans[].spans[].startTimeUnixNano, + .resourceSpans[].scopeSpans[].spans[].endTimeUnixNano + ) + | .resourceSpans[].scopeSpans[].spans[].traceId|= (if + . // "" | test("^[A-Fa-f0-9]{32}$") then "xxxxx" else (. + "<-INVALID") + end) + | .resourceSpans[].scopeSpans[].spans[].spanId|= (if + . // "" | test("^[A-Fa-f0-9]{16}$") then "xxxxx" else (. + "<-INVALID") + end) + | .resourceSpans[].scopeSpans|=sort_by(.scope.name) + ' > ${BATS_TEST_DIRNAME}/traces.json } # ASSERTION HELPERS +# expect a 32-digit hexadecimal string (in quotes) +MATCH_A_TRACE_ID=^"\"[A-Fa-f0-9]{32}\"$" + +# expect a 16-digit hexadecimal string (in quotes) +MATCH_A_SPAN_ID=^"\"[A-Fa-f0-9]{16}\"$" + # Fail and display details if the expected and actual values do not # equal. Details include both values. # @@ -57,6 +80,20 @@ assert_equal() { fi } +assert_regex() { + if ! [[ $1 =~ $2 ]]; then + { + echo + echo "-- 💥 value does not match regular expression 💥 --" + echo "value : $1" + echo "pattern : $2" + echo "--" + echo + } >&2 # output error to STDERR + return 1 + fi +} + assert_not_empty() { EMPTY=(\"\") if [[ "$1" == "${EMPTY}" ]]; then @@ -68,12 +105,5 @@ assert_not_empty() { echo } >&2 # output error to STDERR return 1 - else - { - echo - echo "-- ✅ value is not empty ✅ --" - echo "value : $1" - } >&3 # output success to STDOUT - return 0 fi } From 563e23438ac26db0fb68a39e0854becf90201d50 Mon Sep 17 00:00:00 2001 From: Robb Kidd Date: Thu, 11 May 2023 15:50:31 -0400 Subject: [PATCH 11/12] need to lookup gorillamux as net/http for now --- test/e2e/gorillamux/verify.bats | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/e2e/gorillamux/verify.bats b/test/e2e/gorillamux/verify.bats index c8aa467ea..7ec50184a 100644 --- a/test/e2e/gorillamux/verify.bats +++ b/test/e2e/gorillamux/verify.bats @@ -27,12 +27,12 @@ TEMP_LIBRARY_NAME="net/http" } @test "${LIBRARY_NAME} :: trace ID present and valid in all spans" { - trace_id=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".traceId") + trace_id=$(spans_from_scope_named ${TEMP_LIBRARY_NAME} | jq ".traceId") assert_regex "$trace_id" ${MATCH_A_TRACE_ID} } @test "${LIBRARY_NAME} :: span ID present and valid in all spans" { - span_id=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".spanId") + span_id=$(spans_from_scope_named ${TEMP_LIBRARY_NAME} | jq ".spanId") assert_regex "$span_id" ${MATCH_A_SPAN_ID} } From 0361d961995fb3118b115cccb5450c02d7521a50 Mon Sep 17 00:00:00 2001 From: JamieDanielson Date: Mon, 15 May 2023 13:22:59 -0400 Subject: [PATCH 12/12] update test for gorillamux spans now present --- test/e2e/gorillamux/verify.bats | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/test/e2e/gorillamux/verify.bats b/test/e2e/gorillamux/verify.bats index 7ec50184a..711ac3b7a 100644 --- a/test/e2e/gorillamux/verify.bats +++ b/test/e2e/gorillamux/verify.bats @@ -3,8 +3,6 @@ load ../../test_helpers/utilities LIBRARY_NAME="github.com/gorilla/mux" -# TODO: spans currently show net/http as the library name -TEMP_LIBRARY_NAME="net/http" @test "go-auto :: includes service.name in resource attributes" { result=$(resource_attributes_received | jq "select(.key == \"service.name\").value.stringValue") @@ -12,27 +10,27 @@ TEMP_LIBRARY_NAME="net/http" } @test "${LIBRARY_NAME} :: emits a span name '{http.method} {http.target}' (per semconv)" { - result=$(span_names_for ${TEMP_LIBRARY_NAME}) + result=$(span_names_for ${LIBRARY_NAME}) assert_equal "$result" '"GET /users/foo"' } @test "${LIBRARY_NAME} :: includes http.method attribute" { - result=$(span_attributes_for ${TEMP_LIBRARY_NAME} | jq "select(.key == \"http.method\").value.stringValue") + result=$(span_attributes_for ${LIBRARY_NAME} | jq "select(.key == \"http.method\").value.stringValue") assert_equal "$result" '"GET"' } @test "${LIBRARY_NAME} :: includes http.target attribute" { - result=$(span_attributes_for ${TEMP_LIBRARY_NAME} | jq "select(.key == \"http.target\").value.stringValue") + result=$(span_attributes_for ${LIBRARY_NAME} | jq "select(.key == \"http.target\").value.stringValue") assert_equal "$result" '"/users/foo"' } @test "${LIBRARY_NAME} :: trace ID present and valid in all spans" { - trace_id=$(spans_from_scope_named ${TEMP_LIBRARY_NAME} | jq ".traceId") + trace_id=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".traceId") assert_regex "$trace_id" ${MATCH_A_TRACE_ID} } @test "${LIBRARY_NAME} :: span ID present and valid in all spans" { - span_id=$(spans_from_scope_named ${TEMP_LIBRARY_NAME} | jq ".spanId") + span_id=$(spans_from_scope_named ${LIBRARY_NAME} | jq ".spanId") assert_regex "$span_id" ${MATCH_A_SPAN_ID} }