forked from go-kit/kit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
prometheus.go
93 lines (83 loc) · 2.83 KB
/
prometheus.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package teststat
import (
"io/ioutil"
"math"
"net/http"
"net/http/httptest"
"regexp"
"strconv"
"strings"
"testing"
"github.com/prometheus/client_golang/prometheus"
)
// ScrapePrometheus returns the text encoding of the current state of
// Prometheus.
func ScrapePrometheus(t *testing.T) string {
server := httptest.NewServer(prometheus.UninstrumentedHandler())
defer server.Close()
resp, err := http.Get(server.URL)
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
buf, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatal(err)
}
return strings.TrimSpace(string(buf))
}
// AssertPrometheusNormalSummary ensures the Prometheus Summary referenced by
// name abides a normal distribution.
func AssertPrometheusNormalSummary(t *testing.T, metricName string, mean, stdev int64) {
scrape := ScrapePrometheus(t)
const tolerance int = 5 // Prometheus approximates higher quantiles badly -_-;
for quantileInt, quantileStr := range map[int]string{50: "0.5", 90: "0.9", 99: "0.99"} {
want := normalValueAtQuantile(mean, stdev, quantileInt)
have := getPrometheusQuantile(t, scrape, metricName, quantileStr)
if int(math.Abs(float64(want)-float64(have))) > tolerance {
t.Errorf("%q: want %d, have %d", quantileStr, want, have)
}
}
}
// AssertPrometheusBucketedHistogram ensures the Prometheus Histogram
// referenced by name has observations in the expected quantity and bucket.
func AssertPrometheusBucketedHistogram(t *testing.T, metricName string, mean, stdev int64, buckets []float64) {
scrape := ScrapePrometheus(t)
const tolerance int = population / 50 // pretty coarse-grained
for _, bucket := range buckets {
want := observationsLessThan(mean, stdev, bucket, population)
have := getPrometheusLessThan(t, scrape, metricName, strconv.FormatFloat(bucket, 'f', 0, 64))
if int(math.Abs(float64(want)-float64(have))) > tolerance {
t.Errorf("%.0f: want %d, have %d", bucket, want, have)
}
}
}
func getPrometheusQuantile(t *testing.T, scrape, name, quantileStr string) int {
matches := regexp.MustCompile(name+`{quantile="`+quantileStr+`"} ([0-9]+)`).FindAllStringSubmatch(scrape, -1)
if len(matches) < 1 {
t.Fatalf("%q: quantile %q not found in scrape", name, quantileStr)
}
if len(matches[0]) < 2 {
t.Fatalf("%q: quantile %q not found in scrape", name, quantileStr)
}
i, err := strconv.Atoi(matches[0][1])
if err != nil {
t.Fatal(err)
}
return i
}
func getPrometheusLessThan(t *testing.T, scrape, name, target string) int {
matches := regexp.MustCompile(name+`{le="`+target+`"} ([0-9]+)`).FindAllStringSubmatch(scrape, -1)
if len(matches) < 1 {
t.Logf(">>>\n%s\n", scrape)
t.Fatalf("%q: bucket %q not found in scrape", name, target)
}
if len(matches[0]) < 2 {
t.Fatalf("%q: bucket %q not found in scrape", name, target)
}
i, err := strconv.Atoi(matches[0][1])
if err != nil {
t.Fatal(err)
}
return i
}