Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add linter rules to prevent uses of the SDK in bridges and instrumentations #6145

Merged
merged 10 commits into from
Sep 25, 2024
10 changes: 10 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,16 @@ issues:
linters-settings:
depguard:
rules:
no-sdk-instrumentation:
files:
- "**/*/{bridges,instrumentation}/**/*.go"
- "!**/*test/*.go"
- "!**/*test/**/*.go"
- "!**/*example/*.go"
- "!**/*example/**/*.go"
dmathieu marked this conversation as resolved.
Show resolved Hide resolved
deny:
- pkg: go.opentelemetry.io/otel/sdk
desc: "Bridges and instrumentations should not use the SDKs, except in test or example modules"
non-tests:
files:
- "!$test"
Expand Down
2 changes: 1 addition & 1 deletion bridges/prometheus/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package prometheus_test

import (
"go.opentelemetry.io/contrib/bridges/prometheus"
"go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/metric" //nolint:depguard
)

func ExampleNewMetricProducer() {
Expand Down
6 changes: 3 additions & 3 deletions bridges/prometheus/producer.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ import (

"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/sdk/instrumentation"
"go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/metric/metricdata"
"go.opentelemetry.io/otel/sdk/instrumentation" //nolint:depguard
"go.opentelemetry.io/otel/sdk/metric" //nolint:depguard
"go.opentelemetry.io/otel/sdk/metric/metricdata" //nolint:depguard
)

const (
Expand Down
6 changes: 3 additions & 3 deletions bridges/prometheus/producer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import (
"github.com/stretchr/testify/require"

"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/sdk/instrumentation"
"go.opentelemetry.io/otel/sdk/metric/metricdata"
"go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest"
"go.opentelemetry.io/otel/sdk/instrumentation" //nolint:depguard
"go.opentelemetry.io/otel/sdk/metric/metricdata" //nolint:depguard
"go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" //nolint:depguard
)

const (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"go.opentelemetry.io/contrib/propagators/aws/xray"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
"go.opentelemetry.io/otel/propagation"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
sdktrace "go.opentelemetry.io/otel/sdk/trace" //nolint:depguard // NewTracerProvider requires the SDK
)

func xrayEventToCarrier([]byte) propagation.TextMapCarrier {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,14 @@ require (
github.com/stretchr/testify v1.9.0
go.opentelemetry.io/contrib/propagators/b3 v1.30.0
go.opentelemetry.io/otel v1.30.0
go.opentelemetry.io/otel/sdk v1.30.0
go.opentelemetry.io/otel/trace v1.30.0
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go.opentelemetry.io/otel/metric v1.30.0 // indirect
golang.org/x/sys v0.25.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
Expand All @@ -19,12 +17,8 @@ go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts=
go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc=
go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w=
go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ=
go.opentelemetry.io/otel/sdk v1.30.0 h1:cHdik6irO49R5IysVhdn8oaiR9m8XluDaJAs4DfOrYE=
go.opentelemetry.io/otel/sdk v1.30.0/go.mod h1:p14X4Ok8S+sygzblytT1nqG98QG2KYKv++HE0LY/mhg=
go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc=
go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,11 @@ import (

"github.com/emicklei/go-restful/v3"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful"
b3prop "go.opentelemetry.io/contrib/propagators/b3"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/propagation"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
"go.opentelemetry.io/otel/sdk/trace/tracetest"
oteltrace "go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/otel/trace/noop"
)
Expand Down Expand Up @@ -111,145 +108,3 @@ func TestPropagationWithCustomPropagators(t *testing.T) {

container.ServeHTTP(w, r)
}

func TestWithPublicEndpoint(t *testing.T) {
spanRecorder := tracetest.NewSpanRecorder()
provider := sdktrace.NewTracerProvider(
sdktrace.WithSpanProcessor(spanRecorder),
)
remoteSpan := oteltrace.SpanContextConfig{
TraceID: oteltrace.TraceID{0x01},
SpanID: oteltrace.SpanID{0x01},
Remote: true,
}
prop := propagation.TraceContext{}

handlerFunc := func(req *restful.Request, resp *restful.Response) {
s := oteltrace.SpanFromContext(req.Request.Context())
sc := s.SpanContext()

// Should be with new root trace.
assert.True(t, sc.IsValid())
assert.False(t, sc.IsRemote())
assert.NotEqual(t, remoteSpan.TraceID, sc.TraceID())
}

ws := &restful.WebService{}
ws.Route(ws.GET("/user/{id}").To(handlerFunc))

container := restful.NewContainer()
container.Filter(otelrestful.OTelFilter("test_handler",
otelrestful.WithPublicEndpoint(),
otelrestful.WithPropagators(prop),
otelrestful.WithTracerProvider(provider)),
)
container.Add(ws)

r, err := http.NewRequest(http.MethodGet, "http://localhost/user/123", nil)
require.NoError(t, err)

sc := oteltrace.NewSpanContext(remoteSpan)
ctx := oteltrace.ContextWithSpanContext(context.Background(), sc)
prop.Inject(ctx, propagation.HeaderCarrier(r.Header))

rr := httptest.NewRecorder()
container.ServeHTTP(rr, r)
assert.Equal(t, 200, rr.Result().StatusCode) //nolint:bodyclose // False positive for httptest.ResponseRecorder: https://github.com/timakin/bodyclose/issues/59.

// Recorded span should be linked with an incoming span context.
assert.NoError(t, spanRecorder.ForceFlush(ctx))
done := spanRecorder.Ended()
require.Len(t, done, 1)
require.Len(t, done[0].Links(), 1, "should contain link")
require.True(t, sc.Equal(done[0].Links()[0].SpanContext), "should link incoming span context")
}

func TestWithPublicEndpointFn(t *testing.T) {
remoteSpan := oteltrace.SpanContextConfig{
TraceID: oteltrace.TraceID{0x01},
SpanID: oteltrace.SpanID{0x01},
TraceFlags: oteltrace.FlagsSampled,
Remote: true,
}
prop := propagation.TraceContext{}

for _, tt := range []struct {
name string
fn func(*http.Request) bool
handlerAssert func(*testing.T, oteltrace.SpanContext)
spansAssert func(*testing.T, oteltrace.SpanContext, []sdktrace.ReadOnlySpan)
}{
{
name: "with the method returning true",
fn: func(r *http.Request) bool {
return true
},
handlerAssert: func(t *testing.T, sc oteltrace.SpanContext) {
// Should be with new root trace.
assert.True(t, sc.IsValid())
assert.False(t, sc.IsRemote())
assert.NotEqual(t, remoteSpan.TraceID, sc.TraceID())
},
spansAssert: func(t *testing.T, sc oteltrace.SpanContext, spans []sdktrace.ReadOnlySpan) {
require.Len(t, spans, 1)
require.Len(t, spans[0].Links(), 1, "should contain link")
require.True(t, sc.Equal(spans[0].Links()[0].SpanContext), "should link incoming span context")
},
},
{
name: "with the method returning false",
fn: func(r *http.Request) bool {
return false
},
handlerAssert: func(t *testing.T, sc oteltrace.SpanContext) {
// Should have remote span as parent
assert.True(t, sc.IsValid())
assert.False(t, sc.IsRemote())
assert.Equal(t, remoteSpan.TraceID, sc.TraceID())
},
spansAssert: func(t *testing.T, _ oteltrace.SpanContext, spans []sdktrace.ReadOnlySpan) {
require.Len(t, spans, 1)
require.Empty(t, spans[0].Links(), "should not contain link")
},
},
} {
t.Run(tt.name, func(t *testing.T) {
spanRecorder := tracetest.NewSpanRecorder()
provider := sdktrace.NewTracerProvider(
sdktrace.WithSpanProcessor(spanRecorder),
)

handlerFunc := func(req *restful.Request, resp *restful.Response) {
s := oteltrace.SpanFromContext(req.Request.Context())
tt.handlerAssert(t, s.SpanContext())
}

ws := &restful.WebService{}
ws.Route(ws.GET("/user/{id}").To(handlerFunc))

container := restful.NewContainer()
container.Filter(otelrestful.OTelFilter("test_handler",
otelrestful.WithPublicEndpointFn(tt.fn),
otelrestful.WithPropagators(prop),
otelrestful.WithTracerProvider(provider)),
)
container.Add(ws)

r, err := http.NewRequest(http.MethodGet, "http://localhost/user/123", nil)
require.NoError(t, err)

sc := oteltrace.NewSpanContext(remoteSpan)
ctx := oteltrace.ContextWithSpanContext(context.Background(), sc)
prop.Inject(ctx, propagation.HeaderCarrier(r.Header))

rr := httptest.NewRecorder()
container.ServeHTTP(rr, r)
assert.Equal(t, http.StatusOK, rr.Result().StatusCode) //nolint:bodyclose // False positive for httptest.ResponseRecorder: https://github.com/timakin/bodyclose/issues/59.

// Recorded span should be linked with an incoming span context.
assert.NoError(t, spanRecorder.ForceFlush(ctx))
spans := spanRecorder.Ended()
tt.spansAssert(t, sc, spans)
})
}
}
Loading
Loading