gitlab.com/gitlab-org/labkit@v1.21.0/monitoring/profiler_test.go (about) 1 // +build continuous_profiler_stackdriver 2 3 package monitoring 4 5 import ( 6 "bytes" 7 "fmt" 8 "os" 9 "testing" 10 11 "cloud.google.com/go/profiler" 12 "github.com/stretchr/testify/require" 13 "gitlab.com/gitlab-org/labkit/log" 14 "google.golang.org/api/option" 15 ) 16 17 func TestInitProfiler(t *testing.T) { 18 tests := []struct { 19 name string 20 envParams string 21 writeEnvVar bool 22 opts profilerOpts 23 expectedLog string 24 profErr error 25 expectedConfig profiler.Config 26 expectedOptions []option.ClientOption 27 }{ 28 { 29 name: "complete params", 30 opts: profilerOpts{}, 31 envParams: "stackdriver?service=gitaly&service_version=1.0.1&project_id=test-123", 32 writeEnvVar: true, 33 expectedLog: `^time=.*level=info msg="profiler enabled" driver=stackdriver projectId=test-123 service=gitaly serviceVersion=1.0.1`, 34 expectedConfig: profiler.Config{Service: "gitaly", ServiceVersion: "1.0.1", ProjectID: "test-123", MutexProfiling: true}, 35 }, 36 { 37 name: "complete env params and service version given", 38 opts: profilerOpts{ServiceVersion: "9.0.0"}, 39 envParams: "stackdriver?service=gitaly&service_version=1.0.1&project_id=test-123", 40 writeEnvVar: true, 41 expectedLog: `^time=.*level=info msg="profiler enabled" driver=stackdriver projectId=test-123 service=gitaly serviceVersion=9.0.0`, 42 expectedConfig: profiler.Config{Service: "gitaly", ServiceVersion: "9.0.0", ProjectID: "test-123", MutexProfiling: true}, 43 }, 44 { 45 name: "incomplete env params and service version given through args", 46 opts: profilerOpts{ServiceVersion: "9.0.0"}, 47 envParams: "stackdriver?service=gitaly", 48 expectedLog: `^time=.*level=info msg="profiler enabled" driver=stackdriver projectId= service=gitaly serviceVersion=9.0.0`, 49 expectedConfig: profiler.Config{MutexProfiling: true}, 50 }, 51 { 52 name: "debug logging", 53 opts: profilerOpts{ServiceVersion: "9.0.0"}, 54 envParams: "stackdriver?service=gitaly&debug_logging=true", 55 writeEnvVar: true, 56 expectedLog: `^time=.*level=info msg="profiler enabled" driver=stackdriver projectId= service=gitaly serviceVersion=9.0.0`, 57 expectedConfig: profiler.Config{Service: "gitaly", ServiceVersion: "9.0.0", MutexProfiling: true, DebugLogging: true}, 58 }, 59 { 60 name: "unknown driver", 61 envParams: "true?service=gitaly", 62 writeEnvVar: true, 63 opts: profilerOpts{}, 64 expectedLog: `^time=.*level=warning msg="unknown driver" driver=true`, 65 }, 66 { 67 name: "wrong env content format", 68 envParams: ":foo?service=gitaly", 69 writeEnvVar: true, 70 opts: profilerOpts{}, 71 expectedLog: `^time=.*level=warning msg="unable to parse env var content"`, 72 }, 73 { 74 name: "empty logs when no env var is set", 75 writeEnvVar: false, 76 opts: profilerOpts{}, 77 }, 78 { 79 name: "fails to start profiler", 80 envParams: "stackdriver?service=gitaly&service_version=1.0.1&project_id=test-123", 81 writeEnvVar: true, 82 opts: profilerOpts{}, 83 expectedLog: `^time=.*level=warning msg="unable to initialize stackdriver profiler" error="fail to start"`, 84 profErr: fmt.Errorf("fail to start"), 85 expectedConfig: profiler.Config{Service: "gitaly", ServiceVersion: "1.0.1", ProjectID: "test-123", MutexProfiling: true}, 86 }, 87 { 88 name: "with credentials file", 89 envParams: "stackdriver", 90 writeEnvVar: true, 91 opts: profilerOpts{CredentialsFile: "/path/to/credentials.json"}, 92 expectedOptions: []option.ClientOption{option.WithCredentialsFile("/path/to/credentials.json")}, 93 expectedConfig: profiler.Config{MutexProfiling: true}, 94 }, 95 } 96 for _, test := range tests { 97 t.Run(test.name, func(t *testing.T) { 98 clearGcpEnvVars(t) 99 100 preStubStart := profStart 101 defer func() { profStart = preStubStart }() 102 103 var actualConfig profiler.Config 104 var actualOptions []option.ClientOption 105 profStart = func(cfg profiler.Config, options ...option.ClientOption) error { 106 actualConfig = cfg 107 actualOptions = options 108 return test.profErr 109 } 110 111 if test.writeEnvVar { 112 err := os.Setenv(profilerEnvKey, test.envParams) 113 require.NoError(t, err) 114 } 115 116 logOutput := captureLogOutput(t, initProfiler, test.opts) 117 118 if test.writeEnvVar { 119 require.Regexp(t, test.expectedLog, logOutput) 120 require.Equal(t, test.expectedConfig, actualConfig) 121 require.Equal(t, test.expectedOptions, actualOptions) 122 } else { 123 require.Empty(t, logOutput) 124 } 125 }) 126 } 127 } 128 129 func TestInitProfilerWithNoProfilerEnvKeySet(t *testing.T) { 130 t.Run("no GITLAB_CONTINUOUS_PROFILING env var set", func(t *testing.T) { 131 clearGcpEnvVars(t) 132 133 logOutput := captureLogOutput(t, initProfiler, profilerOpts{}) 134 135 require.Empty(t, logOutput) 136 }) 137 } 138 139 func captureLogOutput(t *testing.T, init func(opts profilerOpts), opts profilerOpts) string { 140 t.Helper() 141 142 buf := &bytes.Buffer{} 143 closer, err := log.Initialize(log.WithWriter(buf)) 144 require.NoError(t, err) 145 defer closer.Close() 146 147 init(opts) 148 149 return buf.String() 150 } 151 152 func clearGcpEnvVars(t *testing.T) { 153 t.Helper() 154 155 for _, env := range []string{profilerEnvKey, "GAE_SERVICE", "GAE_VERSION", "GOOGLE_CLOUD_PROJECT"} { 156 err := os.Unsetenv(env) 157 158 require.NoError(t, err) 159 } 160 }