123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- /*
- Copyright 2019 The Vitess Authors.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package prometheusbackend
- import (
- "fmt"
- "net/http"
- "net/http/httptest"
- "os"
- "strings"
- "testing"
- "time"
- "git.nspix.com/golang/micro/stats"
- "github.com/prometheus/client_golang/prometheus/promhttp"
- )
- const namespace = "namespace"
- func TestPrometheusCounter(t *testing.T) {
- name := "blah"
- c := stats.NewCounter(name, "blah")
- c.Add(1)
- checkHandlerForMetrics(t, name, 1)
- //TODO: ban this? And for other counter types too?
- // c.Add(-1)
- c.Reset()
- checkHandlerForMetrics(t, name, 0)
- }
- func TestPrometheusGauge(t *testing.T) {
- name := "blah_gauge"
- c := stats.NewGauge(name, "help")
- c.Add(1)
- checkHandlerForMetrics(t, name, 1)
- c.Add(-1)
- checkHandlerForMetrics(t, name, 0)
- c.Set(-5)
- checkHandlerForMetrics(t, name, -5)
- c.Reset()
- checkHandlerForMetrics(t, name, 0)
- }
- func TestPrometheusCounterFunc(t *testing.T) {
- name := "blah_counterfunc"
- stats.NewCounterFunc(name, "help", func() int64 {
- return 2
- })
- checkHandlerForMetrics(t, name, 2)
- }
- func TestPrometheusGaugeFunc(t *testing.T) {
- name := "blah_gaugefunc"
- stats.NewGaugeFunc(name, "help", func() int64 {
- return -3
- })
- checkHandlerForMetrics(t, name, -3)
- }
- func TestPrometheusFloatFunc(t *testing.T) {
- name := "blah_floatfunc"
- stats.Publish(name, stats.FloatFunc(func() float64 { return -4 }))
- checkHandlerForMetrics(t, name, -4)
- }
- func TestPrometheusCounterDuration(t *testing.T) {
- name := "blah_counterduration"
- d := stats.NewCounterDuration(name, "help")
- d.Add(1 * time.Second)
- checkHandlerForMetrics(t, name, 1)
- }
- func TestPrometheusCounterDurationFunc(t *testing.T) {
- name := "blah_counterdurationfunc"
- stats.NewCounterDurationFunc(name, "help", func() time.Duration { return 1 * time.Second })
- checkHandlerForMetrics(t, name, 1)
- }
- func TestPrometheusGaugeDuration(t *testing.T) {
- name := "blah_gaugeduration"
- d := stats.NewGaugeDuration(name, "help")
- d.Set(1 * time.Second)
- checkHandlerForMetrics(t, name, 1)
- }
- func TestPrometheusGaugeDurationFunc(t *testing.T) {
- name := "blah_gaugedurationfunc"
- stats.NewGaugeDurationFunc(name, "help", func() time.Duration { return 1 * time.Second })
- checkHandlerForMetrics(t, name, 1)
- }
- func checkHandlerForMetrics(t *testing.T, metric string, value int) {
- response := testMetricsHandler(t)
- expected := fmt.Sprintf("%s_%s %d", namespace, metric, value)
- if !strings.Contains(response.Body.String(), expected) {
- t.Fatalf("Expected %s got %s", expected, response.Body.String())
- }
- }
- func TestPrometheusCountersWithSingleLabel(t *testing.T) {
- name := "blah_counterswithsinglelabel"
- c := stats.NewCountersWithSingleLabel(name, "help", "label", "tag1", "tag2")
- c.Add("tag1", 1)
- checkHandlerForMetricWithSingleLabel(t, name, "label", "tag1", 1)
- checkHandlerForMetricWithSingleLabel(t, name, "label", "tag2", 0)
- c.Add("tag2", 41)
- checkHandlerForMetricWithSingleLabel(t, name, "label", "tag1", 1)
- checkHandlerForMetricWithSingleLabel(t, name, "label", "tag2", 41)
- c.Reset("tag2")
- checkHandlerForMetricWithSingleLabel(t, name, "label", "tag1", 1)
- checkHandlerForMetricWithSingleLabel(t, name, "label", "tag2", 0)
- }
- func TestPrometheusGaugesWithSingleLabel(t *testing.T) {
- name := "blah_gaugeswithsinglelabel"
- c := stats.NewGaugesWithSingleLabel(name, "help", "label", "tag1", "tag2")
- c.Add("tag1", 1)
- checkHandlerForMetricWithSingleLabel(t, name, "label", "tag1", 1)
- c.Add("tag2", 1)
- checkHandlerForMetricWithSingleLabel(t, name, "label", "tag2", 1)
- c.Set("tag1", -1)
- checkHandlerForMetricWithSingleLabel(t, name, "label", "tag1", -1)
- c.Reset("tag2")
- checkHandlerForMetricWithSingleLabel(t, name, "label", "tag1", -1)
- checkHandlerForMetricWithSingleLabel(t, name, "label", "tag2", 0)
- }
- func checkHandlerForMetricWithSingleLabel(t *testing.T, metric, label, tag string, value int) {
- response := testMetricsHandler(t)
- expected := fmt.Sprintf("%s_%s{%s=\"%s\"} %d", namespace, metric, label, tag, value)
- if !strings.Contains(response.Body.String(), expected) {
- t.Fatalf("Expected %s got %s", expected, response.Body.String())
- }
- }
- func TestPrometheusCountersWithMultiLabels(t *testing.T) {
- name := "blah_counterswithmultilabels"
- labels := []string{"label1", "label2"}
- labelValues := []string{"foo", "bar"}
- c := stats.NewCountersWithMultiLabels(name, "help", labels)
- c.Add(labelValues, 1)
- checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues, 1)
- labelValues2 := []string{"baz", "bazbar"}
- c.Add(labelValues2, 1)
- checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues, 1)
- checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues2, 1)
- c.Reset(labelValues)
- checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues, 0)
- checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues2, 1)
- }
- func TestPrometheusGaugesWithMultiLabels(t *testing.T) {
- name := "blah_gaugeswithmultilabels"
- labels := []string{"label1", "label2"}
- labelValues := []string{"foo", "bar"}
- c := stats.NewGaugesWithMultiLabels(name, "help", labels)
- c.Add(labelValues, 1)
- checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues, 1)
- c.Set(labelValues, -1)
- checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues, -1)
- labelValues2 := []string{"baz", "bazbar"}
- c.Add(labelValues2, 1)
- checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues, -1)
- checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues2, 1)
- c.Reset(labelValues)
- checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues, 0)
- checkHandlerForMetricWithMultiLabels(t, name, labels, labelValues2, 1)
- }
- func TestPrometheusCountersWithMultiLabels_AddPanic(t *testing.T) {
- defer func() {
- if r := recover(); r == nil {
- t.Errorf("The code did not panic when adding to inequal label lengths")
- }
- }()
- name := "blah_counterswithmultilabels_inequallength"
- c := stats.NewCountersWithMultiLabels(name, "help", []string{"label1", "label2"})
- c.Add([]string{"label1"}, 1)
- }
- func TestPrometheusCountersFuncWithMultiLabels(t *testing.T) {
- name := "blah_countersfuncwithmultilabels"
- labels := []string{"label1", "label2"}
- stats.NewCountersFuncWithMultiLabels(name, "help", labels, func() map[string]int64 {
- m := make(map[string]int64)
- m["foo.bar"] = 1
- m["bar.baz"] = 1
- return m
- })
- checkHandlerForMetricWithMultiLabels(t, name, labels, []string{"foo", "bar"}, 1)
- checkHandlerForMetricWithMultiLabels(t, name, labels, []string{"bar", "baz"}, 1)
- }
- func checkHandlerForMetricWithMultiLabels(t *testing.T, metric string, labels []string, labelValues []string, value int64) {
- response := testMetricsHandler(t)
- expected := fmt.Sprintf("%s_%s{%s=\"%s\",%s=\"%s\"} %d", namespace, metric, labels[0], labelValues[0], labels[1], labelValues[1], value)
- if !strings.Contains(response.Body.String(), expected) {
- t.Fatalf("Expected %s got %s", expected, response.Body.String())
- }
- }
- func TestPrometheusTimings(t *testing.T) {
- name := "blah_timings"
- cats := []string{"cat1", "cat2"}
- timing := stats.NewTimings(name, "help", "category", cats...)
- timing.Add("cat1", time.Duration(30*time.Millisecond))
- timing.Add("cat1", time.Duration(200*time.Millisecond))
- timing.Add("cat1", time.Duration(1*time.Second))
- response := testMetricsHandler(t)
- var s []string
- s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"0.0005\"} %d", namespace, name, cats[0], 0))
- s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"0.001\"} %d", namespace, name, cats[0], 0))
- s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"0.005\"} %d", namespace, name, cats[0], 0))
- s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"0.01\"} %d", namespace, name, cats[0], 0))
- s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"0.05\"} %d", namespace, name, cats[0], 1))
- s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"0.1\"} %d", namespace, name, cats[0], 1))
- s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"0.5\"} %d", namespace, name, cats[0], 2))
- s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"1\"} %d", namespace, name, cats[0], 3))
- s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"5\"} %d", namespace, name, cats[0], 3))
- s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"10\"} %d", namespace, name, cats[0], 3))
- s = append(s, fmt.Sprintf("%s_%s_bucket{category=\"%s\",le=\"+Inf\"} %d", namespace, name, cats[0], 3))
- s = append(s, fmt.Sprintf("%s_%s_sum{category=\"%s\"} %s", namespace, name, cats[0], "1.23"))
- s = append(s, fmt.Sprintf("%s_%s_count{category=\"%s\"} %d", namespace, name, cats[0], 3))
- for _, line := range s {
- if !strings.Contains(response.Body.String(), line) {
- t.Fatalf("Expected result to contain %s, got %s", line, response.Body.String())
- }
- }
- }
- func TestPrometheusMultiTimings(t *testing.T) {
- name := "blah_multitimings"
- cats := []string{"cat1", "cat2"}
- catLabels := []string{"foo", "bar"}
- timing := stats.NewMultiTimings(name, "help", cats)
- timing.Add(catLabels, time.Duration(30*time.Millisecond))
- timing.Add(catLabels, time.Duration(200*time.Millisecond))
- timing.Add(catLabels, time.Duration(1*time.Second))
- response := testMetricsHandler(t)
- var s []string
- 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))
- 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))
- 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))
- 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))
- 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))
- 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))
- 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))
- 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))
- 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))
- 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))
- 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))
- 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"))
- s = append(s, fmt.Sprintf("%s_%s_count{%s=\"%s\",%s=\"%s\"} %d", namespace, name, cats[0], catLabels[0], cats[1], catLabels[1], 3))
- for _, line := range s {
- if !strings.Contains(response.Body.String(), line) {
- t.Fatalf("Expected result to contain %s, got %s", line, response.Body.String())
- }
- }
- }
- func TestPrometheusMultiTimings_PanicWrongLength(t *testing.T) {
- defer func() {
- if r := recover(); r == nil {
- t.Errorf("The code did not panic when adding to inequal label lengths")
- }
- }()
- c := stats.NewMultiTimings("name", "help", []string{"label1", "label2"})
- c.Add([]string{"label1"}, time.Duration(100000000))
- }
- func TestPrometheusHistogram(t *testing.T) {
- name := "blah_hist"
- hist := stats.NewHistogram(name, "help", []int64{1, 5, 10})
- hist.Add(2)
- hist.Add(3)
- hist.Add(6)
- response := testMetricsHandler(t)
- var s []string
- s = append(s, fmt.Sprintf("%s_%s_bucket{le=\"1\"} %d", namespace, name, 0))
- s = append(s, fmt.Sprintf("%s_%s_bucket{le=\"5\"} %d", namespace, name, 2))
- s = append(s, fmt.Sprintf("%s_%s_bucket{le=\"10\"} %d", namespace, name, 3))
- s = append(s, fmt.Sprintf("%s_%s_sum %d", namespace, name, 1))
- s = append(s, fmt.Sprintf("%s_%s_count %d", namespace, name, 3))
- for _, line := range s {
- if !strings.Contains(response.Body.String(), line) {
- t.Fatalf("Expected result to contain %s, got %s", line, response.Body.String())
- }
- }
- }
- func testMetricsHandler(t *testing.T) *httptest.ResponseRecorder {
- req, _ := http.NewRequest("GET", "/metrics", nil)
- response := httptest.NewRecorder()
- promhttp.Handler().ServeHTTP(response, req)
- return response
- }
- func TestMain(m *testing.M) {
- Init(namespace)
- os.Exit(m.Run())
- }
|