Remove use of oteltest in otelrestful (#1003)

* Use Noop TracerProvider instead of oteltest

* Use tracetest instead of oteltest
This commit is contained in:
Tyler Yahn 2021-08-19 08:09:58 -07:00 committed by GitHub
parent df802af62a
commit 85719edb1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 290 additions and 157 deletions

View File

@ -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"

View File

@ -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=

View File

@ -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
)

View File

@ -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=

View File

@ -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)
}

View File

@ -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

View File

@ -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

View File

@ -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=

View File

@ -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)
}
}