...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package main
18
19 import (
20 "flag"
21 "fmt"
22 "log"
23 "math"
24 "math/rand"
25 "net/http"
26 "time"
27
28 "github.com/prometheus/client_golang/prometheus"
29 "github.com/prometheus/client_golang/prometheus/collectors"
30 "github.com/prometheus/client_golang/prometheus/promhttp"
31 )
32
33 type metrics struct {
34 rpcDurations *prometheus.SummaryVec
35 rpcDurationsHistogram prometheus.Histogram
36 }
37
38 func NewMetrics(reg prometheus.Registerer, normMean, normDomain float64) *metrics {
39 m := &metrics{
40
41
42
43 rpcDurations: prometheus.NewSummaryVec(
44 prometheus.SummaryOpts{
45 Name: "rpc_durations_seconds",
46 Help: "RPC latency distributions.",
47 Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
48 },
49 []string{"service"},
50 ),
51
52
53
54
55
56
57
58
59
60
61
62 rpcDurationsHistogram: prometheus.NewHistogram(prometheus.HistogramOpts{
63 Name: "rpc_durations_histogram_seconds",
64 Help: "RPC latency distributions.",
65 Buckets: prometheus.LinearBuckets(normMean-5*normDomain, .5*normDomain, 20),
66 NativeHistogramBucketFactor: 1.1,
67 }),
68 }
69 reg.MustRegister(m.rpcDurations)
70 reg.MustRegister(m.rpcDurationsHistogram)
71 return m
72 }
73
74 func main() {
75 var (
76 addr = flag.String("listen-address", ":8080", "The address to listen on for HTTP requests.")
77 uniformDomain = flag.Float64("uniform.domain", 0.0002, "The domain for the uniform distribution.")
78 normDomain = flag.Float64("normal.domain", 0.0002, "The domain for the normal distribution.")
79 normMean = flag.Float64("normal.mean", 0.00001, "The mean for the normal distribution.")
80 oscillationPeriod = flag.Duration("oscillation-period", 10*time.Minute, "The duration of the rate oscillation period.")
81 )
82
83 flag.Parse()
84
85
86 reg := prometheus.NewRegistry()
87
88
89 m := NewMetrics(reg, *normMean, *normDomain)
90
91 reg.MustRegister(collectors.NewBuildInfoCollector())
92
93 start := time.Now()
94
95 oscillationFactor := func() float64 {
96 return 2 + math.Sin(math.Sin(2*math.Pi*float64(time.Since(start))/float64(*oscillationPeriod)))
97 }
98
99
100 go func() {
101 for {
102 v := rand.Float64() * *uniformDomain
103 m.rpcDurations.WithLabelValues("uniform").Observe(v)
104 time.Sleep(time.Duration(100*oscillationFactor()) * time.Millisecond)
105 }
106 }()
107
108 go func() {
109 for {
110 v := (rand.NormFloat64() * *normDomain) + *normMean
111 m.rpcDurations.WithLabelValues("normal").Observe(v)
112
113
114
115
116
117
118 m.rpcDurationsHistogram.(prometheus.ExemplarObserver).ObserveWithExemplar(
119 v, prometheus.Labels{"dummyID": fmt.Sprint(rand.Intn(100000))},
120 )
121 time.Sleep(time.Duration(75*oscillationFactor()) * time.Millisecond)
122 }
123 }()
124
125 go func() {
126 for {
127 v := rand.ExpFloat64() / 1e6
128 m.rpcDurations.WithLabelValues("exponential").Observe(v)
129 time.Sleep(time.Duration(50*oscillationFactor()) * time.Millisecond)
130 }
131 }()
132
133
134 http.Handle("/metrics", promhttp.HandlerFor(
135 reg,
136 promhttp.HandlerOpts{
137
138 EnableOpenMetrics: true,
139
140 Registry: reg,
141 },
142 ))
143 log.Fatal(http.ListenAndServe(*addr, nil))
144 }
145
View as plain text