github.com/XiaoMi/Gaea@v1.2.5/stats/prometheus/prometheus_backend_test.go (about) 1 package prometheus 2 3 import ( 4 "fmt" 5 "net/http" 6 "net/http/httptest" 7 "os" 8 "strings" 9 "testing" 10 "time" 11 12 "github.com/XiaoMi/Gaea/stats" 13 14 "github.com/prometheus/client_golang/prometheus/promhttp" 15 ) 16 17 const namespace = "namespace" 18 19 func TestPrometheusCounter(t *testing.T) { 20 name := "blah" 21 c := stats.NewCounter(name, "blah") 22 c.Add(1) 23 checkHandlerForMetrics(t, name, 1) 24 //TODO: ban this? And for other counter types too? 25 // c.Add(-1) 26 c.Reset() 27 checkHandlerForMetrics(t, name, 0) 28 } 29 30 func TestPrometheusGauge(t *testing.T) { 31 name := "blah_gauge" 32 c := stats.NewGauge(name, "help") 33 c.Add(1) 34 checkHandlerForMetrics(t, name, 1) 35 c.Add(-1) 36 checkHandlerForMetrics(t, name, 0) 37 c.Set(-5) 38 checkHandlerForMetrics(t, name, -5) 39 c.Reset() 40 checkHandlerForMetrics(t, name, 0) 41 } 42 43 func TestPrometheusCounterFunc(t *testing.T) { 44 name := "blah_counterfunc" 45 stats.NewCounterFunc(name, "help", func() int64 { 46 return 2 47 }) 48 49 checkHandlerForMetrics(t, name, 2) 50 } 51 52 func TestPrometheusGaugeFunc(t *testing.T) { 53 name := "blah_gaugefunc" 54 55 stats.NewGaugeFunc(name, "help", func() int64 { 56 return -3 57 }) 58 59 checkHandlerForMetrics(t, name, -3) 60 } 61 62 func TestPrometheusCounterDuration(t *testing.T) { 63 name := "blah_counterduration" 64 65 d := stats.NewCounterDuration(name, "help") 66 d.Add(1 * time.Second) 67 68 checkHandlerForMetrics(t, name, 1) 69 } 70 71 func TestPrometheusCounterDurationFunc(t *testing.T) { 72 name := "blah_counterdurationfunc" 73 74 stats.NewCounterDurationFunc(name, "help", func() time.Duration { return 1 * time.Second }) 75 76 checkHandlerForMetrics(t, name, 1) 77 } 78 79 func TestPrometheusGaugeDuration(t *testing.T) { 80 name := "blah_gaugeduration" 81 82 d := stats.NewGaugeDuration(name, "help") 83 d.Set(1 * time.Second) 84 85 checkHandlerForMetrics(t, name, 1) 86 } 87 88 func TestPrometheusGaugeDurationFunc(t *testing.T) { 89 name := "blah_gaugedurationfunc" 90 91 stats.NewGaugeDurationFunc(name, "help", func() time.Duration { return 1 * time.Second }) 92 93 checkHandlerForMetrics(t, name, 1) 94 } 95 96 func checkHandlerForMetrics(t *testing.T, metric string, value int) { 97 response := testMetricsHandler(t) 98 99 expected := fmt.Sprintf("%s_%s %d", namespace, metric, value) 100 101 if !strings.Contains(response.Body.String(), expected) { 102 t.Fatalf("Expected %s got %s", expected, response.Body.String()) 103 } 104 } 105 106 func TestPrometheusCountersWithSingleLabel(t *testing.T) { 107 name := "blah_counterswithsinglelabel" 108 c := stats.NewCountersWithSingleLabel(name, "help", "label", "tag1", "tag2") 109 c.Add("tag1", 1) 110 checkHandlerForMetricWithSingleLabel(t, name, "label", "tag1", 1) 111 checkHandlerForMetricWithSingleLabel(t, name, "label", "tag2", 0) 112 c.Add("tag2", 41) 113 checkHandlerForMetricWithSingleLabel(t, name, "label", "tag1", 1) 114 checkHandlerForMetricWithSingleLabel(t, name, "label", "tag2", 41) 115 c.Reset("tag2") 116 checkHandlerForMetricWithSingleLabel(t, name, "label", "tag1", 1) 117 checkHandlerForMetricWithSingleLabel(t, name, "label", "tag2", 0) 118 } 119 120 func TestPrometheusGaugesWithSingleLabel(t *testing.T) { 121 name := "blah_gaugeswithsinglelabel" 122 c := stats.NewGaugesWithSingleLabel(name, "help", "label", "tag1", "tag2") 123 c.Add("tag1", 1) 124 checkHandlerForMetricWithSingleLabel(t, name, "label", "tag1", 1) 125 126 c.Add("tag2", 1) 127 checkHandlerForMetricWithSingleLabel(t, name, "label", "tag2", 1) 128 129 c.Set("tag1", -1) 130 checkHandlerForMetricWithSingleLabel(t, name, "label", "tag1", -1) 131 132 c.Reset("tag2") 133 checkHandlerForMetricWithSingleLabel(t, name, "label", "tag1", -1) 134 checkHandlerForMetricWithSingleLabel(t, name, "label", "tag2", 0) 135 } 136 137 func checkHandlerForMetricWithSingleLabel(t *testing.T, metric, label, tag string, value int) { 138 response := testMetricsHandler(t) 139 140 expected := fmt.Sprintf("%s_%s{%s=\"%s\"} %d", namespace, metric, label, tag, value) 141 142 if !strings.Contains(response.Body.String(), expected) { 143 t.Fatalf("Expected %s got %s", expected, response.Body.String()) 144 } 145 } 146 147 func TestPrometheusCountersWithMultiLabels(t *testing.T) { 148 name := "blah_counterswithmultilabels" 149 labels := []string{"label1", "label2"} 150 labelValues := []string{"foo", "bar"} 151 c := stats.NewCountersWithMultiLabels(name, "help", labels) 152 c.Add(labelValues, 1) 153 checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues, 1) 154 labelValues2 := []string{"baz", "bazbar"} 155 c.Add(labelValues2, 1) 156 checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues, 1) 157 checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues2, 1) 158 c.Reset(labelValues) 159 checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues, 0) 160 checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues2, 1) 161 } 162 163 func TestPrometheusGaugesWithMultiLabels(t *testing.T) { 164 name := "blah_gaugeswithmultilabels" 165 labels := []string{"label1", "label2"} 166 labelValues := []string{"foo", "bar"} 167 c := stats.NewGaugesWithMultiLabels(name, "help", labels) 168 c.Add(labelValues, 1) 169 checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues, 1) 170 171 c.Set(labelValues, -1) 172 checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues, -1) 173 174 labelValues2 := []string{"baz", "bazbar"} 175 c.Add(labelValues2, 1) 176 checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues, -1) 177 checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues2, 1) 178 179 c.Reset(labelValues) 180 checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues, 0) 181 checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues2, 1) 182 } 183 184 func TestPrometheusCountersWithMultiLabels_AddPanic(t *testing.T) { 185 defer func() { 186 if r := recover(); r == nil { 187 t.Errorf("The code did not panic when adding to inequal label lengths") 188 } 189 }() 190 191 name := "blah_counterswithmultilabels_inequallength" 192 c := stats.NewCountersWithMultiLabels(name, "help", []string{"label1", "label2"}) 193 c.Add([]string{"label1"}, 1) 194 } 195 196 func TestPrometheusCountersFuncWithMultiLabels(t *testing.T) { 197 name := "blah_countersfuncwithmultilabels" 198 labels := []string{"label1", "label2"} 199 200 stats.NewCountersFuncWithMultiLabels(name, "help", labels, func() map[string]int64 { 201 m := make(map[string]int64) 202 m["foo.bar"] = 1 203 m["bar.baz"] = 1 204 return m 205 }) 206 207 checkHandlerForMetricWithMultiLabels(t, name, labels, []string{"foo", "bar"}, 1) 208 checkHandlerForMetricWithMultiLabels(t, name, labels, []string{"bar", "baz"}, 1) 209 } 210 211 func checkHandlerForMetricWithMultiLabels(t *testing.T, metric string, labels []string, labelValues []string, value int64) { 212 response := testMetricsHandler(t) 213 214 expected := fmt.Sprintf("%s_%s{%s=\"%s\",%s=\"%s\"} %d", namespace, metric, labels[0], labelValues[0], labels[1], labelValues[1], value) 215 216 if !strings.Contains(response.Body.String(), expected) { 217 t.Fatalf("Expected %s got %s", expected, response.Body.String()) 218 } 219 } 220 221 func TestPrometheusTimings(t *testing.T) { 222 name := "blah_timings" 223 cats := []string{"cat1", "cat2"} 224 timing := stats.NewTimings(name, "help", "category", cats...) 225 timing.Add("cat1", time.Duration(30*time.Millisecond)) 226 timing.Add("cat1", time.Duration(200*time.Millisecond)) 227 timing.Add("cat1", time.Duration(1*time.Second)) 228 229 response := testMetricsHandler(t) 230 var s []string 231 232 s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"0.0005\"} %d", namespace, name, cats[0], 0)) 233 s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"0.001\"} %d", namespace, name, cats[0], 0)) 234 s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"0.005\"} %d", namespace, name, cats[0], 0)) 235 s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"0.01\"} %d", namespace, name, cats[0], 0)) 236 s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"0.05\"} %d", namespace, name, cats[0], 1)) 237 s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"0.1\"} %d", namespace, name, cats[0], 1)) 238 s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"0.5\"} %d", namespace, name, cats[0], 2)) 239 s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"1\"} %d", namespace, name, cats[0], 3)) 240 s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"5\"} %d", namespace, name, cats[0], 3)) 241 s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"10\"} %d", namespace, name, cats[0], 3)) 242 s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"+Inf\"} %d", namespace, name, cats[0], 3)) 243 s = append(s, fmt.Sprintf("%s_%s_sum{category=\"%s\"} %s", namespace, name, cats[0], "1.23")) 244 s = append(s, fmt.Sprintf("%s_%s_count{category=\"%s\"} %d", namespace, name, cats[0], 3)) 245 246 for _, line := range s { 247 if !strings.Contains(response.Body.String(), line) { 248 t.Fatalf("Expected result to contain %s, got %s", line, response.Body.String()) 249 } 250 } 251 } 252 253 func TestPrometheusMultiTimings(t *testing.T) { 254 name := "blah_multitimings" 255 cats := []string{"cat1", "cat2"} 256 catLabels := []string{"foo", "bar"} 257 timing := stats.NewMultiTimings(name, "help", cats) 258 timing.Add(catLabels, time.Duration(30*time.Millisecond)) 259 timing.Add(catLabels, time.Duration(200*time.Millisecond)) 260 timing.Add(catLabels, time.Duration(1*time.Second)) 261 262 response := testMetricsHandler(t) 263 var s []string 264 265 s = append(s, fmt.Sprintf("%s_%s_bucket{%s=\"%s\",%s=\"%s\",le=\"0.0005\"} %d", namespace, name, cats[0], catLabels[0], cats[1], catLabels[1], 0)) 266 s = append(s, fmt.Sprintf("%s_%s_bucket{%s=\"%s\",%s=\"%s\",le=\"0.001\"} %d", namespace, name, cats[0], catLabels[0], cats[1], catLabels[1], 0)) 267 s = append(s, fmt.Sprintf("%s_%s_bucket{%s=\"%s\",%s=\"%s\",le=\"0.005\"} %d", namespace, name, cats[0], catLabels[0], cats[1], catLabels[1], 0)) 268 s = append(s, fmt.Sprintf("%s_%s_bucket{%s=\"%s\",%s=\"%s\",le=\"0.01\"} %d", namespace, name, cats[0], catLabels[0], cats[1], catLabels[1], 0)) 269 s = append(s, fmt.Sprintf("%s_%s_bucket{%s=\"%s\",%s=\"%s\",le=\"0.05\"} %d", namespace, name, cats[0], catLabels[0], cats[1], catLabels[1], 1)) 270 s = append(s, fmt.Sprintf("%s_%s_bucket{%s=\"%s\",%s=\"%s\",le=\"0.1\"} %d", namespace, name, cats[0], catLabels[0], cats[1], catLabels[1], 1)) 271 s = append(s, fmt.Sprintf("%s_%s_bucket{%s=\"%s\",%s=\"%s\",le=\"0.5\"} %d", namespace, name, cats[0], catLabels[0], cats[1], catLabels[1], 2)) 272 s = append(s, fmt.Sprintf("%s_%s_bucket{%s=\"%s\",%s=\"%s\",le=\"1\"} %d", namespace, name, cats[0], catLabels[0], cats[1], catLabels[1], 3)) 273 s = append(s, fmt.Sprintf("%s_%s_bucket{%s=\"%s\",%s=\"%s\",le=\"5\"} %d", namespace, name, cats[0], catLabels[0], cats[1], catLabels[1], 3)) 274 s = append(s, fmt.Sprintf("%s_%s_bucket{%s=\"%s\",%s=\"%s\",le=\"10\"} %d", namespace, name, cats[0], catLabels[0], cats[1], catLabels[1], 3)) 275 s = append(s, fmt.Sprintf("%s_%s_bucket{%s=\"%s\",%s=\"%s\",le=\"+Inf\"} %d", namespace, name, cats[0], catLabels[0], cats[1], catLabels[1], 3)) 276 s = append(s, fmt.Sprintf("%s_%s_sum{%s=\"%s\",%s=\"%s\"} %s", namespace, name, cats[0], catLabels[0], cats[1], catLabels[1], "1.23")) 277 s = append(s, fmt.Sprintf("%s_%s_count{%s=\"%s\",%s=\"%s\"} %d", namespace, name, cats[0], catLabels[0], cats[1], catLabels[1], 3)) 278 279 for _, line := range s { 280 if !strings.Contains(response.Body.String(), line) { 281 t.Fatalf("Expected result to contain %s, got %s", line, response.Body.String()) 282 } 283 } 284 } 285 286 func TestPrometheusMultiTimings_PanicWrongLength(t *testing.T) { 287 defer func() { 288 if r := recover(); r == nil { 289 t.Errorf("The code did not panic when adding to inequal label lengths") 290 } 291 }() 292 293 c := stats.NewMultiTimings("name", "help", []string{"label1", "label2"}) 294 c.Add([]string{"label1"}, time.Duration(100000000)) 295 } 296 297 func TestPrometheusHistogram(t *testing.T) { 298 name := "blah_hist" 299 hist := stats.NewHistogram(name, "help", []int64{1, 5, 10}) 300 hist.Add(2) 301 hist.Add(3) 302 hist.Add(6) 303 304 response := testMetricsHandler(t) 305 var s []string 306 307 s = append(s, fmt.Sprintf("%s_%s_bucket{le=\"1\"} %d", namespace, name, 0)) 308 s = append(s, fmt.Sprintf("%s_%s_bucket{le=\"5\"} %d", namespace, name, 2)) 309 s = append(s, fmt.Sprintf("%s_%s_bucket{le=\"10\"} %d", namespace, name, 3)) 310 s = append(s, fmt.Sprintf("%s_%s_sum %d", namespace, name, 1)) 311 s = append(s, fmt.Sprintf("%s_%s_count %d", namespace, name, 3)) 312 313 for _, line := range s { 314 if !strings.Contains(response.Body.String(), line) { 315 t.Fatalf("Expected result to contain %s, got %s", line, response.Body.String()) 316 } 317 } 318 } 319 320 func testMetricsHandler(t *testing.T) *httptest.ResponseRecorder { 321 req, _ := http.NewRequest("GET", "/metrics", nil) 322 response := httptest.NewRecorder() 323 324 promhttp.Handler().ServeHTTP(response, req) 325 return response 326 } 327 328 func TestMain(m *testing.M) { 329 Init(namespace) 330 os.Exit(m.Run()) 331 }