Skip to content

Commit 839a656

Browse files
committed
Add start to integration tests
1 parent 1cee96d commit 839a656

File tree

6 files changed

+211
-11
lines changed

6 files changed

+211
-11
lines changed

.github/dependabot.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ updates:
4242
directory: "/instrumentation/github.com/graph-gophers/graphql-go/splunkgraphql"
4343
schedule:
4444
interval: "daily"
45+
- package-ecosystem: "gomod"
46+
directory: "/instrumentation/github.com/graph-gophers/graphql-go/splunkgraphql/test"
47+
schedule:
48+
interval: "daily"
4549
- package-ecosystem: "gomod"
4650
directory: "/instrumentation/github.com/jackc/pgx/splunkpgx"
4751
schedule:

instrumentation/github.com/graph-gophers/graphql-go/splunkgraphql/graphql.go

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,14 @@ import (
2323
"github.com/graph-gophers/graphql-go/errors"
2424
"github.com/graph-gophers/graphql-go/introspection"
2525
"github.com/graph-gophers/graphql-go/trace"
26+
gql "github.com/signalfx/splunk-otel-go/instrumentation/github.com/graph-gophers/graphql-go/splunkgraphql/internal"
2627
"github.com/signalfx/splunk-otel-go/instrumentation/internal"
27-
"go.opentelemetry.io/otel/attribute"
2828
"go.opentelemetry.io/otel/codes"
2929
oteltrace "go.opentelemetry.io/otel/trace"
3030
)
3131

3232
const instrumentationName = "github.com/signalfx/splunk-otel-go/instrumentation/github.com/graph-gophers/graphql-go/splunkgraphql"
3333

34-
var (
35-
graphqlFieldKey = attribute.Key("graphql.field")
36-
graphqlQueryKey = attribute.Key("graphql.query")
37-
graphqlTypeKey = attribute.Key("graphql.type")
38-
)
39-
4034
// otelTracer implements the graphql-go/trace.Tracer interface using
4135
// OpenTelemetry.
4236
type otelTracer struct {
@@ -78,7 +72,7 @@ func (t *otelTracer) TraceQuery(ctx context.Context, queryString string, operati
7872
ctx,
7973
"GraphQL request",
8074
oteltrace.WithSpanKind(oteltrace.SpanKindServer),
81-
oteltrace.WithAttributes(graphqlQueryKey.String(queryString)),
75+
oteltrace.WithAttributes(gql.GraphQLQueryKey.String(queryString)),
8276
)
8377

8478
return spanCtx, traceQueryFinishFunc(span)
@@ -93,9 +87,10 @@ func (t *otelTracer) TraceField(ctx context.Context, label, typeName, fieldName
9387
spanCtx, span := t.cfg.ResolveTracer(ctx).Start(
9488
ctx,
9589
"GraphQL field",
90+
oteltrace.WithSpanKind(oteltrace.SpanKindServer),
9691
oteltrace.WithAttributes(
97-
graphqlFieldKey.String(fieldName),
98-
graphqlTypeKey.String(typeName),
92+
gql.GraphQLFieldKey.String(fieldName),
93+
gql.GraphQLTypeKey.String(typeName),
9994
),
10095
)
10196

@@ -110,6 +105,10 @@ func (t *otelTracer) TraceField(ctx context.Context, label, typeName, fieldName
110105

111106
// TraceValidation traces the schema validation step preceding an operation.
112107
func (t *otelTracer) TraceValidation(ctx context.Context) trace.TraceValidationFinishFunc {
113-
_, span := t.cfg.ResolveTracer(ctx).Start(ctx, "GraphQL validation")
108+
_, span := t.cfg.ResolveTracer(ctx).Start(
109+
ctx,
110+
"GraphQL validation",
111+
oteltrace.WithSpanKind(oteltrace.SpanKindInternal),
112+
)
114113
return traceQueryFinishFunc(span)
115114
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright Splunk Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package internal
16+
17+
import "go.opentelemetry.io/otel/attribute"
18+
19+
// GraphQL attributes.
20+
var (
21+
GraphQLFieldKey = attribute.Key("graphql.field")
22+
GraphQLQueryKey = attribute.Key("graphql.query")
23+
GraphQLTypeKey = attribute.Key("graphql.type")
24+
)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module github.com/signalfx/splunk-otel-go/instrumentation/github.com/graph-gophers/graphql-go/splunkgraphql/test
2+
3+
go 1.16
4+
5+
require (
6+
github.com/graph-gophers/graphql-go v1.2.0
7+
github.com/signalfx/splunk-otel-go/instrumentation/github.com/graph-gophers/graphql-go/splunkgraphql v0.0.0-00010101000000-000000000000
8+
github.com/stretchr/testify v1.7.0
9+
go.opentelemetry.io/otel/sdk v1.3.0
10+
go.opentelemetry.io/otel/trace v1.3.0
11+
)
12+
13+
replace (
14+
github.com/signalfx/splunk-otel-go => ../../../../../../
15+
github.com/signalfx/splunk-otel-go/instrumentation/github.com/graph-gophers/graphql-go/splunkgraphql => ../
16+
)
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
2+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
4+
github.com/go-logr/logr v1.2.1 h1:DX7uPQ4WgAWfoh+NGGlbJQswnYIVvz0SRlLS3rPZQDA=
5+
github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
6+
github.com/go-logr/stdr v1.2.0 h1:j4LrlVXgrbIWO83mmQUnK0Hi+YnbD+vzrE1z/EphbFE=
7+
github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI=
8+
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
9+
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
10+
github.com/graph-gophers/graphql-go v1.2.0 h1:j3tCG0UcE+3f84OAw/4/6YQKyTr+r0yuUKtnxiu5OH4=
11+
github.com/graph-gophers/graphql-go v1.2.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc=
12+
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
13+
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
14+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
15+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
16+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
17+
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
18+
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
19+
go.opentelemetry.io/contrib/propagators/b3 v1.2.0/go.mod h1:kO8hNKCfa1YmQJ0lM7pzfJGvbXEipn/S7afbOfaw2Kc=
20+
go.opentelemetry.io/otel v1.2.0/go.mod h1:aT17Fk0Z1Nor9e0uisf98LrntPGMnk4frBO9+dkf69I=
21+
go.opentelemetry.io/otel v1.3.0 h1:APxLf0eiBwLl+SOXiJJCVYzA1OOJNyAoV8C5RNRyy7Y=
22+
go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs=
23+
go.opentelemetry.io/otel/exporters/jaeger v1.2.0/go.mod h1:KJLFbEMKTNPIfOxcg/WikIozEoKcPgJRz3Ce1vLlM8E=
24+
go.opentelemetry.io/otel/sdk v1.2.0/go.mod h1:jNN8QtpvbsKhgaC6V5lHiejMoKD+V8uadoSafgHPx1U=
25+
go.opentelemetry.io/otel/sdk v1.3.0 h1:3278edCoH89MEJ0Ky8WQXVmDQv3FX4ZJ3Pp+9fJreAI=
26+
go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs=
27+
go.opentelemetry.io/otel/trace v1.2.0/go.mod h1:N5FLswTubnxKxOJHM7XZC074qpeEdLy3CgAVsdMucK0=
28+
go.opentelemetry.io/otel/trace v1.3.0 h1:doy8Hzb1RJ+I3yFhtDmwNc7tIyw1tNMOIsyPzp1NOGY=
29+
go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk=
30+
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw=
31+
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
32+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
33+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
34+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
35+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
36+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// Copyright Splunk Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
/*
16+
Package test provides end-to-end testing of the splunkgraphql instrumentation
17+
with the default SDK.
18+
19+
This package is in a separate module from the instrumentation it tests to
20+
isolate the dependency of the default SDK and not impose this as a transitive
21+
dependency for users.
22+
*/
23+
package test
24+
25+
import (
26+
"context"
27+
"io"
28+
"net/http"
29+
"net/http/httptest"
30+
"strings"
31+
"testing"
32+
33+
"github.com/graph-gophers/graphql-go"
34+
"github.com/graph-gophers/graphql-go/relay"
35+
"github.com/signalfx/splunk-otel-go/instrumentation/github.com/graph-gophers/graphql-go/splunkgraphql"
36+
"github.com/stretchr/testify/assert"
37+
"github.com/stretchr/testify/require"
38+
"go.opentelemetry.io/otel/sdk/trace"
39+
"go.opentelemetry.io/otel/sdk/trace/tracetest"
40+
traceapi "go.opentelemetry.io/otel/trace"
41+
)
42+
43+
const testSchema = `
44+
schema {
45+
query: Query
46+
}
47+
type Query {
48+
hello: String!
49+
helloNonTrivial: String!
50+
}
51+
`
52+
53+
type testResolver struct{}
54+
55+
func (*testResolver) Hello() string { return "Hello, world!" }
56+
func (*testResolver) HelloNonTrivial() (string, error) { return "Hello, world!", nil }
57+
58+
func fixtures(t *testing.T) (*tracetest.SpanRecorder, *httptest.Server) {
59+
sr := tracetest.NewSpanRecorder()
60+
tp := trace.NewTracerProvider(trace.WithSpanProcessor(sr))
61+
t.Cleanup(func() { require.NoError(t, tp.Shutdown(context.Background())) })
62+
63+
tracer := graphql.Tracer(splunkgraphql.NewTracer(splunkgraphql.WithTracerProvider(tp)))
64+
schema := graphql.MustParseSchema(testSchema, new(testResolver), tracer)
65+
srv := httptest.NewServer(&relay.Handler{Schema: schema})
66+
t.Cleanup(srv.Close)
67+
68+
return sr, srv
69+
}
70+
71+
func TestTracerNonTrivial(t *testing.T) {
72+
sr, srv := fixtures(t)
73+
resp, err := http.Post(srv.URL, "application/json", strings.NewReader(`{
74+
"query": "query TestQuery() { hello, helloNonTrivial }",
75+
"operationName": "TestQuery"
76+
}`))
77+
require.NoError(t, err)
78+
t.Cleanup(func() { require.NoError(t, resp.Body.Close()) })
79+
body, err := io.ReadAll(resp.Body)
80+
require.NoError(t, err)
81+
assert.Equal(t, `{"data":{"hello":"Hello, world!","helloNonTrivial":"Hello, world!"}}`, string(body))
82+
83+
spans := sr.Ended()
84+
require.Len(t, spans, 3)
85+
assert.Equal(t, spans[2].SpanContext().TraceID(), spans[1].SpanContext().TraceID())
86+
87+
s := spans[0]
88+
assert.Equal(t, "GraphQL validation", s.Name())
89+
assert.Equal(t, traceapi.SpanKindInternal, s.SpanKind())
90+
// FIXME: validate the rest.
91+
92+
s = spans[1]
93+
assert.Equal(t, "GraphQL field", s.Name())
94+
assert.Equal(t, traceapi.SpanKindServer, s.SpanKind())
95+
// FIXME: validate the rest.
96+
97+
s = spans[2]
98+
assert.Equal(t, "GraphQL request", s.Name())
99+
assert.Equal(t, traceapi.SpanKindServer, s.SpanKind())
100+
// FIXME: validate the rest.
101+
}
102+
103+
func TestTracerTrivial(t *testing.T) {
104+
sr, srv := fixtures(t)
105+
resp, err := http.Post(srv.URL, "application/json", strings.NewReader(`{
106+
"query": "{ hello }"
107+
}`))
108+
require.NoError(t, err)
109+
t.Cleanup(func() { require.NoError(t, resp.Body.Close()) })
110+
body, err := io.ReadAll(resp.Body)
111+
require.NoError(t, err)
112+
assert.Equal(t, `{"data":{"hello":"Hello, world!"}}`, string(body))
113+
114+
spans := sr.Ended()
115+
require.Len(t, spans, 2)
116+
117+
// Trivial queries should not trace a field access.
118+
s0, s1 := spans[0], spans[1]
119+
assert.Equal(t, "GraphQL validation", s0.Name())
120+
assert.Equal(t, "GraphQL request", s1.Name())
121+
}

0 commit comments

Comments
 (0)