package tracing import ( "context" "net/http" "net/http/httptest" "testing" "github.com/opentracing/opentracing-go/ext" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/traefik/traefik/v3/pkg/tracing" ) func TestNewForwarder(t *testing.T) { type expected struct { Tags map[string]interface{} OperationName string } testCases := []struct { desc string spanNameLimit int tracing *trackingBackenMock service string router string expected expected }{ { desc: "Simple Forward Tracer without truncation and hashing", spanNameLimit: 101, tracing: &trackingBackenMock{ tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]interface{})}}, }, service: "some-service.domain.tld", router: "some-service.domain.tld", expected: expected{ Tags: map[string]interface{}{ "http.host": "www.test.com", "http.method": "GET", "http.url": "http://www.test.com/toto", "traefik.service.name": "some-service.domain.tld", "traefik.router.name": "some-service.domain.tld", "span.kind": ext.SpanKindRPCClientEnum, }, OperationName: "forward some-service.domain.tld/some-service.domain.tld", }, }, { desc: "Simple Forward Tracer with truncation and hashing", spanNameLimit: 101, tracing: &trackingBackenMock{ tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]interface{})}}, }, service: "some-service-100.slug.namespace.environment.domain.tld", router: "some-service-100.slug.namespace.environment.domain.tld", expected: expected{ Tags: map[string]interface{}{ "http.host": "www.test.com", "http.method": "GET", "http.url": "http://www.test.com/toto", "traefik.service.name": "some-service-100.slug.namespace.environment.domain.tld", "traefik.router.name": "some-service-100.slug.namespace.environment.domain.tld", "span.kind": ext.SpanKindRPCClientEnum, }, OperationName: "forward some-service-100.slug.namespace.enviro.../some-service-100.slug.namespace.enviro.../bc4a0d48", }, }, { desc: "Exactly 101 chars", spanNameLimit: 101, tracing: &trackingBackenMock{ tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]interface{})}}, }, service: "some-service1.namespace.environment.domain.tld", router: "some-service1.namespace.environment.domain.tld", expected: expected{ Tags: map[string]interface{}{ "http.host": "www.test.com", "http.method": "GET", "http.url": "http://www.test.com/toto", "traefik.service.name": "some-service1.namespace.environment.domain.tld", "traefik.router.name": "some-service1.namespace.environment.domain.tld", "span.kind": ext.SpanKindRPCClientEnum, }, OperationName: "forward some-service1.namespace.environment.domain.tld/some-service1.namespace.environment.domain.tld", }, }, { desc: "More than 101 chars", spanNameLimit: 101, tracing: &trackingBackenMock{ tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]interface{})}}, }, service: "some-service1.frontend.namespace.environment.domain.tld", router: "some-service1.backend.namespace.environment.domain.tld", expected: expected{ Tags: map[string]interface{}{ "http.host": "www.test.com", "http.method": "GET", "http.url": "http://www.test.com/toto", "traefik.service.name": "some-service1.frontend.namespace.environment.domain.tld", "traefik.router.name": "some-service1.backend.namespace.environment.domain.tld", "span.kind": ext.SpanKindRPCClientEnum, }, OperationName: "forward some-service1.frontend.namespace.envir.../some-service1.backend.namespace.enviro.../fa49dd23", }, }, } for _, test := range testCases { t.Run(test.desc, func(t *testing.T) { newTracing, err := tracing.NewTracing("", test.spanNameLimit, test.tracing) require.NoError(t, err) req := httptest.NewRequest(http.MethodGet, "http://www.test.com/toto", nil) req = req.WithContext(tracing.WithTracing(req.Context(), newTracing)) rw := httptest.NewRecorder() next := http.HandlerFunc(func(http.ResponseWriter, *http.Request) { span := test.tracing.tracer.(*MockTracer).Span tags := span.Tags assert.Equal(t, test.expected.Tags, tags) assert.True(t, len(test.expected.OperationName) <= test.spanNameLimit, "the len of the operation name %q [len: %d] doesn't respect limit %d", test.expected.OperationName, len(test.expected.OperationName), test.spanNameLimit) assert.Equal(t, test.expected.OperationName, span.OpName) }) handler := NewForwarder(context.Background(), test.router, test.service, next) handler.ServeHTTP(rw, req) }) } }