OSDN Git Service

delete miner
[bytom/vapor.git] / vendor / github.com / go-kit / kit / metrics / prometheus / prometheus_test.go
1 package prometheus
2
3 import (
4         "io/ioutil"
5         "math"
6         "math/rand"
7         "net/http"
8         "net/http/httptest"
9         "reflect"
10         "regexp"
11         "strconv"
12         "strings"
13         "testing"
14
15         stdprometheus "github.com/prometheus/client_golang/prometheus"
16
17         "github.com/go-kit/kit/metrics/teststat"
18 )
19
20 func TestCounter(t *testing.T) {
21         s := httptest.NewServer(stdprometheus.UninstrumentedHandler())
22         defer s.Close()
23
24         scrape := func() string {
25                 resp, _ := http.Get(s.URL)
26                 buf, _ := ioutil.ReadAll(resp.Body)
27                 return string(buf)
28         }
29
30         namespace, subsystem, name := "ns", "ss", "foo"
31         re := regexp.MustCompile(namespace + `_` + subsystem + `_` + name + `{alpha="alpha-value",beta="beta-value"} ([0-9\.]+)`)
32
33         counter := NewCounterFrom(stdprometheus.CounterOpts{
34                 Namespace: namespace,
35                 Subsystem: subsystem,
36                 Name:      name,
37                 Help:      "This is the help string.",
38         }, []string{"alpha", "beta"}).With("beta", "beta-value", "alpha", "alpha-value") // order shouldn't matter
39
40         value := func() float64 {
41                 matches := re.FindStringSubmatch(scrape())
42                 f, _ := strconv.ParseFloat(matches[1], 64)
43                 return f
44         }
45
46         if err := teststat.TestCounter(counter, value); err != nil {
47                 t.Fatal(err)
48         }
49 }
50
51 func TestGauge(t *testing.T) {
52         s := httptest.NewServer(stdprometheus.UninstrumentedHandler())
53         defer s.Close()
54
55         scrape := func() string {
56                 resp, _ := http.Get(s.URL)
57                 buf, _ := ioutil.ReadAll(resp.Body)
58                 return string(buf)
59         }
60
61         namespace, subsystem, name := "aaa", "bbb", "ccc"
62         re := regexp.MustCompile(namespace + `_` + subsystem + `_` + name + `{foo="bar"} ([0-9\.]+)`)
63
64         gauge := NewGaugeFrom(stdprometheus.GaugeOpts{
65                 Namespace: namespace,
66                 Subsystem: subsystem,
67                 Name:      name,
68                 Help:      "This is a different help string.",
69         }, []string{"foo"}).With("foo", "bar")
70
71         value := func() float64 {
72                 matches := re.FindStringSubmatch(scrape())
73                 f, _ := strconv.ParseFloat(matches[1], 64)
74                 return f
75         }
76
77         if err := teststat.TestGauge(gauge, value); err != nil {
78                 t.Fatal(err)
79         }
80 }
81
82 func TestSummary(t *testing.T) {
83         s := httptest.NewServer(stdprometheus.UninstrumentedHandler())
84         defer s.Close()
85
86         scrape := func() string {
87                 resp, _ := http.Get(s.URL)
88                 buf, _ := ioutil.ReadAll(resp.Body)
89                 return string(buf)
90         }
91
92         namespace, subsystem, name := "test", "prometheus", "summary"
93         re50 := regexp.MustCompile(namespace + `_` + subsystem + `_` + name + `{a="a",b="b",quantile="0.5"} ([0-9\.]+)`)
94         re90 := regexp.MustCompile(namespace + `_` + subsystem + `_` + name + `{a="a",b="b",quantile="0.9"} ([0-9\.]+)`)
95         re99 := regexp.MustCompile(namespace + `_` + subsystem + `_` + name + `{a="a",b="b",quantile="0.99"} ([0-9\.]+)`)
96
97         summary := NewSummaryFrom(stdprometheus.SummaryOpts{
98                 Namespace: namespace,
99                 Subsystem: subsystem,
100                 Name:      name,
101                 Help:      "This is the help string for the summary.",
102         }, []string{"a", "b"}).With("b", "b").With("a", "a")
103
104         quantiles := func() (float64, float64, float64, float64) {
105                 buf := scrape()
106                 match50 := re50.FindStringSubmatch(buf)
107                 p50, _ := strconv.ParseFloat(match50[1], 64)
108                 match90 := re90.FindStringSubmatch(buf)
109                 p90, _ := strconv.ParseFloat(match90[1], 64)
110                 match99 := re99.FindStringSubmatch(buf)
111                 p99, _ := strconv.ParseFloat(match99[1], 64)
112                 p95 := p90 + ((p99 - p90) / 2) // Prometheus, y u no p95??? :< #yolo
113                 return p50, p90, p95, p99
114         }
115
116         if err := teststat.TestHistogram(summary, quantiles, 0.01); err != nil {
117                 t.Fatal(err)
118         }
119 }
120
121 func TestHistogram(t *testing.T) {
122         // Prometheus reports histograms as a count of observations that fell into
123         // each predefined bucket, with the bucket value representing a global upper
124         // limit. That is, the count monotonically increases over the buckets. This
125         // requires a different strategy to test.
126
127         s := httptest.NewServer(stdprometheus.UninstrumentedHandler())
128         defer s.Close()
129
130         scrape := func() string {
131                 resp, _ := http.Get(s.URL)
132                 buf, _ := ioutil.ReadAll(resp.Body)
133                 return string(buf)
134         }
135
136         namespace, subsystem, name := "test", "prometheus", "histogram"
137         re := regexp.MustCompile(namespace + `_` + subsystem + `_` + name + `_bucket{x="1",le="([0-9]+|\+Inf)"} ([0-9\.]+)`)
138
139         numStdev := 3
140         bucketMin := (teststat.Mean - (numStdev * teststat.Stdev))
141         bucketMax := (teststat.Mean + (numStdev * teststat.Stdev))
142         if bucketMin < 0 {
143                 bucketMin = 0
144         }
145         bucketCount := 10
146         bucketDelta := (bucketMax - bucketMin) / bucketCount
147         buckets := []float64{}
148         for i := bucketMin; i <= bucketMax; i += bucketDelta {
149                 buckets = append(buckets, float64(i))
150         }
151
152         histogram := NewHistogramFrom(stdprometheus.HistogramOpts{
153                 Namespace: namespace,
154                 Subsystem: subsystem,
155                 Name:      name,
156                 Help:      "This is the help string for the histogram.",
157                 Buckets:   buckets,
158         }, []string{"x"}).With("x", "1")
159
160         // Can't TestHistogram, because Prometheus Histograms don't dynamically
161         // compute quantiles. Instead, they fill up buckets. So, let's populate the
162         // histogram kind of manually.
163         teststat.PopulateNormalHistogram(histogram, rand.Int())
164
165         // Then, we use ExpectedObservationsLessThan to validate.
166         for _, line := range strings.Split(scrape(), "\n") {
167                 match := re.FindStringSubmatch(line)
168                 if match == nil {
169                         continue
170                 }
171
172                 bucket, _ := strconv.ParseInt(match[1], 10, 64)
173                 have, _ := strconv.ParseInt(match[2], 10, 64)
174
175                 want := teststat.ExpectedObservationsLessThan(bucket)
176                 if match[1] == "+Inf" {
177                         want = int64(teststat.Count) // special case
178                 }
179
180                 // Unfortunately, we observe experimentally that Prometheus is quite
181                 // imprecise at the extremes. I'm setting a very high tolerance for now.
182                 // It would be great to dig in and figure out whether that's a problem
183                 // with my Expected calculation, or in Prometheus.
184                 tolerance := 0.25
185                 if delta := math.Abs(float64(want) - float64(have)); (delta / float64(want)) > tolerance {
186                         t.Errorf("Bucket %d: want %d, have %d (%.1f%%)", bucket, want, have, (100.0 * delta / float64(want)))
187                 }
188         }
189 }
190
191 func TestInconsistentLabelCardinality(t *testing.T) {
192         defer func() {
193                 x := recover()
194                 if x == nil {
195                         t.Fatal("expected panic, got none")
196                 }
197                 err, ok := x.(error)
198                 if !ok {
199                         t.Fatalf("expected error, got %s", reflect.TypeOf(x))
200                 }
201                 if want, have := "inconsistent label cardinality", err.Error(); want != have {
202                         t.Fatalf("want %q, have %q", want, have)
203                 }
204         }()
205
206         NewCounterFrom(stdprometheus.CounterOpts{
207                 Namespace: "test",
208                 Subsystem: "inconsistent_label_cardinality",
209                 Name:      "foobar",
210                 Help:      "This is the help string for the metric.",
211         }, []string{"a", "b"}).With(
212                 "a", "1", "b", "2", "c", "KABOOM!",
213         ).Add(123)
214 }