github.com/icyphox/x@v0.0.355-0.20220311094250-029bd783e8b8/tracing/middleware_test.go (about)

     1  package tracing_test
     2  
     3  import (
     4  	"net/http"
     5  	"net/http/httptest"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/require"
     9  
    10  	opentracing "github.com/opentracing/opentracing-go"
    11  	"github.com/opentracing/opentracing-go/ext"
    12  	"github.com/opentracing/opentracing-go/mocktracer"
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/urfave/negroni"
    15  
    16  	"github.com/ory/x/tracing"
    17  )
    18  
    19  var mockedTracer *mocktracer.MockTracer
    20  var tracer = &tracing.Tracer{Config: &tracing.Config{
    21  	ServiceName: "Ory Hydra Test",
    22  	Provider:    "Mock Provider",
    23  }}
    24  
    25  func init() {
    26  	mockedTracer = mocktracer.New()
    27  	opentracing.SetGlobalTracer(mockedTracer)
    28  }
    29  
    30  func TestTracingServeHttp(t *testing.T) {
    31  	expectedTagsSuccess := map[string]interface{}{
    32  		string(ext.Component):      "Ory Hydra Test",
    33  		string(ext.SpanKind):       ext.SpanKindRPCServerEnum,
    34  		string(ext.HTTPMethod):     "GET",
    35  		string(ext.HTTPUrl):        "https://apis.somecompany.com/endpoint",
    36  		string(ext.HTTPStatusCode): uint16(200),
    37  	}
    38  
    39  	expectedTagsError := map[string]interface{}{
    40  		string(ext.Component):      "Ory Hydra Test",
    41  		string(ext.SpanKind):       ext.SpanKindRPCServerEnum,
    42  		string(ext.HTTPMethod):     "GET",
    43  		string(ext.HTTPUrl):        "https://apis.somecompany.com/endpoint",
    44  		string(ext.HTTPStatusCode): uint16(400),
    45  		string(ext.Error):          true,
    46  	}
    47  
    48  	testCases := []struct {
    49  		httpStatus      int
    50  		testDescription string
    51  		expectedTags    map[string]interface{}
    52  	}{
    53  		{
    54  			testDescription: "success http response",
    55  			httpStatus:      http.StatusOK,
    56  			expectedTags:    expectedTagsSuccess,
    57  		},
    58  		{
    59  			testDescription: "error http response",
    60  			httpStatus:      http.StatusBadRequest,
    61  			expectedTags:    expectedTagsError,
    62  		},
    63  	}
    64  
    65  	for _, test := range testCases {
    66  		t.Run(test.testDescription, func(t *testing.T) {
    67  			defer mockedTracer.Reset()
    68  			request := httptest.NewRequest(http.MethodGet, "https://apis.somecompany.com/endpoint", nil)
    69  			next := func(rw http.ResponseWriter, _ *http.Request) {
    70  				rw.WriteHeader(test.httpStatus)
    71  			}
    72  
    73  			tracer.ServeHTTP(negroni.NewResponseWriter(httptest.NewRecorder()), request, next)
    74  
    75  			spans := mockedTracer.FinishedSpans()
    76  			assert.Len(t, spans, 1)
    77  			span := spans[0]
    78  
    79  			assert.Equal(t, test.expectedTags, span.Tags())
    80  		})
    81  	}
    82  }
    83  
    84  func TestShouldContinueTraceIfAlreadyPresent(t *testing.T) {
    85  	defer mockedTracer.Reset()
    86  	parentSpan := mockedTracer.StartSpan("some-operation").(*mocktracer.MockSpan)
    87  	ext.SpanKindRPCClient.Set(parentSpan)
    88  	request := httptest.NewRequest(http.MethodGet, "https://apis.somecompany.com/endpoint", nil)
    89  	carrier := opentracing.HTTPHeadersCarrier(request.Header)
    90  	// this request now contains a trace initiated by another service/process (e.g. an edge proxy that fronts Hydra)
    91  	require.NoError(t, mockedTracer.Inject(parentSpan.Context(), opentracing.HTTPHeaders, carrier))
    92  
    93  	next := func(rw http.ResponseWriter, _ *http.Request) {
    94  		rw.WriteHeader(http.StatusOK)
    95  	}
    96  
    97  	tracer.ServeHTTP(negroni.NewResponseWriter(httptest.NewRecorder()), request, next)
    98  
    99  	spans := mockedTracer.FinishedSpans()
   100  	assert.Len(t, spans, 1)
   101  	span := spans[0]
   102  
   103  	assert.Equal(t, parentSpan.SpanContext.SpanID, span.ParentID)
   104  }
   105  
   106  func TestShouldNotTraceHealthEndpoint(t *testing.T) {
   107  	testCases := []struct {
   108  		path            string
   109  		testDescription string
   110  	}{
   111  		{
   112  			path:            "health/ready",
   113  			testDescription: "ready",
   114  		},
   115  		{
   116  			path:            "health/alive",
   117  			testDescription: "alive",
   118  		},
   119  	}
   120  	for _, test := range testCases {
   121  		t.Run(test.testDescription, func(t *testing.T) {
   122  			defer mockedTracer.Reset()
   123  			request := httptest.NewRequest(http.MethodGet, "https://apis.somecompany.com/"+test.path, nil)
   124  
   125  			next := func(rw http.ResponseWriter, _ *http.Request) {
   126  				rw.WriteHeader(http.StatusOK)
   127  			}
   128  
   129  			tracer.ServeHTTP(negroni.NewResponseWriter(httptest.NewRecorder()), request, next)
   130  
   131  			spans := mockedTracer.FinishedSpans()
   132  			assert.Len(t, spans, 0)
   133  		})
   134  	}
   135  }