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 }