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  }