package opencensus_test import ( "bytes" "context" "encoding/json" "errors" "fmt" "net/http" "net/http/httptest" "net/url" "testing" "go.opencensus.io/plugin/ochttp" "go.opencensus.io/plugin/ochttp/propagation/b3" "go.opencensus.io/plugin/ochttp/propagation/tracecontext" "go.opencensus.io/trace" "go.opencensus.io/trace/propagation" "github.com/go-kit/kit/endpoint" ockit "github.com/go-kit/kit/tracing/opencensus" jsonrpc "github.com/go-kit/kit/transport/http/jsonrpc" ) func TestJSONRPCClientTrace(t *testing.T) { t.Skip("FLAKY") var ( err error rec = &recordingExporter{} rURL, _ = url.Parse("https://httpbin.org/anything") endpointName = "DummyEndpoint" ) trace.RegisterExporter(rec) traces := []struct { name string err error }{ {"", nil}, {"CustomName", nil}, {"", errors.New("dummy-error")}, } for _, tr := range traces { clientTracer := ockit.JSONRPCClientTrace( ockit.WithName(tr.name), ockit.WithSampler(trace.AlwaysSample()), ) ep := jsonrpc.NewClient( rURL, endpointName, jsonrpc.ClientRequestEncoder(func(ctx context.Context, i interface{}) (json.RawMessage, error) { return json.RawMessage(`{}`), nil }), jsonrpc.ClientResponseDecoder(func(ctx context.Context, r jsonrpc.Response) (response interface{}, err error) { return nil, tr.err }), clientTracer, ).Endpoint() ctx, parentSpan := trace.StartSpan(context.Background(), "test") _, err = ep(ctx, nil) if want, have := tr.err, err; want != have { t.Fatalf("unexpected error, want %v, have %v", tr.err, err) } spans := rec.Flush() if want, have := 1, len(spans); want != have { t.Fatalf("incorrect number of spans, want %d, have %d", want, have) } span := spans[0] if want, have := parentSpan.SpanContext().SpanID, span.ParentSpanID; want != have { t.Errorf("incorrect parent ID, want %s, have %s", want, have) } if want, have := tr.name, span.Name; want != have && want != "" { t.Errorf("incorrect span name, want %s, have %s", want, have) } if want, have := endpointName, span.Name; want != have && tr.name == "" { t.Errorf("incorrect span name, want %s, have %s", want, have) } code := trace.StatusCodeOK if tr.err != nil { code = trace.StatusCodeUnknown if want, have := err.Error(), span.Status.Message; want != have { t.Errorf("incorrect span status msg, want %s, have %s", want, have) } } if want, have := int32(code), span.Status.Code; want != have { t.Errorf("incorrect span status code, want %d, have %d", want, have) } } } func TestJSONRPCServerTrace(t *testing.T) { var ( endpointName = "DummyEndpoint" rec = &recordingExporter{} ) trace.RegisterExporter(rec) traces := []struct { useParent bool name string err error propagation propagation.HTTPFormat }{ {false, "", nil, nil}, {true, "", nil, nil}, {true, "CustomName", nil, &b3.HTTPFormat{}}, {true, "", errors.New("dummy-error"), &tracecontext.HTTPFormat{}}, } for _, tr := range traces { var client http.Client handler := jsonrpc.NewServer( jsonrpc.EndpointCodecMap{ endpointName: jsonrpc.EndpointCodec{ Endpoint: endpoint.Nop, Decode: func(context.Context, json.RawMessage) (interface{}, error) { return nil, nil }, Encode: func(context.Context, interface{}) (json.RawMessage, error) { return nil, tr.err }, }, }, ockit.JSONRPCServerTrace( ockit.WithName(tr.name), ockit.WithSampler(trace.AlwaysSample()), ockit.WithHTTPPropagation(tr.propagation), ), ) server := httptest.NewServer(handler) defer server.Close() jsonStr := []byte(fmt.Sprintf(`{"method":"%s"}`, endpointName)) req, err := http.NewRequest("POST", server.URL, bytes.NewBuffer(jsonStr)) if err != nil { t.Fatalf("unable to create JSONRPC request: %v", err) } if tr.useParent { client = http.Client{ Transport: &ochttp.Transport{ StartOptions: trace.StartOptions{ Sampler: trace.AlwaysSample(), }, Propagation: tr.propagation, }, } } resp, err := client.Do(req.WithContext(context.Background())) if err != nil { t.Fatalf("unable to send JSONRPC request: %v", err) } resp.Body.Close() spans := rec.Flush() expectedSpans := 1 if tr.useParent { expectedSpans++ } if want, have := expectedSpans, len(spans); want != have { t.Fatalf("incorrect number of spans, want %d, have %d", want, have) } if tr.useParent { if want, have := spans[1].TraceID, spans[0].TraceID; want != have { t.Errorf("incorrect trace ID, want %s, have %s", want, have) } if want, have := spans[1].SpanID, spans[0].ParentSpanID; want != have { t.Errorf("incorrect span ID, want %s, have %s", want, have) } } if want, have := tr.name, spans[0].Name; want != have && want != "" { t.Errorf("incorrect span name, want %s, have %s", want, have) } if want, have := endpointName, spans[0].Name; want != have && tr.name == "" { t.Errorf("incorrect span name, want %s, have %s", want, have) } } }