From a9bdb338bfbc09b80a0dc69f98fa4bbdfde10b78 Mon Sep 17 00:00:00 2001 From: Ben Carr Date: Fri, 1 Mar 2024 17:18:49 -0800 Subject: [PATCH 1/2] WIP: start using semconv definitions from otel-go --- test/integration/traces_test.go | 49 ++++++++++++++++++--------------- test/tools/helpers.go | 22 +++++++++++++++ 2 files changed, 49 insertions(+), 22 deletions(-) create mode 100644 test/tools/helpers.go diff --git a/test/integration/traces_test.go b/test/integration/traces_test.go index 7a37687aa..4e101cdc0 100644 --- a/test/integration/traces_test.go +++ b/test/integration/traces_test.go @@ -13,9 +13,12 @@ import ( "github.com/mariomac/guara/pkg/test" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/attribute" + semconv "go.opentelemetry.io/otel/semconv/v1.24.0" "github.com/grafana/beyla/test/integration/components/jaeger" grpcclient "github.com/grafana/beyla/test/integration/components/testserver/grpc/client" + "github.com/grafana/beyla/test/tools" ) func testHTTPTracesNoTraceID(t *testing.T) { @@ -55,7 +58,7 @@ func testHTTPTracesCommon(t *testing.T, doTraceID bool, httpCode int) { require.Equal(t, http.StatusOK, resp.StatusCode) var tq jaeger.TracesQuery require.NoError(t, json.NewDecoder(resp.Body).Decode(&tq)) - traces := tq.FindBySpan(jaeger.Tag{Key: "url.path", Type: "string", Value: "/" + slug}) + traces := tq.FindBySpan(tools.KeyValueToJaegerTag(semconv.URLPath("/" + slug))) require.Len(t, traces, 1) trace = traces[0] require.Len(t, trace.Spans, 3) // parent - in queue - processing @@ -76,20 +79,20 @@ func testHTTPTracesCommon(t *testing.T, doTraceID bool, httpCode int) { // check duration is at least 10ms assert.Less(t, (10 * time.Millisecond).Microseconds(), parent.Duration) // check span attributes - sd := parent.Diff( - jaeger.Tag{Key: "http.request.method", Type: "string", Value: "GET"}, - jaeger.Tag{Key: "http.response.status_code", Type: "int64", Value: float64(httpCode)}, - jaeger.Tag{Key: "url.path", Type: "string", Value: "/" + slug}, - jaeger.Tag{Key: "server.port", Type: "int64", Value: float64(8080)}, - jaeger.Tag{Key: "http.route", Type: "string", Value: "/" + slug}, + tags := append( + tools.KeyValuesToJaegerTags([]attribute.KeyValue{ + semconv.HTTPRequestMethodGet, + semconv.HTTPResponseStatusCode(httpCode), + semconv.ServerPort(8080), + semconv.HTTPRoute("/" + slug), + }), jaeger.Tag{Key: "span.kind", Type: "string", Value: "server"}, ) + sd := parent.Diff(tags...) assert.Empty(t, sd, sd.String()) if httpCode >= 500 { - sd := parent.Diff( - jaeger.Tag{Key: "otel.status_code", Type: "string", Value: "ERROR"}, - ) + sd := parent.Diff(tools.KeyValueToJaegerTag(semconv.OTelStatusCodeError)) assert.Empty(t, sd, sd.String()) } @@ -107,7 +110,7 @@ func testHTTPTracesCommon(t *testing.T, doTraceID bool, httpCode int) { assert.LessOrEqual(t, queue.StartTime+queue.Duration, parent.StartTime+parent.Duration+1) // adding 1 to tolerate inaccuracies from rounding from ns to ms - // check span attributes + // check span attributes sd = queue.Diff( jaeger.Tag{Key: "span.kind", Type: "string", Value: "internal"}, @@ -145,10 +148,10 @@ func testHTTPTracesCommon(t *testing.T, doTraceID bool, httpCode int) { assert.Regexp(t, `^beyla-\d+$`, serviceInstance.Value) jaeger.Diff([]jaeger.Tag{ - {Key: "otel.library.name", Type: "string", Value: "github.com/grafana/beyla"}, - {Key: "telemetry.sdk.language", Type: "string", Value: "go"}, - {Key: "telemetry.sdk.name", Type: "string", Value: "beyla"}, - {Key: "service.namespace", Type: "string", Value: "integration-test"}, + tools.KeyValueToJaegerTag(semconv.OTelScopeName("github.com/grafana/beyla")), + tools.KeyValueToJaegerTag(semconv.TelemetrySDKLanguageGo), + tools.KeyValueToJaegerTag(semconv.TelemetrySDKName("beyla")), + tools.KeyValueToJaegerTag(semconv.ServiceNamespace("integration-test")), serviceInstance, }, process.Tags) assert.Empty(t, sd, sd.String()) @@ -162,7 +165,7 @@ func testHTTPTracesCommon(t *testing.T, doTraceID bool, httpCode int) { require.Equal(t, http.StatusOK, resp.StatusCode) var tq jaeger.TracesQuery require.NoError(t, json.NewDecoder(resp.Body).Decode(&tq)) - traces := tq.FindBySpan(jaeger.Tag{Key: "url.path", Type: "string", Value: "/metrics"}) + traces := tq.FindBySpan(tools.KeyValueToJaegerTag(semconv.URLPath("/metrics"))) require.Len(t, traces, 0) } @@ -180,7 +183,7 @@ func testGRPCTracesForServiceName(t *testing.T, svcName string) { require.Equal(t, http.StatusOK, resp.StatusCode) var tq jaeger.TracesQuery require.NoError(t, json.NewDecoder(resp.Body).Decode(&tq)) - traces := tq.FindBySpan(jaeger.Tag{Key: "rpc.method", Type: "string", Value: "/routeguide.RouteGuide/Debug"}) + traces := tq.FindBySpan(tools.KeyValueToJaegerTag(semconv.RPCMethod("/routeguide.RouteGuide/Debug"))) require.Len(t, traces, 1) trace = traces[0] require.Len(t, trace.Spans, 3) // parent - in queue - processing @@ -195,13 +198,15 @@ func testGRPCTracesForServiceName(t *testing.T, svcName string) { // check duration is at least 10ms (10,000 microseconds) assert.Less(t, (10 * time.Millisecond).Microseconds(), parent.Duration) // check span attributes - sd := parent.Diff( - jaeger.Tag{Key: "server.port", Type: "int64", Value: float64(5051)}, - jaeger.Tag{Key: "rpc.grpc.status_code", Type: "int64", Value: float64(2)}, - jaeger.Tag{Key: "rpc.method", Type: "string", Value: "/routeguide.RouteGuide/Debug"}, - jaeger.Tag{Key: "rpc.system", Type: "string", Value: "grpc"}, + tags := append( + tools.KeyValuesToJaegerTags([]attribute.KeyValue{ + semconv.ServerPort(5051), + semconv.RPCGRPCStatusCodeUnknown, + semconv.RPCMethod("/routeguide.RouteGuide/Debug"), + semconv.RPCSystemGRPC}), jaeger.Tag{Key: "span.kind", Type: "string", Value: "server"}, ) + sd := parent.Diff(tags...) assert.Empty(t, sd, sd.String()) // Check the information of the "in queue" span diff --git a/test/tools/helpers.go b/test/tools/helpers.go new file mode 100644 index 000000000..61bcf61c9 --- /dev/null +++ b/test/tools/helpers.go @@ -0,0 +1,22 @@ +package tools + +import ( + "github.com/grafana/beyla/test/integration/components/jaeger" + "go.opentelemetry.io/otel/attribute" +) + +func KeyValueToJaegerTag(kv attribute.KeyValue) jaeger.Tag { + return jaeger.Tag{ + Key: string(kv.Key), + Type: kv.Value.Type().String(), + Value: kv.Value.AsInterface(), + } +} + +func KeyValuesToJaegerTags(kvs []attribute.KeyValue) []jaeger.Tag { + tags := make([]jaeger.Tag, len(kvs)) + for i, kv := range kvs { + tags[i] = KeyValueToJaegerTag(kv) + } + return tags +} From 5c5776a6c2d5bcc46f4456402cc5acbeebbae939 Mon Sep 17 00:00:00 2001 From: Ben Carr Date: Mon, 4 Mar 2024 09:06:42 -0800 Subject: [PATCH 2/2] move helper functions to appropriate package --- test/integration/components/jaeger/jaeger.go | 18 ++++++++++++++++ test/integration/traces_test.go | 21 +++++++++---------- test/tools/helpers.go | 22 -------------------- 3 files changed, 28 insertions(+), 33 deletions(-) delete mode 100644 test/tools/helpers.go diff --git a/test/integration/components/jaeger/jaeger.go b/test/integration/components/jaeger/jaeger.go index c3dfa19a1..fe2abd33e 100644 --- a/test/integration/components/jaeger/jaeger.go +++ b/test/integration/components/jaeger/jaeger.go @@ -7,6 +7,8 @@ import ( "fmt" "regexp" "strings" + + "go.opentelemetry.io/otel/attribute" ) type TracesQuery struct { @@ -193,3 +195,19 @@ func DiffAsRegexp(expected, actual []Tag) DiffResult { } return dr } + +func TagFromOtel(kv attribute.KeyValue) Tag { + return Tag{ + Key: string(kv.Key), + Type: kv.Value.Type().String(), + Value: kv.Value.AsInterface(), + } +} + +func TagsFromOtel(kvs []attribute.KeyValue) []Tag { + tags := make([]Tag, len(kvs)) + for i, kv := range kvs { + tags[i] = TagFromOtel(kv) + } + return tags +} diff --git a/test/integration/traces_test.go b/test/integration/traces_test.go index 4e101cdc0..880aac16f 100644 --- a/test/integration/traces_test.go +++ b/test/integration/traces_test.go @@ -18,7 +18,6 @@ import ( "github.com/grafana/beyla/test/integration/components/jaeger" grpcclient "github.com/grafana/beyla/test/integration/components/testserver/grpc/client" - "github.com/grafana/beyla/test/tools" ) func testHTTPTracesNoTraceID(t *testing.T) { @@ -58,7 +57,7 @@ func testHTTPTracesCommon(t *testing.T, doTraceID bool, httpCode int) { require.Equal(t, http.StatusOK, resp.StatusCode) var tq jaeger.TracesQuery require.NoError(t, json.NewDecoder(resp.Body).Decode(&tq)) - traces := tq.FindBySpan(tools.KeyValueToJaegerTag(semconv.URLPath("/" + slug))) + traces := tq.FindBySpan(jaeger.TagFromOtel(semconv.URLPath("/" + slug))) require.Len(t, traces, 1) trace = traces[0] require.Len(t, trace.Spans, 3) // parent - in queue - processing @@ -80,7 +79,7 @@ func testHTTPTracesCommon(t *testing.T, doTraceID bool, httpCode int) { assert.Less(t, (10 * time.Millisecond).Microseconds(), parent.Duration) // check span attributes tags := append( - tools.KeyValuesToJaegerTags([]attribute.KeyValue{ + jaeger.TagsFromOtel([]attribute.KeyValue{ semconv.HTTPRequestMethodGet, semconv.HTTPResponseStatusCode(httpCode), semconv.ServerPort(8080), @@ -92,7 +91,7 @@ func testHTTPTracesCommon(t *testing.T, doTraceID bool, httpCode int) { assert.Empty(t, sd, sd.String()) if httpCode >= 500 { - sd := parent.Diff(tools.KeyValueToJaegerTag(semconv.OTelStatusCodeError)) + sd := parent.Diff(jaeger.TagFromOtel(semconv.OTelStatusCodeError)) assert.Empty(t, sd, sd.String()) } @@ -148,10 +147,10 @@ func testHTTPTracesCommon(t *testing.T, doTraceID bool, httpCode int) { assert.Regexp(t, `^beyla-\d+$`, serviceInstance.Value) jaeger.Diff([]jaeger.Tag{ - tools.KeyValueToJaegerTag(semconv.OTelScopeName("github.com/grafana/beyla")), - tools.KeyValueToJaegerTag(semconv.TelemetrySDKLanguageGo), - tools.KeyValueToJaegerTag(semconv.TelemetrySDKName("beyla")), - tools.KeyValueToJaegerTag(semconv.ServiceNamespace("integration-test")), + jaeger.TagFromOtel(semconv.OTelScopeName("github.com/grafana/beyla")), + jaeger.TagFromOtel(semconv.TelemetrySDKLanguageGo), + jaeger.TagFromOtel(semconv.TelemetrySDKName("beyla")), + jaeger.TagFromOtel(semconv.ServiceNamespace("integration-test")), serviceInstance, }, process.Tags) assert.Empty(t, sd, sd.String()) @@ -165,7 +164,7 @@ func testHTTPTracesCommon(t *testing.T, doTraceID bool, httpCode int) { require.Equal(t, http.StatusOK, resp.StatusCode) var tq jaeger.TracesQuery require.NoError(t, json.NewDecoder(resp.Body).Decode(&tq)) - traces := tq.FindBySpan(tools.KeyValueToJaegerTag(semconv.URLPath("/metrics"))) + traces := tq.FindBySpan(jaeger.TagFromOtel(semconv.URLPath("/metrics"))) require.Len(t, traces, 0) } @@ -183,7 +182,7 @@ func testGRPCTracesForServiceName(t *testing.T, svcName string) { require.Equal(t, http.StatusOK, resp.StatusCode) var tq jaeger.TracesQuery require.NoError(t, json.NewDecoder(resp.Body).Decode(&tq)) - traces := tq.FindBySpan(tools.KeyValueToJaegerTag(semconv.RPCMethod("/routeguide.RouteGuide/Debug"))) + traces := tq.FindBySpan(jaeger.TagFromOtel(semconv.RPCMethod("/routeguide.RouteGuide/Debug"))) require.Len(t, traces, 1) trace = traces[0] require.Len(t, trace.Spans, 3) // parent - in queue - processing @@ -199,7 +198,7 @@ func testGRPCTracesForServiceName(t *testing.T, svcName string) { assert.Less(t, (10 * time.Millisecond).Microseconds(), parent.Duration) // check span attributes tags := append( - tools.KeyValuesToJaegerTags([]attribute.KeyValue{ + jaeger.TagsFromOtel([]attribute.KeyValue{ semconv.ServerPort(5051), semconv.RPCGRPCStatusCodeUnknown, semconv.RPCMethod("/routeguide.RouteGuide/Debug"), diff --git a/test/tools/helpers.go b/test/tools/helpers.go deleted file mode 100644 index 61bcf61c9..000000000 --- a/test/tools/helpers.go +++ /dev/null @@ -1,22 +0,0 @@ -package tools - -import ( - "github.com/grafana/beyla/test/integration/components/jaeger" - "go.opentelemetry.io/otel/attribute" -) - -func KeyValueToJaegerTag(kv attribute.KeyValue) jaeger.Tag { - return jaeger.Tag{ - Key: string(kv.Key), - Type: kv.Value.Type().String(), - Value: kv.Value.AsInterface(), - } -} - -func KeyValuesToJaegerTags(kvs []attribute.KeyValue) []jaeger.Tag { - tags := make([]jaeger.Tag, len(kvs)) - for i, kv := range kvs { - tags[i] = KeyValueToJaegerTag(kv) - } - return tags -}