github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/util/tracing/tracer_test.go (about)

     1  // Copyright 2016 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package tracing
    12  
    13  import (
    14  	"testing"
    15  
    16  	"github.com/cockroachdb/logtags"
    17  	lightstep "github.com/lightstep/lightstep-tracer-go"
    18  	opentracing "github.com/opentracing/opentracing-go"
    19  )
    20  
    21  func TestTracerRecording(t *testing.T) {
    22  	tr := NewTracer()
    23  
    24  	noop1 := tr.StartSpan("noop")
    25  	if _, noop := noop1.(*noopSpan); !noop {
    26  		t.Error("expected noop span")
    27  	}
    28  	noop1.LogKV("hello", "void")
    29  
    30  	noop2 := tr.StartSpan("noop2", opentracing.ChildOf(noop1.Context()))
    31  	if _, noop := noop2.(*noopSpan); !noop {
    32  		t.Error("expected noop child span")
    33  	}
    34  	noop2.Finish()
    35  	noop1.Finish()
    36  
    37  	s1 := tr.StartSpan("a", Recordable)
    38  	if _, noop := s1.(*noopSpan); noop {
    39  		t.Error("Recordable (but not recording) span should not be noop")
    40  	}
    41  	if !IsBlackHoleSpan(s1) {
    42  		t.Error("Recordable span should be black hole")
    43  	}
    44  
    45  	// Unless recording is actually started, child spans are still noop.
    46  	noop3 := tr.StartSpan("noop3", opentracing.ChildOf(s1.Context()))
    47  	if _, noop := noop3.(*noopSpan); !noop {
    48  		t.Error("expected noop child span")
    49  	}
    50  	noop3.Finish()
    51  
    52  	s1.LogKV("x", 1)
    53  	StartRecording(s1, SingleNodeRecording)
    54  	s1.LogKV("x", 2)
    55  	s2 := tr.StartSpan("b", opentracing.ChildOf(s1.Context()))
    56  	if IsBlackHoleSpan(s2) {
    57  		t.Error("recording span should not be black hole")
    58  	}
    59  	s2.LogKV("x", 3)
    60  
    61  	if err := TestingCheckRecordedSpans(GetRecording(s1), `
    62  		span a:
    63  			tags: unfinished=
    64  			x: 2
    65  		span b:
    66  			tags: unfinished=
    67  			x: 3
    68  	`); err != nil {
    69  		t.Fatal(err)
    70  	}
    71  
    72  	if err := TestingCheckRecordedSpans(GetRecording(s2), `
    73  		span a:
    74  			tags: unfinished=
    75  			x: 2
    76  		span b:
    77  			tags: unfinished=
    78  			x: 3
    79  	`); err != nil {
    80  		t.Fatal(err)
    81  	}
    82  
    83  	s3 := tr.StartSpan("c", opentracing.FollowsFrom(s2.Context()))
    84  	s3.LogKV("x", 4)
    85  	s3.SetTag("tag", "val")
    86  
    87  	s2.Finish()
    88  
    89  	if err := TestingCheckRecordedSpans(GetRecording(s1), `
    90  		span a:
    91  			tags: unfinished=
    92  			x: 2
    93  		span b:
    94  			x: 3
    95  		span c:
    96  			tags: tag=val unfinished=
    97  			x: 4
    98  	`); err != nil {
    99  		t.Fatal(err)
   100  	}
   101  	s3.Finish()
   102  	if err := TestingCheckRecordedSpans(GetRecording(s1), `
   103  		span a:
   104        tags: unfinished=
   105  			x: 2
   106  		span b:
   107  			x: 3
   108  		span c:
   109  			tags: tag=val
   110  			x: 4
   111  	`); err != nil {
   112  		t.Fatal(err)
   113  	}
   114  	StopRecording(s1)
   115  	s1.LogKV("x", 100)
   116  	if err := TestingCheckRecordedSpans(GetRecording(s1), ``); err != nil {
   117  		t.Fatal(err)
   118  	}
   119  
   120  	// The child span is still recording.
   121  	s3.LogKV("x", 5)
   122  	if err := TestingCheckRecordedSpans(GetRecording(s3), `
   123  		span a:
   124  			tags: unfinished=
   125  			x: 2
   126  		span b:
   127  			x: 3
   128  		span c:
   129  			tags: tag=val
   130  			x: 4
   131  			x: 5
   132  	`); err != nil {
   133  		t.Fatal(err)
   134  	}
   135  	s1.Finish()
   136  }
   137  
   138  func TestStartChildSpan(t *testing.T) {
   139  	tr := NewTracer()
   140  	sp1 := tr.StartSpan("parent", Recordable)
   141  	StartRecording(sp1, SingleNodeRecording)
   142  	sp2 := StartChildSpan("child", sp1, nil /* logTags */, false /*separateRecording*/)
   143  	sp2.Finish()
   144  	sp1.Finish()
   145  	if err := TestingCheckRecordedSpans(GetRecording(sp1), `
   146  		span parent:
   147  			span child:
   148  	`); err != nil {
   149  		t.Fatal(err)
   150  	}
   151  
   152  	sp1 = tr.StartSpan("parent", Recordable)
   153  	StartRecording(sp1, SingleNodeRecording)
   154  	sp2 = StartChildSpan("child", sp1, nil /* logTags */, true /*separateRecording*/)
   155  	sp2.Finish()
   156  	sp1.Finish()
   157  	if err := TestingCheckRecordedSpans(GetRecording(sp1), `
   158  		span parent:
   159  	`); err != nil {
   160  		t.Fatal(err)
   161  	}
   162  	if err := TestingCheckRecordedSpans(GetRecording(sp2), `
   163  		span child:
   164  	`); err != nil {
   165  		t.Fatal(err)
   166  	}
   167  
   168  	sp1 = tr.StartSpan("parent", Recordable)
   169  	StartRecording(sp1, SingleNodeRecording)
   170  	sp2 = StartChildSpan(
   171  		"child", sp1, logtags.SingleTagBuffer("key", "val"), false, /*separateRecording*/
   172  	)
   173  	sp2.Finish()
   174  	sp1.Finish()
   175  	if err := TestingCheckRecordedSpans(GetRecording(sp1), `
   176  		span parent:
   177  			span child:
   178  				tags: key=val
   179  	`); err != nil {
   180  		t.Fatal(err)
   181  	}
   182  }
   183  
   184  func TestTracerInjectExtract(t *testing.T) {
   185  	tr := NewTracer()
   186  	tr2 := NewTracer()
   187  
   188  	// Verify that noop spans become noop spans on the remote side.
   189  
   190  	noop1 := tr.StartSpan("noop")
   191  	if _, noop := noop1.(*noopSpan); !noop {
   192  		t.Fatalf("expected noop span: %+v", noop1)
   193  	}
   194  	carrier := make(opentracing.HTTPHeadersCarrier)
   195  	if err := tr.Inject(noop1.Context(), opentracing.HTTPHeaders, carrier); err != nil {
   196  		t.Fatal(err)
   197  	}
   198  	if len(carrier) != 0 {
   199  		t.Errorf("noop span has carrier: %+v", carrier)
   200  	}
   201  
   202  	wireContext, err := tr2.Extract(opentracing.HTTPHeaders, carrier)
   203  	if err != nil {
   204  		t.Fatal(err)
   205  	}
   206  	if _, noopCtx := wireContext.(noopSpanContext); !noopCtx {
   207  		t.Errorf("expected noop context: %v", wireContext)
   208  	}
   209  	noop2 := tr2.StartSpan("remote op", opentracing.FollowsFrom(wireContext))
   210  	if _, noop := noop2.(*noopSpan); !noop {
   211  		t.Fatalf("expected noop span: %+v", noop2)
   212  	}
   213  	noop1.Finish()
   214  	noop2.Finish()
   215  
   216  	// Verify that snowball tracing is propagated and triggers recording on the
   217  	// remote side.
   218  
   219  	s1 := tr.StartSpan("a", Recordable)
   220  	StartRecording(s1, SnowballRecording)
   221  
   222  	carrier = make(opentracing.HTTPHeadersCarrier)
   223  	if err := tr.Inject(s1.Context(), opentracing.HTTPHeaders, carrier); err != nil {
   224  		t.Fatal(err)
   225  	}
   226  
   227  	wireContext, err = tr2.Extract(opentracing.HTTPHeaders, carrier)
   228  	if err != nil {
   229  		t.Fatal(err)
   230  	}
   231  	s2 := tr2.StartSpan("remote op", opentracing.FollowsFrom(wireContext))
   232  
   233  	// Compare TraceIDs
   234  	trace1 := s1.Context().(*spanContext).TraceID
   235  	trace2 := s2.Context().(*spanContext).TraceID
   236  	if trace1 != trace2 {
   237  		t.Errorf("TraceID doesn't match: parent %d child %d", trace1, trace2)
   238  	}
   239  	s2.LogKV("x", 1)
   240  	s2.Finish()
   241  
   242  	// Verify that recording was started automatically.
   243  	rec := GetRecording(s2)
   244  	if err := TestingCheckRecordedSpans(rec, `
   245  		span remote op:
   246  			tags: sb=1
   247  			x: 1
   248  	`); err != nil {
   249  		t.Fatal(err)
   250  	}
   251  
   252  	if err := TestingCheckRecordedSpans(GetRecording(s1), `
   253  		span a:
   254  			tags: sb=1 unfinished=
   255  	`); err != nil {
   256  		t.Fatal(err)
   257  	}
   258  
   259  	if err := ImportRemoteSpans(s1, rec); err != nil {
   260  		t.Fatal(err)
   261  	}
   262  	s1.Finish()
   263  
   264  	if err := TestingCheckRecordedSpans(GetRecording(s1), `
   265  		span a:
   266  			tags: sb=1
   267  		span remote op:
   268  			tags: sb=1
   269  			x: 1
   270  	`); err != nil {
   271  		t.Fatal(err)
   272  	}
   273  }
   274  
   275  func TestLightstepContext(t *testing.T) {
   276  	tr := NewTracer()
   277  	lsTr := lightstep.NewTracer(lightstep.Options{
   278  		AccessToken: "invalid",
   279  		Collector: lightstep.Endpoint{
   280  			Host:      "127.0.0.1",
   281  			Port:      65535,
   282  			Plaintext: true,
   283  		},
   284  		MaxLogsPerSpan: maxLogsPerSpan,
   285  		UseGRPC:        true,
   286  	})
   287  	tr.setShadowTracer(lightStepManager{}, lsTr)
   288  	s := tr.StartSpan("test")
   289  
   290  	const testBaggageKey = "test-baggage"
   291  	const testBaggageVal = "test-val"
   292  	s.SetBaggageItem(testBaggageKey, testBaggageVal)
   293  
   294  	carrier := make(opentracing.HTTPHeadersCarrier)
   295  	if err := tr.Inject(s.Context(), opentracing.HTTPHeaders, carrier); err != nil {
   296  		t.Fatal(err)
   297  	}
   298  
   299  	// Extract also extracts the embedded lightstep context.
   300  	wireContext, err := tr.Extract(opentracing.HTTPHeaders, carrier)
   301  	if err != nil {
   302  		t.Fatal(err)
   303  	}
   304  
   305  	s2 := tr.StartSpan("child", opentracing.FollowsFrom(wireContext))
   306  	s2Ctx := s2.(*span).shadowSpan.Context()
   307  
   308  	// Verify that the baggage is correct in both the tracer context and in the
   309  	// lightstep context.
   310  	for i, spanCtx := range []opentracing.SpanContext{s2.Context(), s2Ctx} {
   311  		baggage := make(map[string]string)
   312  		spanCtx.ForeachBaggageItem(func(k, v string) bool {
   313  			baggage[k] = v
   314  			return true
   315  		})
   316  		if len(baggage) != 1 || baggage[testBaggageKey] != testBaggageVal {
   317  			t.Errorf("%d: expected baggage %s=%s, got %v", i, testBaggageKey, testBaggageVal, baggage)
   318  		}
   319  	}
   320  }