github.com/mier85/go-sensor@v1.30.1-0.20220920111756-9bf41b3bc7e0/span_test.go (about) 1 // (c) Copyright IBM Corp. 2021 2 // (c) Copyright Instana Inc. 2017 3 4 package instana_test 5 6 import ( 7 "errors" 8 "testing" 9 "time" 10 11 "github.com/instana/testify/assert" 12 "github.com/instana/testify/require" 13 instana "github.com/mier85/go-sensor" 14 ot "github.com/opentracing/opentracing-go" 15 "github.com/opentracing/opentracing-go/ext" 16 "github.com/opentracing/opentracing-go/log" 17 ) 18 19 func TestBasicSpan(t *testing.T) { 20 recorder := instana.NewTestRecorder() 21 tracer := instana.NewTracerWithEverything(&instana.Options{}, recorder) 22 23 start := time.Now() 24 sp := tracer.StartSpan("test") 25 time.Sleep(10 * time.Millisecond) 26 sp.Finish() 27 elapsed := time.Since(start) 28 29 spans := recorder.GetQueuedSpans() 30 require.Len(t, spans, 1) 31 span := spans[0] 32 33 assert.NotEmpty(t, span.SpanID) 34 assert.NotEmpty(t, span.TraceID) 35 assert.NotEmpty(t, span.Timestamp) 36 assert.LessOrEqual(t, uint64(10), span.Duration) 37 assert.LessOrEqual(t, span.Duration, uint64(elapsed)) 38 assert.Equal(t, "sdk", span.Name) 39 40 require.IsType(t, instana.SDKSpanData{}, span.Data) 41 data := span.Data.(instana.SDKSpanData) 42 assert.Equal(t, TestServiceName, data.Service) 43 44 assert.Equal(t, "test", data.Tags.Name) 45 assert.Nil(t, data.Tags.Custom["tags"]) 46 assert.Nil(t, data.Tags.Custom["baggage"]) 47 } 48 49 func TestSpanHeritage(t *testing.T) { 50 recorder := instana.NewTestRecorder() 51 tracer := instana.NewTracerWithEverything(&instana.Options{}, recorder) 52 53 parentSpan := tracer.StartSpan("parent") 54 55 childSpan := tracer.StartSpan("child", ot.ChildOf(parentSpan.Context())) 56 childSpan.Finish() 57 58 parentSpan.Finish() 59 60 spans := recorder.GetQueuedSpans() 61 require.Len(t, spans, 2) 62 63 cSpan, pSpan := spans[0], spans[1] 64 65 // Parent should not have a parent 66 assert.Empty(t, pSpan.ParentID) 67 68 // Child must have parent ID set as parent 69 assert.Equal(t, pSpan.SpanID, cSpan.ParentID) 70 71 // Must be root span 72 assert.Equal(t, pSpan.TraceID, pSpan.SpanID) 73 74 // Trace ID must be consistent across spans 75 assert.Equal(t, cSpan.TraceID, pSpan.TraceID) 76 77 require.IsType(t, cSpan.Data, instana.SDKSpanData{}) 78 cData := cSpan.Data.(instana.SDKSpanData) 79 assert.Equal(t, "child", cData.Tags.Name) 80 81 require.IsType(t, pSpan.Data, instana.SDKSpanData{}) 82 pData := pSpan.Data.(instana.SDKSpanData) 83 assert.Equal(t, "parent", pData.Tags.Name) 84 } 85 86 func TestSpanBaggage(t *testing.T) { 87 const op = "test" 88 recorder := instana.NewTestRecorder() 89 tracer := instana.NewTracerWithEverything(&instana.Options{}, recorder) 90 91 sp := tracer.StartSpan(op) 92 sp.SetBaggageItem("foo", "bar") 93 sp.Finish() 94 95 spans := recorder.GetQueuedSpans() 96 require.Len(t, spans, 1) 97 span := spans[0] 98 99 require.IsType(t, instana.SDKSpanData{}, span.Data) 100 data := span.Data.(instana.SDKSpanData) 101 102 assert.Equal(t, map[string]string{"foo": "bar"}, data.Tags.Custom["baggage"]) 103 } 104 105 func TestSpanTags(t *testing.T) { 106 const op = "test" 107 recorder := instana.NewTestRecorder() 108 tracer := instana.NewTracerWithEverything(&instana.Options{}, recorder) 109 110 sp := tracer.StartSpan(op) 111 sp.SetTag("foo", "bar") 112 sp.Finish() 113 114 spans := recorder.GetQueuedSpans() 115 require.Len(t, spans, 1) 116 span := spans[0] 117 118 require.IsType(t, instana.SDKSpanData{}, span.Data) 119 data := span.Data.(instana.SDKSpanData) 120 121 assert.Equal(t, ot.Tags{"foo": "bar"}, data.Tags.Custom["tags"]) 122 } 123 124 func TestOTLogError(t *testing.T) { 125 recorder := instana.NewTestRecorder() 126 tracer := instana.NewTracerWithEverything(&instana.Options{}, recorder) 127 128 sp := tracer.StartSpan("test") 129 ext.Error.Set(sp, true) 130 sp.Finish() 131 132 spans := recorder.GetQueuedSpans() 133 require.Equal(t, len(spans), 1) 134 135 span := spans[0] 136 assert.Equal(t, 1, span.Ec) 137 138 require.IsType(t, instana.SDKSpanData{}, span.Data) 139 data := span.Data.(instana.SDKSpanData) 140 141 assert.Equal(t, map[string]interface{}{ 142 "tags": ot.Tags{"error": true}, 143 }, data.Tags.Custom) 144 } 145 146 func TestSpanErrorLogKV(t *testing.T) { 147 recorder := instana.NewTestRecorder() 148 tracer := instana.NewTracerWithEverything(&instana.Options{}, recorder) 149 150 sp := tracer.StartSpan("test") 151 sp.LogKV("error", "simulated error") 152 sp.Finish() 153 154 spans := recorder.GetQueuedSpans() 155 require.Len(t, spans, 2) 156 157 span, logSpan := spans[0], spans[1] 158 assert.Equal(t, 1, span.Ec) 159 160 assert.Equal(t, span.TraceID, logSpan.TraceID) 161 assert.Equal(t, span.SpanID, logSpan.ParentID) 162 assert.Equal(t, "log.go", logSpan.Name) 163 164 // assert that log message has been recorded within the span interval 165 assert.GreaterOrEqual(t, logSpan.Timestamp, span.Timestamp) 166 assert.LessOrEqual(t, logSpan.Duration, span.Duration) 167 168 require.IsType(t, instana.LogSpanData{}, logSpan.Data) 169 logData := logSpan.Data.(instana.LogSpanData) 170 171 assert.Equal(t, instana.LogSpanTags{ 172 Level: "ERROR", 173 Message: `error: "simulated error"`, 174 }, logData.Tags) 175 } 176 177 func TestSpan_LogFields(t *testing.T) { 178 recorder := instana.NewTestRecorder() 179 tracer := instana.NewTracerWithEverything(&instana.Options{}, recorder) 180 181 examples := map[string]struct { 182 Fields []log.Field 183 ExpectedErrorCount int 184 ExpectedTags instana.LogSpanTags 185 }{ 186 "error object": { 187 Fields: []log.Field{ 188 log.Error(errors.New("simulated error")), 189 log.String("function", "ErrorFunc"), 190 }, 191 ExpectedErrorCount: 1, 192 ExpectedTags: instana.LogSpanTags{ 193 Level: "ERROR", 194 Message: `error: "simulated error" function: "ErrorFunc"`, 195 }, 196 }, 197 "error log": { 198 Fields: []log.Field{ 199 log.String("error", "simulated error"), 200 log.String("function", "ErrorFunc"), 201 }, 202 ExpectedErrorCount: 1, 203 ExpectedTags: instana.LogSpanTags{ 204 Level: "ERROR", 205 Message: `error: "simulated error" function: "ErrorFunc"`, 206 }, 207 }, 208 "warn log": { 209 Fields: []log.Field{ 210 log.String("warn", "simulated warning"), 211 log.String("function", "WarnFunc"), 212 }, 213 ExpectedTags: instana.LogSpanTags{ 214 Level: "WARN", 215 Message: `warn: "simulated warning" function: "WarnFunc"`, 216 }, 217 }, 218 } 219 220 for name, example := range examples { 221 t.Run(name, func(t *testing.T) { 222 sp := tracer.StartSpan("test") 223 sp.LogFields(example.Fields...) 224 sp.Finish() 225 226 spans := recorder.GetQueuedSpans() 227 require.Len(t, spans, 2) 228 229 span, logSpan := spans[0], spans[1] 230 assert.Equal(t, example.ExpectedErrorCount, span.Ec) 231 232 assert.Equal(t, span.TraceID, logSpan.TraceID) 233 assert.Equal(t, span.SpanID, logSpan.ParentID) 234 assert.Equal(t, "log.go", logSpan.Name) 235 236 // assert that log message has been recorded within the span interval 237 assert.GreaterOrEqual(t, logSpan.Timestamp, span.Timestamp) 238 assert.LessOrEqual(t, logSpan.Duration, span.Duration) 239 240 require.IsType(t, instana.LogSpanData{}, logSpan.Data) 241 logData := logSpan.Data.(instana.LogSpanData) 242 243 assert.Equal(t, example.ExpectedTags, logData.Tags) 244 }) 245 } 246 } 247 248 func TestSpan_Suppressed_StartSpanOption(t *testing.T) { 249 recorder := instana.NewTestRecorder() 250 tracer := instana.NewTracerWithEverything(&instana.Options{}, recorder) 251 252 sp := tracer.StartSpan("test", instana.SuppressTracing()) 253 sp.Finish() 254 255 assert.Empty(t, recorder.GetQueuedSpans()) 256 } 257 258 func TestSpan_Suppressed_SetTag(t *testing.T) { 259 recorder := instana.NewTestRecorder() 260 tracer := instana.NewTracerWithEverything(&instana.Options{}, recorder) 261 262 sp := tracer.StartSpan("test") 263 instana.SuppressTracing().Set(sp) 264 sp.Finish() 265 266 assert.Empty(t, recorder.GetQueuedSpans()) 267 }