github.com/mier85/go-sensor@v1.30.1-0.20220920111756-9bf41b3bc7e0/instrumentation_sql_go1.10_test.go (about)

     1  // (c) Copyright IBM Corp. 2021
     2  // (c) Copyright Instana Inc. 2020
     3  
     4  //go:build go1.10
     5  // +build go1.10
     6  
     7  package instana_test
     8  
     9  import (
    10  	"context"
    11  	"database/sql"
    12  	"database/sql/driver"
    13  	"errors"
    14  	"testing"
    15  
    16  	"github.com/instana/testify/assert"
    17  	"github.com/instana/testify/require"
    18  	instana "github.com/mier85/go-sensor"
    19  	ot "github.com/opentracing/opentracing-go"
    20  	"github.com/opentracing/opentracing-go/ext"
    21  )
    22  
    23  func TestWrapSQLConnector_Exec(t *testing.T) {
    24  	recorder := instana.NewTestRecorder()
    25  	s := instana.NewSensorWithTracer(instana.NewTracerWithEverything(&instana.Options{
    26  		Service: "go-sensor-test",
    27  	}, recorder))
    28  
    29  	db := sql.OpenDB(instana.WrapSQLConnector(s, "connection string", sqlConnector{}))
    30  
    31  	res, err := db.Exec("TEST QUERY")
    32  	require.NoError(t, err)
    33  
    34  	lastID, err := res.LastInsertId()
    35  	require.NoError(t, err)
    36  	assert.Equal(t, int64(42), lastID)
    37  
    38  	spans := recorder.GetQueuedSpans()
    39  	require.Len(t, spans, 1)
    40  
    41  	span := spans[0]
    42  	assert.Equal(t, 0, span.Ec)
    43  	assert.EqualValues(t, instana.ExitSpanKind, span.Kind)
    44  
    45  	require.IsType(t, instana.SDKSpanData{}, span.Data)
    46  	data := span.Data.(instana.SDKSpanData)
    47  
    48  	assert.Equal(t, instana.SDKSpanTags{
    49  		Name: "sdk.database",
    50  		Type: "exit",
    51  		Custom: map[string]interface{}{
    52  			"tags": ot.Tags{
    53  				"span.kind":    ext.SpanKindRPCClientEnum,
    54  				"db.instance":  "connection string",
    55  				"db.statement": "TEST QUERY",
    56  				"db.type":      "sql",
    57  				"peer.address": "connection string",
    58  			},
    59  		},
    60  	}, data.Tags)
    61  }
    62  
    63  func TestWrapSQLConnector_Exec_Error(t *testing.T) {
    64  	recorder := instana.NewTestRecorder()
    65  	s := instana.NewSensorWithTracer(instana.NewTracerWithEverything(&instana.Options{
    66  		Service: "go-sensor-test",
    67  	}, recorder))
    68  
    69  	db := sql.OpenDB(instana.WrapSQLConnector(s, "connection string", sqlConnector{
    70  		Error: errors.New("something went wrong"),
    71  	}))
    72  
    73  	_, err := db.Exec("TEST QUERY")
    74  	assert.Error(t, err)
    75  
    76  	spans := recorder.GetQueuedSpans()
    77  	require.Len(t, spans, 2)
    78  
    79  	span, logSpan := spans[0], spans[1]
    80  	assert.Equal(t, 1, span.Ec)
    81  	assert.EqualValues(t, instana.ExitSpanKind, span.Kind)
    82  
    83  	require.IsType(t, instana.SDKSpanData{}, span.Data)
    84  
    85  	assert.Equal(t, span.TraceID, logSpan.TraceID)
    86  	assert.Equal(t, span.SpanID, logSpan.ParentID)
    87  	assert.Equal(t, "log.go", logSpan.Name)
    88  
    89  	// assert that log message has been recorded within the span interval
    90  	assert.GreaterOrEqual(t, logSpan.Timestamp, span.Timestamp)
    91  	assert.LessOrEqual(t, logSpan.Duration, span.Duration)
    92  
    93  	require.IsType(t, instana.LogSpanData{}, logSpan.Data)
    94  	logData := logSpan.Data.(instana.LogSpanData)
    95  
    96  	assert.Equal(t, instana.LogSpanTags{
    97  		Level:   "ERROR",
    98  		Message: `error: "something went wrong"`,
    99  	}, logData.Tags)
   100  }
   101  
   102  func TestWrapSQLConnector_Query(t *testing.T) {
   103  	recorder := instana.NewTestRecorder()
   104  	s := instana.NewSensorWithTracer(instana.NewTracerWithEverything(&instana.Options{
   105  		Service: "go-sensor-test",
   106  	}, recorder))
   107  
   108  	db := sql.OpenDB(instana.WrapSQLConnector(s, "connection string", sqlConnector{}))
   109  
   110  	res, err := db.Query("TEST QUERY")
   111  	require.NoError(t, err)
   112  
   113  	cols, err := res.Columns()
   114  	require.NoError(t, err)
   115  	assert.Equal(t, []string{"col1", "col2"}, cols)
   116  
   117  	spans := recorder.GetQueuedSpans()
   118  	require.Len(t, spans, 1)
   119  
   120  	span := spans[0]
   121  	assert.Equal(t, 0, span.Ec)
   122  	assert.EqualValues(t, instana.ExitSpanKind, span.Kind)
   123  
   124  	require.IsType(t, instana.SDKSpanData{}, span.Data)
   125  	data := span.Data.(instana.SDKSpanData)
   126  
   127  	assert.Equal(t, instana.SDKSpanTags{
   128  		Name: "sdk.database",
   129  		Type: "exit",
   130  		Custom: map[string]interface{}{
   131  			"tags": ot.Tags{
   132  				"span.kind":    ext.SpanKindRPCClientEnum,
   133  				"db.instance":  "connection string",
   134  				"db.statement": "TEST QUERY",
   135  				"db.type":      "sql",
   136  				"peer.address": "connection string",
   137  			},
   138  		},
   139  	}, data.Tags)
   140  }
   141  
   142  func TestWrapSQLConnector_Query_Error(t *testing.T) {
   143  	recorder := instana.NewTestRecorder()
   144  	s := instana.NewSensorWithTracer(instana.NewTracerWithEverything(&instana.Options{
   145  		Service: "go-sensor-test",
   146  	}, recorder))
   147  
   148  	dbErr := errors.New("something went wrong")
   149  	db := sql.OpenDB(instana.WrapSQLConnector(s, "connection string", sqlConnector{
   150  		Error: dbErr,
   151  	}))
   152  
   153  	_, err := db.Query("TEST QUERY")
   154  	assert.Error(t, err)
   155  
   156  	spans := recorder.GetQueuedSpans()
   157  	require.Len(t, spans, 2)
   158  
   159  	span, logSpan := spans[0], spans[1]
   160  	assert.Equal(t, 1, span.Ec)
   161  	assert.EqualValues(t, instana.ExitSpanKind, span.Kind)
   162  
   163  	require.IsType(t, instana.SDKSpanData{}, span.Data)
   164  
   165  	assert.Equal(t, span.TraceID, logSpan.TraceID)
   166  	assert.Equal(t, span.SpanID, logSpan.ParentID)
   167  	assert.Equal(t, "log.go", logSpan.Name)
   168  
   169  	// assert that log message has been recorded within the span interval
   170  	assert.GreaterOrEqual(t, logSpan.Timestamp, span.Timestamp)
   171  	assert.LessOrEqual(t, logSpan.Duration, span.Duration)
   172  
   173  	require.IsType(t, instana.LogSpanData{}, logSpan.Data)
   174  	logData := logSpan.Data.(instana.LogSpanData)
   175  
   176  	assert.Equal(t, instana.LogSpanTags{
   177  		Level:   "ERROR",
   178  		Message: `error: "something went wrong"`,
   179  	}, logData.Tags)
   180  }
   181  
   182  type sqlConnector struct{ Error error }
   183  
   184  func (c sqlConnector) Connect(context.Context) (driver.Conn, error) { return sqlConn{c.Error}, nil } //nolint:gosimple
   185  func (sqlConnector) Driver() driver.Driver                          { return sqlDriver{} }