diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 4f4dbec0879..a8b058d20fb 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -205,6 +205,16 @@ updates: schedule: interval: "weekly" day: "sunday" + - + package-ecosystem: "gomod" + directory: "/instrumentation/github.com/emicklei/go-restful/otelrestful/test" + labels: + - dependencies + - go + - "Skip Changelog" + schedule: + interval: "weekly" + day: "sunday" - package-ecosystem: "gomod" directory: "/instrumentation/github.com/gin-gonic/gin/otelgin" diff --git a/instrumentation/github.com/emicklei/go-restful/otelrestful/example/go.sum b/instrumentation/github.com/emicklei/go-restful/otelrestful/example/go.sum index 77c97bb3e7b..56876d8e2cd 100644 --- a/instrumentation/github.com/emicklei/go-restful/otelrestful/example/go.sum +++ b/instrumentation/github.com/emicklei/go-restful/otelrestful/example/go.sum @@ -22,8 +22,6 @@ go.opentelemetry.io/otel v1.0.0-RC2 h1:SHhxSjB+omnGZPgGlKe+QMp3MyazcOHdQ8qwo89oK go.opentelemetry.io/otel v1.0.0-RC2/go.mod h1:w1thVQ7qbAy8MHb0IFj8a5Q2QU0l2ksf8u/CN8m3NOM= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.0-RC2 h1:crksoFyTPDDywRJDUW36OZma+C3HhcYwQLPUZZMXFO0= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.0-RC2/go.mod h1:6kVxj1C/f3irP/IeeZNbcEwbg3rwnM6a7bCrcGbIJeI= -go.opentelemetry.io/otel/oteltest v1.0.0-RC2 h1:xNKqMhlZYkASSyvF4JwObZFMq0jhFN3c3SP+2rCzVPk= -go.opentelemetry.io/otel/oteltest v1.0.0-RC2/go.mod h1:kiQ4tw5tAL4JLTbcOYwK1CWI1HkT5aiLzHovgOVnz/A= go.opentelemetry.io/otel/sdk v1.0.0-RC2 h1:ROuteeSCBaZNjiT9JcFzZepmInDvLktR28Y6qKo8bCs= go.opentelemetry.io/otel/sdk v1.0.0-RC2/go.mod h1:fgwHyiDn4e5k40TD9VX243rOxXR+jzsWBZYA2P5jpEw= go.opentelemetry.io/otel/trace v1.0.0-RC2 h1:dunAP0qDULMIT82atj34m5RgvsIK6LcsXf1c/MsYg1w= diff --git a/instrumentation/github.com/emicklei/go-restful/otelrestful/go.mod b/instrumentation/github.com/emicklei/go-restful/otelrestful/go.mod index fa9f66cb461..de4e78bb247 100644 --- a/instrumentation/github.com/emicklei/go-restful/otelrestful/go.mod +++ b/instrumentation/github.com/emicklei/go-restful/otelrestful/go.mod @@ -14,6 +14,5 @@ require ( go.opentelemetry.io/contrib v0.22.0 go.opentelemetry.io/contrib/propagators/b3 v0.22.0 go.opentelemetry.io/otel v1.0.0-RC2 - go.opentelemetry.io/otel/oteltest v1.0.0-RC2 go.opentelemetry.io/otel/trace v1.0.0-RC2 ) diff --git a/instrumentation/github.com/emicklei/go-restful/otelrestful/go.sum b/instrumentation/github.com/emicklei/go-restful/otelrestful/go.sum index d057e011cb7..803d4d8696c 100644 --- a/instrumentation/github.com/emicklei/go-restful/otelrestful/go.sum +++ b/instrumentation/github.com/emicklei/go-restful/otelrestful/go.sum @@ -20,8 +20,6 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= go.opentelemetry.io/otel v1.0.0-RC2 h1:SHhxSjB+omnGZPgGlKe+QMp3MyazcOHdQ8qwo89oKbg= go.opentelemetry.io/otel v1.0.0-RC2/go.mod h1:w1thVQ7qbAy8MHb0IFj8a5Q2QU0l2ksf8u/CN8m3NOM= -go.opentelemetry.io/otel/oteltest v1.0.0-RC2 h1:xNKqMhlZYkASSyvF4JwObZFMq0jhFN3c3SP+2rCzVPk= -go.opentelemetry.io/otel/oteltest v1.0.0-RC2/go.mod h1:kiQ4tw5tAL4JLTbcOYwK1CWI1HkT5aiLzHovgOVnz/A= go.opentelemetry.io/otel/trace v1.0.0-RC2 h1:dunAP0qDULMIT82atj34m5RgvsIK6LcsXf1c/MsYg1w= go.opentelemetry.io/otel/trace v1.0.0-RC2/go.mod h1:JPQ+z6nNw9mqEGT8o3eoPTdnNI+Aj5JcxEsVGREIAy4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= diff --git a/instrumentation/github.com/emicklei/go-restful/otelrestful/restful_test.go b/instrumentation/github.com/emicklei/go-restful/otelrestful/restful_test.go index 9cc689daa5b..ffb9ed0f91e 100644 --- a/instrumentation/github.com/emicklei/go-restful/otelrestful/restful_test.go +++ b/instrumentation/github.com/emicklei/go-restful/otelrestful/restful_test.go @@ -22,112 +22,16 @@ 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" - otelkv "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/oteltest" "go.opentelemetry.io/otel/propagation" oteltrace "go.opentelemetry.io/otel/trace" ) const tracerName = "go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful" -func TestChildSpanFromGlobalTracer(t *testing.T) { - otel.SetTracerProvider(oteltest.NewTracerProvider()) - - handlerFunc := func(req *restful.Request, resp *restful.Response) { - span := oteltrace.SpanFromContext(req.Request.Context()) - _, ok := span.(*oteltest.Span) - assert.True(t, ok) - resp.WriteHeader(http.StatusOK) - } - ws := &restful.WebService{} - ws.Route(ws.GET("/user/{id}").To(handlerFunc). - Returns(200, "OK", nil). - Returns(404, "Not Found", nil)) - container := restful.NewContainer() - container.Filter(otelrestful.OTelFilter("my-service")) - container.Add(ws) - - r := httptest.NewRequest("GET", "/user/123", nil) - w := httptest.NewRecorder() - - container.ServeHTTP(w, r) -} - -func TestChildSpanFromCustomTracer(t *testing.T) { - provider := oteltest.NewTracerProvider() - - handlerFunc := func(req *restful.Request, resp *restful.Response) { - span := oteltrace.SpanFromContext(req.Request.Context()) - _, ok := span.(*oteltest.Span) - assert.True(t, ok) - resp.WriteHeader(http.StatusOK) - } - ws := &restful.WebService{} - ws.Route(ws.GET("/user/{id}").To(handlerFunc)) - - container := restful.NewContainer() - container.Filter(otelrestful.OTelFilter("my-service", otelrestful.WithTracerProvider(provider))) - container.Add(ws) - - r := httptest.NewRequest("GET", "/user/123", nil) - w := httptest.NewRecorder() - - container.ServeHTTP(w, r) -} - -func TestChildSpanNames(t *testing.T) { - sr := new(oteltest.SpanRecorder) - provider := oteltest.NewTracerProvider(oteltest.WithSpanRecorder(sr)) - - handlerFunc := func(req *restful.Request, resp *restful.Response) { - resp.WriteHeader(http.StatusOK) - } - ws := &restful.WebService{} - ws.Route(ws.GET("/user/{id:[0-9]+}").To(handlerFunc)) - - container := restful.NewContainer() - container.Filter(otelrestful.OTelFilter("foobar", otelrestful.WithTracerProvider(provider))) - container.Add(ws) - - ws.Route(ws.GET("/book/{title}").To(func(req *restful.Request, resp *restful.Response) { - _, _ = resp.Write(([]byte)("ok")) - })) - - r := httptest.NewRequest("GET", "/user/123", nil) - w := httptest.NewRecorder() - - container.ServeHTTP(w, r) - spans := sr.Completed() - require.Len(t, spans, 1) - span := spans[0] - assert.Equal(t, "/user/{id:[0-9]+}", span.Name()) - assert.Equal(t, oteltrace.SpanKindServer, span.SpanKind()) - assert.Equal(t, otelkv.StringValue("foobar"), span.Attributes()["http.server_name"]) - assert.Equal(t, otelkv.IntValue(http.StatusOK), span.Attributes()["http.status_code"]) - assert.Equal(t, otelkv.StringValue("GET"), span.Attributes()["http.method"]) - assert.Equal(t, otelkv.StringValue("/user/123"), span.Attributes()["http.target"]) - assert.Equal(t, otelkv.StringValue("/user/{id:[0-9]+}"), span.Attributes()["http.route"]) - - r = httptest.NewRequest("GET", "/book/foo", nil) - w = httptest.NewRecorder() - container.ServeHTTP(w, r) - spans = sr.Completed() - require.Len(t, spans, 2) - span = spans[1] - assert.Equal(t, "/book/{title}", span.Name()) - assert.Equal(t, oteltrace.SpanKindServer, span.SpanKind()) - assert.Equal(t, otelkv.StringValue("foobar"), span.Attributes()["http.server_name"]) - assert.Equal(t, otelkv.IntValue(http.StatusOK), span.Attributes()["http.status_code"]) - assert.Equal(t, otelkv.StringValue("GET"), span.Attributes()["http.method"]) - assert.Equal(t, otelkv.StringValue("/book/foo"), span.Attributes()["http.target"]) - assert.Equal(t, otelkv.StringValue("/book/{title}"), span.Attributes()["http.route"]) -} - func TestGetSpanNotInstrumented(t *testing.T) { handlerFunc := func(req *restful.Request, resp *restful.Response) { span := oteltrace.SpanFromContext(req.Request.Context()) @@ -147,21 +51,28 @@ func TestGetSpanNotInstrumented(t *testing.T) { } func TestPropagationWithGlobalPropagators(t *testing.T) { - provider := oteltest.NewTracerProvider() + defer func(p propagation.TextMapPropagator) { + otel.SetTextMapPropagator(p) + }(otel.GetTextMapPropagator()) + provider := oteltrace.NewNoopTracerProvider() otel.SetTextMapPropagator(propagation.TraceContext{}) r := httptest.NewRequest("GET", "/user/123", nil) w := httptest.NewRecorder() - ctx, pspan := provider.Tracer(tracerName).Start(context.Background(), "test") + ctx := context.Background() + sc := oteltrace.NewSpanContext(oteltrace.SpanContextConfig{ + TraceID: oteltrace.TraceID{0x01}, + SpanID: oteltrace.SpanID{0x01}, + }) + ctx = oteltrace.ContextWithRemoteSpanContext(ctx, sc) + ctx, _ = provider.Tracer(tracerName).Start(ctx, "test") otel.GetTextMapPropagator().Inject(ctx, propagation.HeaderCarrier(r.Header)) handlerFunc := func(req *restful.Request, resp *restful.Response) { span := oteltrace.SpanFromContext(req.Request.Context()) - mspan, ok := span.(*oteltest.Span) - require.True(t, ok) - assert.Equal(t, pspan.SpanContext().TraceID(), mspan.SpanContext().TraceID()) - assert.Equal(t, pspan.SpanContext().SpanID(), mspan.ParentSpanID()) + assert.Equal(t, sc.TraceID(), span.SpanContext().TraceID()) + assert.Equal(t, sc.SpanID(), span.SpanContext().SpanID()) w.WriteHeader(http.StatusOK) } ws := &restful.WebService{} @@ -172,25 +83,28 @@ func TestPropagationWithGlobalPropagators(t *testing.T) { container.Add(ws) container.ServeHTTP(w, r) - otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator()) } func TestPropagationWithCustomPropagators(t *testing.T) { - provider := oteltest.NewTracerProvider() + provider := oteltrace.NewNoopTracerProvider() b3 := b3prop.New() r := httptest.NewRequest("GET", "/user/123", nil) w := httptest.NewRecorder() - ctx, pspan := provider.Tracer(tracerName).Start(context.Background(), "test") + ctx := context.Background() + sc := oteltrace.NewSpanContext(oteltrace.SpanContextConfig{ + TraceID: oteltrace.TraceID{0x01}, + SpanID: oteltrace.SpanID{0x01}, + }) + ctx = oteltrace.ContextWithRemoteSpanContext(ctx, sc) + ctx, _ = provider.Tracer(tracerName).Start(ctx, "test") b3.Inject(ctx, propagation.HeaderCarrier(r.Header)) handlerFunc := func(req *restful.Request, resp *restful.Response) { span := oteltrace.SpanFromContext(req.Request.Context()) - mspan, ok := span.(*oteltest.Span) - require.True(t, ok) - assert.Equal(t, pspan.SpanContext().TraceID(), mspan.SpanContext().TraceID()) - assert.Equal(t, pspan.SpanContext().SpanID(), mspan.ParentSpanID()) + assert.Equal(t, sc.TraceID(), span.SpanContext().TraceID()) + assert.Equal(t, sc.SpanID(), span.SpanContext().SpanID()) w.WriteHeader(http.StatusOK) } ws := &restful.WebService{} @@ -204,46 +118,3 @@ func TestPropagationWithCustomPropagators(t *testing.T) { container.ServeHTTP(w, r) } - -func TestMultiFilters(t *testing.T) { - sr := new(oteltest.SpanRecorder) - provider := oteltest.NewTracerProvider(oteltest.WithSpanRecorder(sr)) - - wrappedFunc := func(tracerName string) restful.RouteFunction { - return func(req *restful.Request, resp *restful.Response) { - span := oteltrace.SpanFromContext(req.Request.Context()) - _, ok := span.(*oteltest.Span) - assert.True(t, ok) - resp.WriteHeader(http.StatusOK) - } - } - ws1 := &restful.WebService{} - ws1.Path("/user") - ws1.Route(ws1.GET("/{id}"). - Filter(otelrestful.OTelFilter("my-service", otelrestful.WithTracerProvider(provider))). - To(wrappedFunc(tracerName))) - ws1.Route(ws1.GET("/{id}/books"). - Filter(otelrestful.OTelFilter("book-service", otelrestful.WithTracerProvider(provider))). - To(wrappedFunc(tracerName))) - - ws2 := &restful.WebService{} - ws2.Path("/library") - ws2.Filter(otelrestful.OTelFilter("library-service", otelrestful.WithTracerProvider(provider))) - ws2.Route(ws2.GET("/{name}").To(wrappedFunc(tracerName))) - - container := restful.NewContainer() - container.Add(ws1) - container.Add(ws2) - - r := httptest.NewRequest("GET", "/user/123", nil) - w := httptest.NewRecorder() - container.ServeHTTP(w, r) - - r = httptest.NewRequest("GET", "/user/123/books", nil) - w = httptest.NewRecorder() - container.ServeHTTP(w, r) - - r = httptest.NewRequest("GET", "/library/metropolitan", nil) - w = httptest.NewRecorder() - container.ServeHTTP(w, r) -} diff --git a/instrumentation/github.com/emicklei/go-restful/otelrestful/test/doc.go b/instrumentation/github.com/emicklei/go-restful/otelrestful/test/doc.go new file mode 100644 index 00000000000..376ea336f33 --- /dev/null +++ b/instrumentation/github.com/emicklei/go-restful/otelrestful/test/doc.go @@ -0,0 +1,22 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* +Package test validates the otelrestful instrumentation with the default SDK. + +This package is in a separate module from the instrumentation it tests to +isolate the dependency of the default SDK and not impose this as a transitive +dependency for users. +*/ +package test diff --git a/instrumentation/github.com/emicklei/go-restful/otelrestful/test/go.mod b/instrumentation/github.com/emicklei/go-restful/otelrestful/test/go.mod new file mode 100644 index 00000000000..27a079f1089 --- /dev/null +++ b/instrumentation/github.com/emicklei/go-restful/otelrestful/test/go.mod @@ -0,0 +1,16 @@ +module go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful/test + +go 1.15 + +require ( + github.com/emicklei/go-restful/v3 v3.5.2 + github.com/stretchr/testify v1.7.0 + go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful v0.22.0 + go.opentelemetry.io/otel v1.0.0-RC2.0.20210812161231-a8bb0bf89f3b + go.opentelemetry.io/otel/sdk v1.0.0-RC2.0.20210812161231-a8bb0bf89f3b + go.opentelemetry.io/otel/trace v1.0.0-RC2 +) + +replace go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful => ../ + +replace go.opentelemetry.io/contrib/propagators/b3 => ../../../../../../propagators/b3 diff --git a/instrumentation/github.com/emicklei/go-restful/otelrestful/test/go.sum b/instrumentation/github.com/emicklei/go-restful/otelrestful/test/go.sum new file mode 100644 index 00000000000..31b846cb489 --- /dev/null +++ b/instrumentation/github.com/emicklei/go-restful/otelrestful/test/go.sum @@ -0,0 +1,37 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emicklei/go-restful/v3 v3.5.2 h1:RCNMSbcGIVafG4ZfgIXIEHTaV59ZRsi41IvZ7RC9+ls= +github.com/emicklei/go-restful/v3 v3.5.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +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/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +go.opentelemetry.io/contrib v0.22.0 h1:0F7gDEjgb1WGn4ODIjaCAg75hmqF+UN0LiVgwxsCodc= +go.opentelemetry.io/contrib v0.22.0/go.mod h1:EH4yDYeNoaTqn/8yCWQmfNB78VHfGX2Jt2bvnvzBlGM= +go.opentelemetry.io/otel v1.0.0-RC2/go.mod h1:w1thVQ7qbAy8MHb0IFj8a5Q2QU0l2ksf8u/CN8m3NOM= +go.opentelemetry.io/otel v1.0.0-RC2.0.20210812161231-a8bb0bf89f3b h1:mVdpWpFdeOeGPCpwO95rocgtrkE12gZhDU4LA9K9TNE= +go.opentelemetry.io/otel v1.0.0-RC2.0.20210812161231-a8bb0bf89f3b/go.mod h1:WrhiZahmIBdsXGO6mYjS6eW6kZzI/9GfGHFpRi8X/Yg= +go.opentelemetry.io/otel/sdk v1.0.0-RC2.0.20210812161231-a8bb0bf89f3b h1:3L//VzNirHuL0jZSmHFeQOIdGvNmSsfnl4g9UV6ZRcI= +go.opentelemetry.io/otel/sdk v1.0.0-RC2.0.20210812161231-a8bb0bf89f3b/go.mod h1:RiCEArosW4fWBJshjrl1H4IAzoRwI0sIqfqac5ramT8= +go.opentelemetry.io/otel/trace v1.0.0-RC2 h1:dunAP0qDULMIT82atj34m5RgvsIK6LcsXf1c/MsYg1w= +go.opentelemetry.io/otel/trace v1.0.0-RC2/go.mod h1:JPQ+z6nNw9mqEGT8o3eoPTdnNI+Aj5JcxEsVGREIAy4= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +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.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/instrumentation/github.com/emicklei/go-restful/otelrestful/test/restful_test.go b/instrumentation/github.com/emicklei/go-restful/otelrestful/test/restful_test.go new file mode 100644 index 00000000000..fa838666d50 --- /dev/null +++ b/instrumentation/github.com/emicklei/go-restful/otelrestful/test/restful_test.go @@ -0,0 +1,182 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package test + +import ( + "net/http" + "net/http/httptest" + "testing" + + "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" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + "go.opentelemetry.io/otel/sdk/trace/tracetest" + oteltrace "go.opentelemetry.io/otel/trace" +) + +func TestChildSpanFromGlobalTracer(t *testing.T) { + sr := tracetest.NewSpanRecorder() + otel.SetTracerProvider(sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr))) + + handlerFunc := func(req *restful.Request, resp *restful.Response) { + resp.WriteHeader(http.StatusOK) + } + ws := &restful.WebService{} + ws.Route(ws.GET("/user/{id}").To(handlerFunc). + Returns(200, "OK", nil). + Returns(404, "Not Found", nil)) + container := restful.NewContainer() + container.Filter(otelrestful.OTelFilter("my-service")) + container.Add(ws) + + r := httptest.NewRequest("GET", "/user/123", nil) + w := httptest.NewRecorder() + + container.ServeHTTP(w, r) + assert.Len(t, sr.Ended(), 1) +} + +func TestChildSpanFromCustomTracer(t *testing.T) { + sr := tracetest.NewSpanRecorder() + provider := sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) + + handlerFunc := func(req *restful.Request, resp *restful.Response) { + resp.WriteHeader(http.StatusOK) + } + ws := &restful.WebService{} + ws.Route(ws.GET("/user/{id}").To(handlerFunc)) + + container := restful.NewContainer() + container.Filter(otelrestful.OTelFilter("my-service", otelrestful.WithTracerProvider(provider))) + container.Add(ws) + + r := httptest.NewRequest("GET", "/user/123", nil) + w := httptest.NewRecorder() + + container.ServeHTTP(w, r) + assert.Len(t, sr.Ended(), 1) +} + +func TestChildSpanNames(t *testing.T) { + sr := tracetest.NewSpanRecorder() + provider := sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) + + handlerFunc := func(req *restful.Request, resp *restful.Response) { + resp.WriteHeader(http.StatusOK) + } + ws := &restful.WebService{} + ws.Route(ws.GET("/user/{id:[0-9]+}").To(handlerFunc)) + + container := restful.NewContainer() + container.Filter(otelrestful.OTelFilter("foobar", otelrestful.WithTracerProvider(provider))) + container.Add(ws) + + ws.Route(ws.GET("/book/{title}").To(func(req *restful.Request, resp *restful.Response) { + _, _ = resp.Write(([]byte)("ok")) + })) + + r := httptest.NewRequest("GET", "/user/123", nil) + w := httptest.NewRecorder() + + container.ServeHTTP(w, r) + spans := sr.Ended() + require.Len(t, spans, 1) + assertSpan( + t, + spans[0], + "/user/{id:[0-9]+}", + attribute.String("http.server_name", "foobar"), + attribute.Int("http.status_code", http.StatusOK), + attribute.String("http.method", "GET"), + attribute.String("http.target", "/user/123"), + attribute.String("http.route", "/user/{id:[0-9]+}"), + ) + + r = httptest.NewRequest("GET", "/book/foo", nil) + w = httptest.NewRecorder() + container.ServeHTTP(w, r) + spans = sr.Ended() + require.Len(t, spans, 2) + assertSpan( + t, + spans[1], + "/book/{title}", + attribute.String("http.server_name", "foobar"), + attribute.Int("http.status_code", http.StatusOK), + attribute.String("http.method", "GET"), + attribute.String("http.target", "/book/foo"), + attribute.String("http.route", "/book/{title}"), + ) +} + +func TestMultiFilters(t *testing.T) { + sr := tracetest.NewSpanRecorder() + provider := sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) + + retOK := func(req *restful.Request, resp *restful.Response) { resp.WriteHeader(http.StatusOK) } + ws1 := &restful.WebService{} + ws1.Path("/user") + ws1.Route(ws1.GET("/{id}"). + Filter(otelrestful.OTelFilter("my-service", otelrestful.WithTracerProvider(provider))). + To(retOK)) + ws1.Route(ws1.GET("/{id}/books"). + Filter(otelrestful.OTelFilter("book-service", otelrestful.WithTracerProvider(provider))). + To(retOK)) + + ws2 := &restful.WebService{} + ws2.Path("/library") + ws2.Filter(otelrestful.OTelFilter("library-service", otelrestful.WithTracerProvider(provider))) + ws2.Route(ws2.GET("/{name}").To(retOK)) + + container := restful.NewContainer() + container.Add(ws1) + container.Add(ws2) + + r := httptest.NewRequest("GET", "/user/123", nil) + w := httptest.NewRecorder() + container.ServeHTTP(w, r) + spans := sr.Ended() + require.Len(t, spans, 1) + assertSpan(t, spans[0], "/user/{id}") + + r = httptest.NewRequest("GET", "/user/123/books", nil) + w = httptest.NewRecorder() + container.ServeHTTP(w, r) + spans = sr.Ended() + require.Len(t, spans, 2) + assertSpan(t, spans[1], "/user/{id}/books") + + r = httptest.NewRequest("GET", "/library/metropolitan", nil) + w = httptest.NewRecorder() + container.ServeHTTP(w, r) + spans = sr.Ended() + require.Len(t, spans, 3) + assertSpan(t, spans[2], "/library/{name}") +} + +func assertSpan(t *testing.T, span sdktrace.ReadOnlySpan, name string, attrs ...attribute.KeyValue) { + assert.Equal(t, name, span.Name()) + assert.Equal(t, oteltrace.SpanKindServer, span.SpanKind()) + + gotA := span.Attributes() + for _, a := range attrs { + assert.Contains(t, gotA, a) + } +}