github.com/snowflakedb/gosnowflake@v1.9.0/telemetry_test.go (about)

     1  // Copyright (c) 2021-2022 Snowflake Computing Inc. All rights reserved.
     2  
     3  package gosnowflake
     4  
     5  import (
     6  	"context"
     7  	"errors"
     8  	"math/rand"
     9  	"net/http"
    10  	"net/url"
    11  	"sync"
    12  	"testing"
    13  	"time"
    14  )
    15  
    16  func TestTelemetryAddLog(t *testing.T) {
    17  	runSnowflakeConnTest(t, func(sct *SCTest) {
    18  		st := &snowflakeTelemetry{
    19  			sr:        sct.sc.rest,
    20  			mutex:     &sync.Mutex{},
    21  			enabled:   true,
    22  			flushSize: defaultFlushSize,
    23  		}
    24  		rand.Seed(time.Now().UnixNano())
    25  		randNum := rand.Int() % 10000
    26  		for i := 0; i < randNum; i++ {
    27  			if err := st.addLog(&telemetryData{
    28  				Message: map[string]string{
    29  					typeKey:    "client_telemetry_type",
    30  					queryIDKey: "123",
    31  				},
    32  				Timestamp: time.Now().UnixNano() / int64(time.Millisecond),
    33  			}); err != nil {
    34  				t.Fatal(err)
    35  			}
    36  		}
    37  		if len(st.logs) != randNum%defaultFlushSize {
    38  			t.Errorf("length of remaining logs does not match. expected: %v, got: %v",
    39  				randNum%defaultFlushSize, len(st.logs))
    40  		}
    41  		if err := st.sendBatch(); err != nil {
    42  			t.Fatal(err)
    43  		}
    44  	})
    45  }
    46  
    47  func TestTelemetrySQLException(t *testing.T) {
    48  	runSnowflakeConnTest(t, func(sct *SCTest) {
    49  		sct.sc.telemetry = &snowflakeTelemetry{
    50  			sr:        sct.sc.rest,
    51  			mutex:     &sync.Mutex{},
    52  			enabled:   true,
    53  			flushSize: defaultFlushSize,
    54  		}
    55  		sfa := &snowflakeFileTransferAgent{
    56  			sc:          sct.sc,
    57  			commandType: uploadCommand,
    58  			srcFiles:    make([]string, 0),
    59  			data: &execResponseData{
    60  				SrcLocations: make([]string, 0),
    61  			},
    62  		}
    63  		if err := sfa.initFileMetadata(); err == nil {
    64  			t.Fatal("this should have thrown an error")
    65  		}
    66  		if len(sct.sc.telemetry.logs) != 1 {
    67  			t.Errorf("there should be 1 telemetry data in log. found: %v", len(sct.sc.telemetry.logs))
    68  		}
    69  		if sendErr := sct.sc.telemetry.sendBatch(); sendErr != nil {
    70  			t.Fatal(sendErr)
    71  		}
    72  		if len(sct.sc.telemetry.logs) != 0 {
    73  			t.Errorf("there should be no telemetry data in log. found: %v", len(sct.sc.telemetry.logs))
    74  		}
    75  	})
    76  }
    77  
    78  func TestDisableTelemetry(t *testing.T) {
    79  	config, err := ParseDSN(dsn)
    80  	if err != nil {
    81  		t.Error(err)
    82  	}
    83  	config.DisableTelemetry = true
    84  	sc, err := buildSnowflakeConn(context.Background(), *config)
    85  	if err != nil {
    86  		t.Fatal(err)
    87  	}
    88  	if err = authenticateWithConfig(sc); err != nil {
    89  		t.Fatal(err)
    90  	}
    91  	if !sc.cfg.DisableTelemetry {
    92  		t.Errorf("DisableTelemetry should be true. DisableTelemetry: %v", sc.cfg.DisableTelemetry)
    93  	}
    94  	if sc.telemetry.enabled {
    95  		t.Errorf("telemetry should be disabled.")
    96  	}
    97  }
    98  
    99  func TestEnableTelemetry(t *testing.T) {
   100  	runSnowflakeConnTest(t, func(sct *SCTest) {
   101  		if sct.sc.cfg.DisableTelemetry {
   102  			t.Errorf("DisableTelemetry should be false. DisableTelemetry: %v", sct.sc.cfg.DisableTelemetry)
   103  		}
   104  		if !sct.sc.telemetry.enabled {
   105  			t.Errorf("telemetry should be enabled.")
   106  		}
   107  	})
   108  }
   109  
   110  func funcPostTelemetryRespFail(_ context.Context, _ *snowflakeRestful, _ *url.URL, _ map[string]string, _ []byte, _ time.Duration, _ currentTimeProvider, _ *Config) (*http.Response, error) {
   111  	return nil, errors.New("failed to upload metrics to telemetry")
   112  }
   113  
   114  func TestTelemetryError(t *testing.T) {
   115  	runSnowflakeConnTest(t, func(sct *SCTest) {
   116  		st := &snowflakeTelemetry{
   117  			sr: &snowflakeRestful{
   118  				FuncPost:      funcPostTelemetryRespFail,
   119  				TokenAccessor: getSimpleTokenAccessor(),
   120  			},
   121  			mutex:     &sync.Mutex{},
   122  			enabled:   true,
   123  			flushSize: defaultFlushSize,
   124  		}
   125  
   126  		if err := st.addLog(&telemetryData{
   127  			Message: map[string]string{
   128  				typeKey:    "client_telemetry_type",
   129  				queryIDKey: "123",
   130  			},
   131  			Timestamp: time.Now().UnixNano() / int64(time.Millisecond),
   132  		}); err != nil {
   133  			t.Fatal(err)
   134  		}
   135  
   136  		err := st.sendBatch()
   137  		if err == nil {
   138  			t.Fatal("should have failed")
   139  		}
   140  	})
   141  }
   142  
   143  func TestTelemetryDisabledOnBadResponse(t *testing.T) {
   144  	runSnowflakeConnTest(t, func(sct *SCTest) {
   145  		st := &snowflakeTelemetry{
   146  			sr: &snowflakeRestful{
   147  				FuncPost:      postTestAppBadGatewayError,
   148  				TokenAccessor: getSimpleTokenAccessor(),
   149  			},
   150  			mutex:     &sync.Mutex{},
   151  			enabled:   true,
   152  			flushSize: defaultFlushSize,
   153  		}
   154  
   155  		if err := st.addLog(&telemetryData{
   156  			Message: map[string]string{
   157  				typeKey:    "client_telemetry_type",
   158  				queryIDKey: "123",
   159  			},
   160  			Timestamp: time.Now().UnixNano() / int64(time.Millisecond),
   161  		}); err != nil {
   162  			t.Fatal(err)
   163  		}
   164  		err := st.sendBatch()
   165  		if err == nil {
   166  			t.Fatal("should have failed")
   167  		}
   168  		if st.enabled == true {
   169  			t.Fatal("telemetry should be disabled")
   170  		}
   171  
   172  		st.enabled = true
   173  		st.sr.FuncPost = postTestQueryNotExecuting
   174  		if err = st.addLog(&telemetryData{
   175  			Message: map[string]string{
   176  				typeKey:    "client_telemetry_type",
   177  				queryIDKey: "123",
   178  			},
   179  			Timestamp: time.Now().UnixNano() / int64(time.Millisecond),
   180  		}); err != nil {
   181  			t.Fatal(err)
   182  		}
   183  		err = st.sendBatch()
   184  		if err == nil {
   185  			t.Fatal("should have failed")
   186  		}
   187  		if st.enabled == true {
   188  			t.Fatal("telemetry should be disabled")
   189  		}
   190  
   191  		st.enabled = true
   192  		st.sr.FuncPost = postTestSuccessButInvalidJSON
   193  		if err = st.addLog(&telemetryData{
   194  			Message: map[string]string{
   195  				typeKey:    "client_telemetry_type",
   196  				queryIDKey: "123",
   197  			},
   198  			Timestamp: time.Now().UnixNano() / int64(time.Millisecond),
   199  		}); err != nil {
   200  			t.Fatal(err)
   201  		}
   202  		err = st.sendBatch()
   203  		if err == nil {
   204  			t.Fatal("should have failed")
   205  		}
   206  		if st.enabled == true {
   207  			t.Fatal("telemetry should be disabled")
   208  		}
   209  	})
   210  }
   211  
   212  func TestTelemetryDisabled(t *testing.T) {
   213  	runSnowflakeConnTest(t, func(sct *SCTest) {
   214  		st := &snowflakeTelemetry{
   215  			sr: &snowflakeRestful{
   216  				FuncPost:      postTestAppBadGatewayError,
   217  				TokenAccessor: getSimpleTokenAccessor(),
   218  			},
   219  			mutex:     &sync.Mutex{},
   220  			enabled:   false, // disable
   221  			flushSize: defaultFlushSize,
   222  		}
   223  		if err := st.addLog(&telemetryData{
   224  			Message: map[string]string{
   225  				typeKey:    "client_telemetry_type",
   226  				queryIDKey: "123",
   227  			},
   228  			Timestamp: time.Now().UnixNano() / int64(time.Millisecond),
   229  		}); err == nil {
   230  			t.Fatal("should have failed")
   231  		}
   232  		st.enabled = true
   233  		if err := st.addLog(&telemetryData{
   234  			Message: map[string]string{
   235  				typeKey:    "client_telemetry_type",
   236  				queryIDKey: "123",
   237  			},
   238  			Timestamp: time.Now().UnixNano() / int64(time.Millisecond),
   239  		}); err != nil {
   240  			t.Fatal(err)
   241  		}
   242  		st.enabled = false
   243  		err := st.sendBatch()
   244  		if err == nil {
   245  			t.Fatal("should have failed")
   246  		}
   247  	})
   248  }
   249  
   250  func TestAddLogError(t *testing.T) {
   251  	runSnowflakeConnTest(t, func(sct *SCTest) {
   252  		st := &snowflakeTelemetry{
   253  			sr: &snowflakeRestful{
   254  				FuncPost:      funcPostTelemetryRespFail,
   255  				TokenAccessor: getSimpleTokenAccessor(),
   256  			},
   257  			mutex:     &sync.Mutex{},
   258  			enabled:   true,
   259  			flushSize: 1,
   260  		}
   261  
   262  		if err := st.addLog(&telemetryData{
   263  			Message: map[string]string{
   264  				typeKey:    "client_telemetry_type",
   265  				queryIDKey: "123",
   266  			},
   267  			Timestamp: time.Now().UnixNano() / int64(time.Millisecond),
   268  		}); err == nil {
   269  			t.Fatal("should have failed")
   270  		}
   271  	})
   272  }