github.com/hashicorp/go-metrics@v0.5.3/sink_test.go (about) 1 package metrics 2 3 import ( 4 "reflect" 5 "strings" 6 "sync" 7 "testing" 8 ) 9 10 type MockSink struct { 11 lock sync.Mutex 12 13 shutdown bool 14 keys [][]string 15 vals []float32 16 precisionVals []float64 17 labels [][]Label 18 } 19 20 func (m *MockSink) getKeys() [][]string { 21 m.lock.Lock() 22 defer m.lock.Unlock() 23 24 return m.keys 25 } 26 27 func (m *MockSink) SetGauge(key []string, val float32) { 28 m.SetGaugeWithLabels(key, val, nil) 29 } 30 func (m *MockSink) SetGaugeWithLabels(key []string, val float32, labels []Label) { 31 m.lock.Lock() 32 defer m.lock.Unlock() 33 34 m.keys = append(m.keys, key) 35 m.vals = append(m.vals, val) 36 m.labels = append(m.labels, labels) 37 } 38 func (m *MockSink) SetPrecisionGauge(key []string, val float64) { 39 m.SetPrecisionGaugeWithLabels(key, val, nil) 40 } 41 func (m *MockSink) SetPrecisionGaugeWithLabels(key []string, val float64, labels []Label) { 42 m.lock.Lock() 43 defer m.lock.Unlock() 44 45 m.keys = append(m.keys, key) 46 m.precisionVals = append(m.precisionVals, val) 47 m.labels = append(m.labels, labels) 48 } 49 func (m *MockSink) EmitKey(key []string, val float32) { 50 m.lock.Lock() 51 defer m.lock.Unlock() 52 53 m.keys = append(m.keys, key) 54 m.vals = append(m.vals, val) 55 m.labels = append(m.labels, nil) 56 } 57 func (m *MockSink) IncrCounter(key []string, val float32) { 58 m.IncrCounterWithLabels(key, val, nil) 59 } 60 func (m *MockSink) IncrCounterWithLabels(key []string, val float32, labels []Label) { 61 m.lock.Lock() 62 defer m.lock.Unlock() 63 64 m.keys = append(m.keys, key) 65 m.vals = append(m.vals, val) 66 m.labels = append(m.labels, labels) 67 } 68 func (m *MockSink) AddSample(key []string, val float32) { 69 m.AddSampleWithLabels(key, val, nil) 70 } 71 func (m *MockSink) AddSampleWithLabels(key []string, val float32, labels []Label) { 72 m.lock.Lock() 73 defer m.lock.Unlock() 74 75 m.keys = append(m.keys, key) 76 m.vals = append(m.vals, val) 77 m.labels = append(m.labels, labels) 78 } 79 func (m *MockSink) Shutdown() { 80 m.lock.Lock() 81 defer m.lock.Unlock() 82 83 m.shutdown = true 84 } 85 86 func TestFanoutSink_Gauge(t *testing.T) { 87 m1 := &MockSink{} 88 m2 := &MockSink{} 89 fh := &FanoutSink{m1, m2} 90 91 k := []string{"test"} 92 v := float32(42.0) 93 fh.SetGauge(k, v) 94 95 if !reflect.DeepEqual(m1.keys[0], k) { 96 t.Fatalf("key not equal") 97 } 98 if !reflect.DeepEqual(m2.keys[0], k) { 99 t.Fatalf("key not equal") 100 } 101 if !reflect.DeepEqual(m1.vals[0], v) { 102 t.Fatalf("val not equal") 103 } 104 if !reflect.DeepEqual(m2.vals[0], v) { 105 t.Fatalf("val not equal") 106 } 107 } 108 109 func TestFanoutSink_Gauge_Labels(t *testing.T) { 110 m1 := &MockSink{} 111 m2 := &MockSink{} 112 fh := &FanoutSink{m1, m2} 113 114 k := []string{"test"} 115 v := float32(42.0) 116 l := []Label{{"a", "b"}} 117 fh.SetGaugeWithLabels(k, v, l) 118 119 if !reflect.DeepEqual(m1.keys[0], k) { 120 t.Fatalf("key not equal") 121 } 122 if !reflect.DeepEqual(m2.keys[0], k) { 123 t.Fatalf("key not equal") 124 } 125 if !reflect.DeepEqual(m1.vals[0], v) { 126 t.Fatalf("val not equal") 127 } 128 if !reflect.DeepEqual(m2.vals[0], v) { 129 t.Fatalf("val not equal") 130 } 131 if !reflect.DeepEqual(m1.labels[0], l) { 132 t.Fatalf("labels not equal") 133 } 134 if !reflect.DeepEqual(m2.labels[0], l) { 135 t.Fatalf("labels not equal") 136 } 137 } 138 139 func TestFanoutSink_Key(t *testing.T) { 140 m1 := &MockSink{} 141 m2 := &MockSink{} 142 fh := &FanoutSink{m1, m2} 143 144 k := []string{"test"} 145 v := float32(42.0) 146 fh.EmitKey(k, v) 147 148 if !reflect.DeepEqual(m1.keys[0], k) { 149 t.Fatalf("key not equal") 150 } 151 if !reflect.DeepEqual(m2.keys[0], k) { 152 t.Fatalf("key not equal") 153 } 154 if !reflect.DeepEqual(m1.vals[0], v) { 155 t.Fatalf("val not equal") 156 } 157 if !reflect.DeepEqual(m2.vals[0], v) { 158 t.Fatalf("val not equal") 159 } 160 } 161 162 func TestFanoutSink_Counter(t *testing.T) { 163 m1 := &MockSink{} 164 m2 := &MockSink{} 165 fh := &FanoutSink{m1, m2} 166 167 k := []string{"test"} 168 v := float32(42.0) 169 fh.IncrCounter(k, v) 170 171 if !reflect.DeepEqual(m1.keys[0], k) { 172 t.Fatalf("key not equal") 173 } 174 if !reflect.DeepEqual(m2.keys[0], k) { 175 t.Fatalf("key not equal") 176 } 177 if !reflect.DeepEqual(m1.vals[0], v) { 178 t.Fatalf("val not equal") 179 } 180 if !reflect.DeepEqual(m2.vals[0], v) { 181 t.Fatalf("val not equal") 182 } 183 } 184 185 func TestFanoutSink_Counter_Labels(t *testing.T) { 186 m1 := &MockSink{} 187 m2 := &MockSink{} 188 fh := &FanoutSink{m1, m2} 189 190 k := []string{"test"} 191 v := float32(42.0) 192 l := []Label{{"a", "b"}} 193 fh.IncrCounterWithLabels(k, v, l) 194 195 if !reflect.DeepEqual(m1.keys[0], k) { 196 t.Fatalf("key not equal") 197 } 198 if !reflect.DeepEqual(m2.keys[0], k) { 199 t.Fatalf("key not equal") 200 } 201 if !reflect.DeepEqual(m1.vals[0], v) { 202 t.Fatalf("val not equal") 203 } 204 if !reflect.DeepEqual(m2.vals[0], v) { 205 t.Fatalf("val not equal") 206 } 207 if !reflect.DeepEqual(m1.labels[0], l) { 208 t.Fatalf("labels not equal") 209 } 210 if !reflect.DeepEqual(m2.labels[0], l) { 211 t.Fatalf("labels not equal") 212 } 213 } 214 215 func TestFanoutSink_Sample(t *testing.T) { 216 m1 := &MockSink{} 217 m2 := &MockSink{} 218 fh := &FanoutSink{m1, m2} 219 220 k := []string{"test"} 221 v := float32(42.0) 222 fh.AddSample(k, v) 223 224 if !reflect.DeepEqual(m1.keys[0], k) { 225 t.Fatalf("key not equal") 226 } 227 if !reflect.DeepEqual(m2.keys[0], k) { 228 t.Fatalf("key not equal") 229 } 230 if !reflect.DeepEqual(m1.vals[0], v) { 231 t.Fatalf("val not equal") 232 } 233 if !reflect.DeepEqual(m2.vals[0], v) { 234 t.Fatalf("val not equal") 235 } 236 } 237 238 func TestFanoutSink_Sample_Labels(t *testing.T) { 239 m1 := &MockSink{} 240 m2 := &MockSink{} 241 fh := &FanoutSink{m1, m2} 242 243 k := []string{"test"} 244 v := float32(42.0) 245 l := []Label{{"a", "b"}} 246 fh.AddSampleWithLabels(k, v, l) 247 248 if !reflect.DeepEqual(m1.keys[0], k) { 249 t.Fatalf("key not equal") 250 } 251 if !reflect.DeepEqual(m2.keys[0], k) { 252 t.Fatalf("key not equal") 253 } 254 if !reflect.DeepEqual(m1.vals[0], v) { 255 t.Fatalf("val not equal") 256 } 257 if !reflect.DeepEqual(m2.vals[0], v) { 258 t.Fatalf("val not equal") 259 } 260 if !reflect.DeepEqual(m1.labels[0], l) { 261 t.Fatalf("labels not equal") 262 } 263 if !reflect.DeepEqual(m2.labels[0], l) { 264 t.Fatalf("labels not equal") 265 } 266 } 267 268 func TestNewMetricSinkFromURL(t *testing.T) { 269 for _, tc := range []struct { 270 desc string 271 input string 272 expect reflect.Type 273 expectErr string 274 }{ 275 { 276 desc: "statsd scheme yields a StatsdSink", 277 input: "statsd://someserver:123", 278 expect: reflect.TypeOf(&StatsdSink{}), 279 }, 280 { 281 desc: "statsite scheme yields a StatsiteSink", 282 input: "statsite://someserver:123", 283 expect: reflect.TypeOf(&StatsiteSink{}), 284 }, 285 { 286 desc: "inmem scheme yields an InmemSink", 287 input: "inmem://?interval=30s&retain=30s", 288 expect: reflect.TypeOf(&InmemSink{}), 289 }, 290 { 291 desc: "unknown scheme yields an error", 292 input: "notasink://whatever", 293 expectErr: "unrecognized sink name: \"notasink\"", 294 }, 295 } { 296 t.Run(tc.desc, func(t *testing.T) { 297 ms, err := NewMetricSinkFromURL(tc.input) 298 if tc.expectErr != "" { 299 if !strings.Contains(err.Error(), tc.expectErr) { 300 t.Fatalf("expected err: %q to contain: %q", err, tc.expectErr) 301 } 302 } else { 303 if err != nil { 304 t.Fatalf("unexpected err: %s", err) 305 } 306 got := reflect.TypeOf(ms) 307 if got != tc.expect { 308 t.Fatalf("expected return type to be %v, got: %v", tc.expect, got) 309 } 310 } 311 }) 312 } 313 }