github.com/kaituanwang/hyperledger@v2.0.1+incompatible/common/metrics/prometheus/provider_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package prometheus_test 8 9 import ( 10 "fmt" 11 "io/ioutil" 12 "net/http" 13 "net/http/httptest" 14 15 commonmetrics "github.com/hyperledger/fabric/common/metrics" 16 "github.com/hyperledger/fabric/common/metrics/prometheus" 17 . "github.com/onsi/ginkgo" 18 . "github.com/onsi/gomega" 19 prom "github.com/prometheus/client_golang/prometheus" 20 "github.com/prometheus/client_golang/prometheus/promhttp" 21 ) 22 23 var _ = Describe("Provider", func() { 24 var ( 25 server *httptest.Server 26 client *http.Client 27 p *prometheus.Provider 28 ) 29 30 BeforeEach(func() { 31 // Note: These tests can't be run in parallel because go-kit uses 32 // the global registry to manage metrics. This is something to revisit 33 // in the future. 34 registry := prom.NewRegistry() 35 prom.DefaultRegisterer = registry 36 prom.DefaultGatherer = registry 37 38 server = httptest.NewServer(promhttp.HandlerFor(registry, promhttp.HandlerOpts{})) 39 client = server.Client() 40 41 p = &prometheus.Provider{} 42 }) 43 44 AfterEach(func() { 45 server.Close() 46 }) 47 48 It("implements metrics.Provider", func() { 49 var p commonmetrics.Provider = &prometheus.Provider{} 50 Expect(p).NotTo(BeNil()) 51 }) 52 53 Describe("NewCounter", func() { 54 var counterOpts commonmetrics.CounterOpts 55 56 BeforeEach(func() { 57 counterOpts = commonmetrics.CounterOpts{ 58 Namespace: "peer", 59 Subsystem: "playground", 60 Name: "counter_name", 61 Help: "This is some help text for the counter", 62 LabelNames: []string{"alpha", "beta"}, 63 } 64 }) 65 66 It("creates counters that support labels", func() { 67 counter := p.NewCounter(counterOpts) 68 counter.With("alpha", "a", "beta", "b").Add(1) 69 counter.With("alpha", "aardvark", "beta", "b").Add(2) 70 71 resp, err := client.Get(fmt.Sprintf("http://%s/metrics", server.Listener.Addr().String())) 72 Expect(err).NotTo(HaveOccurred()) 73 defer resp.Body.Close() 74 75 bytes, err := ioutil.ReadAll(resp.Body) 76 Expect(err).NotTo(HaveOccurred()) 77 Expect(string(bytes)).To(ContainSubstring(`# HELP peer_playground_counter_name This is some help text for the counter`)) 78 Expect(string(bytes)).To(ContainSubstring(`# TYPE peer_playground_counter_name counter`)) 79 Expect(string(bytes)).To(ContainSubstring(`peer_playground_counter_name{alpha="a",beta="b"} 1`)) 80 Expect(string(bytes)).To(ContainSubstring(`peer_playground_counter_name{alpha="aardvark",beta="b"} 2`)) 81 }) 82 83 Context("when the counter is defined without labels", func() { 84 BeforeEach(func() { 85 counterOpts.LabelNames = nil 86 }) 87 88 It("With does not need to be called", func() { 89 counter := p.NewCounter(counterOpts) 90 counter.Add(1) 91 92 resp, err := client.Get(fmt.Sprintf("http://%s/metrics", server.Listener.Addr().String())) 93 Expect(err).NotTo(HaveOccurred()) 94 defer resp.Body.Close() 95 96 bytes, err := ioutil.ReadAll(resp.Body) 97 Expect(err).NotTo(HaveOccurred()) 98 Expect(string(bytes)).To(ContainSubstring(`peer_playground_counter_name 1`)) 99 }) 100 }) 101 }) 102 103 Describe("NewGauge", func() { 104 var gaugeOpts commonmetrics.GaugeOpts 105 106 BeforeEach(func() { 107 gaugeOpts = commonmetrics.GaugeOpts{ 108 Namespace: "peer", 109 Subsystem: "playground", 110 Name: "gauge_name", 111 Help: "This is some help text for the gauge", 112 LabelNames: []string{"alpha", "beta"}, 113 } 114 }) 115 116 It("creates gauges that support labels", func() { 117 gauge := p.NewGauge(gaugeOpts) 118 gauge.With("alpha", "a", "beta", "b").Add(1) 119 gauge.With("alpha", "a", "beta", "b").Add(1) 120 gauge.With("alpha", "aardvark", "beta", "b").Add(1) 121 gauge.With("alpha", "aardvark", "beta", "bob").Set(99) 122 123 resp, err := client.Get(fmt.Sprintf("http://%s/metrics", server.Listener.Addr().String())) 124 Expect(err).NotTo(HaveOccurred()) 125 defer resp.Body.Close() 126 127 bytes, err := ioutil.ReadAll(resp.Body) 128 Expect(err).NotTo(HaveOccurred()) 129 Expect(string(bytes)).To(ContainSubstring(`# HELP peer_playground_gauge_name This is some help text for the gauge`)) 130 Expect(string(bytes)).To(ContainSubstring(`# TYPE peer_playground_gauge_name gauge`)) 131 Expect(string(bytes)).To(ContainSubstring(`peer_playground_gauge_name{alpha="a",beta="b"} 2`)) 132 Expect(string(bytes)).To(ContainSubstring(`peer_playground_gauge_name{alpha="aardvark",beta="b"} 1`)) 133 Expect(string(bytes)).To(ContainSubstring(`peer_playground_gauge_name{alpha="aardvark",beta="bob"} 99`)) 134 }) 135 }) 136 137 Describe("NewHistogram", func() { 138 var histogramOpts commonmetrics.HistogramOpts 139 140 BeforeEach(func() { 141 histogramOpts = commonmetrics.HistogramOpts{ 142 Namespace: "peer", 143 Subsystem: "playground", 144 Name: "histogram_name", 145 Help: "This is some help text for the gauge", 146 LabelNames: []string{"alpha", "beta"}, 147 } 148 }) 149 150 It("creates histogram that support labels", func() { 151 histogram := p.NewHistogram(histogramOpts) 152 for _, limit := range prom.DefBuckets { 153 histogram.With("alpha", "a", "beta", "b").Observe(limit) 154 } 155 histogram.With("alpha", "a", "beta", "b").Observe(prom.DefBuckets[len(prom.DefBuckets)-1] + 1) 156 157 resp, err := client.Get(fmt.Sprintf("http://%s/metrics", server.Listener.Addr().String())) 158 Expect(err).NotTo(HaveOccurred()) 159 defer resp.Body.Close() 160 161 bytes, err := ioutil.ReadAll(resp.Body) 162 Expect(err).NotTo(HaveOccurred()) 163 Expect(string(bytes)).To(ContainSubstring(`# HELP peer_playground_histogram_name This is some help text for the gauge`)) 164 Expect(string(bytes)).To(ContainSubstring(`# TYPE peer_playground_histogram_name histogram`)) 165 Expect(string(bytes)).To(ContainSubstring(`peer_playground_histogram_name_bucket{alpha="a",beta="b",le="0.005"} 1`)) 166 Expect(string(bytes)).To(ContainSubstring(`peer_playground_histogram_name_bucket{alpha="a",beta="b",le="0.01"} 2`)) 167 Expect(string(bytes)).To(ContainSubstring(`peer_playground_histogram_name_bucket{alpha="a",beta="b",le="0.025"} 3`)) 168 Expect(string(bytes)).To(ContainSubstring(`peer_playground_histogram_name_bucket{alpha="a",beta="b",le="0.05"} 4`)) 169 Expect(string(bytes)).To(ContainSubstring(`peer_playground_histogram_name_bucket{alpha="a",beta="b",le="0.1"} 5`)) 170 Expect(string(bytes)).To(ContainSubstring(`peer_playground_histogram_name_bucket{alpha="a",beta="b",le="0.25"} 6`)) 171 Expect(string(bytes)).To(ContainSubstring(`peer_playground_histogram_name_bucket{alpha="a",beta="b",le="0.5"} 7`)) 172 Expect(string(bytes)).To(ContainSubstring(`peer_playground_histogram_name_bucket{alpha="a",beta="b",le="1"} 8`)) 173 Expect(string(bytes)).To(ContainSubstring(`peer_playground_histogram_name_bucket{alpha="a",beta="b",le="2.5"} 9`)) 174 Expect(string(bytes)).To(ContainSubstring(`peer_playground_histogram_name_bucket{alpha="a",beta="b",le="5"} 10`)) 175 Expect(string(bytes)).To(ContainSubstring(`peer_playground_histogram_name_bucket{alpha="a",beta="b",le="10"} 11`)) 176 Expect(string(bytes)).To(ContainSubstring(`peer_playground_histogram_name_bucket{alpha="a",beta="b",le="+Inf"} 12`)) 177 Expect(string(bytes)).To(ContainSubstring(`peer_playground_histogram_name_sum{alpha="a",beta="b"} `)) 178 Expect(string(bytes)).To(ContainSubstring(`peer_playground_histogram_name_count{alpha="a",beta="b"} 12`)) 179 }) 180 181 It("creates histogram with buckets that support labels", func() { 182 histogramOpts.Buckets = []float64{1, 5} 183 histogram := p.NewHistogram(histogramOpts) 184 185 histogram.With("alpha", "a", "beta", "b").Observe(0.5) 186 histogram.With("alpha", "a", "beta", "b").Observe(4.5) 187 188 resp, err := client.Get(fmt.Sprintf("http://%s/metrics", server.Listener.Addr().String())) 189 Expect(err).NotTo(HaveOccurred()) 190 defer resp.Body.Close() 191 192 bytes, err := ioutil.ReadAll(resp.Body) 193 Expect(err).NotTo(HaveOccurred()) 194 Expect(string(bytes)).To(ContainSubstring(`# HELP peer_playground_histogram_name This is some help text for the gauge`)) 195 Expect(string(bytes)).To(ContainSubstring(`# TYPE peer_playground_histogram_name histogram`)) 196 Expect(string(bytes)).To(ContainSubstring(`peer_playground_histogram_name_bucket{alpha="a",beta="b",le="1"} 1`)) 197 Expect(string(bytes)).To(ContainSubstring(`peer_playground_histogram_name_bucket{alpha="a",beta="b",le="5"} 2`)) 198 Expect(string(bytes)).To(ContainSubstring(`peer_playground_histogram_name_sum{alpha="a",beta="b"} 5`)) 199 Expect(string(bytes)).To(ContainSubstring(`peer_playground_histogram_name_count{alpha="a",beta="b"} 2`)) 200 }) 201 }) 202 203 // This helps ensure the label cardinality behavior matches what was implemented 204 // for statsd. If these tests fail, correspending updates will be needed in the label 205 // processing used for statsd. 206 Describe("edge case behavior", func() { 207 var counterOpts commonmetrics.CounterOpts 208 209 BeforeEach(func() { 210 counterOpts = commonmetrics.CounterOpts{ 211 Namespace: "peer", 212 Subsystem: "playground", 213 Name: "counter_name", 214 Help: "This is some help text for the counter", 215 LabelNames: []string{"alpha", "beta"}, 216 } 217 }) 218 Context("when With is called without a label value", func() { 219 It("uses unknown for the missing value", func() { 220 counter := p.NewCounter(counterOpts) 221 counter.With("alpha", "a", "beta").Add(1) 222 resp, err := client.Get(fmt.Sprintf("http://%s/metrics", server.Listener.Addr().String())) 223 Expect(err).NotTo(HaveOccurred()) 224 defer resp.Body.Close() 225 226 bytes, err := ioutil.ReadAll(resp.Body) 227 Expect(err).NotTo(HaveOccurred()) 228 Expect(string(bytes)).To(ContainSubstring(`# HELP peer_playground_counter_name This is some help text for the counter`)) 229 Expect(string(bytes)).To(ContainSubstring(`# TYPE peer_playground_counter_name counter`)) 230 Expect(string(bytes)).To(ContainSubstring(`peer_playground_counter_name{alpha="a",beta="unknown"} 1`)) 231 }) 232 }) 233 234 Context("when With is called with an extra label", func() { 235 It("panics", func() { 236 counter := p.NewCounter(counterOpts) 237 panicMessage := func() (panicMessage interface{}) { 238 defer func() { panicMessage = recover() }() 239 counter.With("alpha", "a", "beta", "b", "charlie", "c").Add(1) 240 return 241 }() 242 Expect(panicMessage).To(MatchError(MatchRegexp(`inconsistent label cardinality: expected 2 label values but got 3 in prometheus.Labels\{.*\}`))) 243 }) 244 }) 245 246 Context("when label values are not provided", func() { 247 It("it panics with a cardinaility message", func() { 248 counter := p.NewCounter(counterOpts) 249 panicMessage := func() (panicMessage interface{}) { 250 defer func() { panicMessage = recover() }() 251 counter.Add(1) 252 return 253 }() 254 Expect(panicMessage).To(MatchError(`inconsistent label cardinality: expected 2 label values but got 0 in prometheus.Labels{}`)) 255 }) 256 }) 257 }) 258 })