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  }