github.com/lzy4123/fabric@v2.1.1+incompatible/common/metrics/statsd/provider_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package statsd_test 8 9 import ( 10 "bytes" 11 "fmt" 12 "strings" 13 14 kitstatsd "github.com/go-kit/kit/metrics/statsd" 15 "github.com/hyperledger/fabric/common/metrics" 16 "github.com/hyperledger/fabric/common/metrics/statsd" 17 . "github.com/onsi/ginkgo" 18 . "github.com/onsi/gomega" 19 ) 20 21 var _ = Describe("Provider", func() { 22 var ( 23 s *kitstatsd.Statsd 24 provider *statsd.Provider 25 ) 26 27 BeforeEach(func() { 28 s = kitstatsd.New("", nil) 29 provider = &statsd.Provider{Statsd: s} 30 }) 31 32 It("implements metrics.Provider", func() { 33 var p metrics.Provider = &statsd.Provider{} 34 Expect(p).NotTo(BeNil()) 35 }) 36 37 Describe("NewCounter", func() { 38 var counterOpts metrics.CounterOpts 39 40 BeforeEach(func() { 41 counterOpts = metrics.CounterOpts{ 42 Namespace: "namespace", 43 Subsystem: "subsystem", 44 Name: "name", 45 StatsdFormat: "%{#namespace}.%{#subsystem}.%{#name}.%{alpha}.%{beta}", 46 LabelNames: []string{"alpha", "beta"}, 47 } 48 }) 49 50 It("creates counters that include label values in bucket names", func() { 51 counter := provider.NewCounter(counterOpts) 52 for _, alpha := range []string{"x", "y", "z"} { 53 counter.With("alpha", alpha, "beta", "b").Add(1) 54 buf := &bytes.Buffer{} 55 s.WriteTo(buf) 56 Expect(buf.String()).To(Equal(fmt.Sprintf("namespace.subsystem.name.%s.b:%f|c\n", alpha, float64(1)))) 57 } 58 }) 59 60 Context("when a statsd format is not provided", func() { 61 BeforeEach(func() { 62 counterOpts.LabelNames = nil 63 counterOpts.StatsdFormat = "" 64 }) 65 66 It("uses the default format", func() { 67 counter := provider.NewCounter(counterOpts) 68 counter.Add(1) 69 70 buf := &bytes.Buffer{} 71 s.WriteTo(buf) 72 Expect(buf.String()).To(Equal("namespace.subsystem.name:1.000000|c\n")) 73 }) 74 }) 75 76 Context("when label values are not specified in counter options", func() { 77 BeforeEach(func() { 78 counterOpts.LabelNames = nil 79 counterOpts.StatsdFormat = "%{#namespace}.%{#subsystem}.%{#name}" 80 }) 81 82 It("creates counters that do not require calls to With", func() { 83 counter := provider.NewCounter(counterOpts) 84 for i := 0; i < 10; i++ { 85 counter.Add(float64(i)) 86 87 buf := &bytes.Buffer{} 88 s.WriteTo(buf) 89 Expect(buf.String()).To(Equal(fmt.Sprintf("namespace.subsystem.name:%f|c\n", float64(i)))) 90 } 91 }) 92 }) 93 94 Context("when labels are specified and with is not called", func() { 95 It("panics with an appropriate message when Add is called", func() { 96 counter := provider.NewCounter(counterOpts) 97 panicMessage := func() (panicMessage interface{}) { 98 defer func() { panicMessage = recover() }() 99 counter.Add(1) 100 return 101 }() 102 Expect(panicMessage).To(Equal("label values must be provided by calling With")) 103 }) 104 }) 105 }) 106 107 Describe("NewGauge", func() { 108 var gaugeOpts metrics.GaugeOpts 109 110 BeforeEach(func() { 111 gaugeOpts = metrics.GaugeOpts{ 112 Namespace: "namespace", 113 Subsystem: "subsystem", 114 Name: "name", 115 StatsdFormat: "%{#namespace}.%{#subsystem}.%{#name}.%{alpha}.%{beta}", 116 LabelNames: []string{"alpha", "beta"}, 117 } 118 }) 119 120 It("creates gauges that support Set with label values in bucket names", func() { 121 gauge := provider.NewGauge(gaugeOpts) 122 for i := 1; i <= 5; i++ { 123 for _, alpha := range []string{"x", "y", "z"} { 124 gauge.With("alpha", alpha, "beta", "b").Set(float64(i)) 125 buf := &bytes.Buffer{} 126 s.WriteTo(buf) 127 Expect(buf.String()).To(Equal(fmt.Sprintf("namespace.subsystem.name.%s.b:%f|g\n", alpha, float64(i)))) 128 } 129 } 130 }) 131 132 It("creates gauges that support Add with label values in bucket names", func() { 133 gauge := provider.NewGauge(gaugeOpts) 134 135 for _, alpha := range []string{"x", "y", "z"} { 136 gauge.With("alpha", alpha, "beta", "b").Set(float64(1.0)) 137 } 138 for _, alpha := range []string{"x", "y", "z"} { 139 for i := 0; i < 5; i++ { 140 gauge.With("alpha", alpha, "beta", "b").Add(float64(1.0)) 141 } 142 } 143 buf := &bytes.Buffer{} 144 s.WriteTo(buf) 145 Expect(strings.SplitN(buf.String(), "\n", -1)).To(ConsistOf( 146 Equal("namespace.subsystem.name.x.b:6.000000|g"), 147 Equal("namespace.subsystem.name.y.b:6.000000|g"), 148 Equal("namespace.subsystem.name.z.b:6.000000|g"), 149 Equal(""), 150 )) 151 }) 152 153 Context("when a statsd format is not provided", func() { 154 BeforeEach(func() { 155 gaugeOpts.LabelNames = nil 156 gaugeOpts.StatsdFormat = "" 157 }) 158 159 It("uses the default format", func() { 160 gauge := provider.NewGauge(gaugeOpts) 161 gauge.Set(1) 162 163 buf := &bytes.Buffer{} 164 s.WriteTo(buf) 165 Expect(buf.String()).To(Equal("namespace.subsystem.name:1.000000|g\n")) 166 }) 167 }) 168 169 Context("when label values are not specified in gauge options", func() { 170 BeforeEach(func() { 171 gaugeOpts.LabelNames = nil 172 gaugeOpts.StatsdFormat = "%{#namespace}.%{#subsystem}.%{#name}" 173 }) 174 175 It("creates gauges that do not require calls to With", func() { 176 gauge := provider.NewGauge(gaugeOpts) 177 for i := 0; i < 10; i++ { 178 gauge.Add(float64(i)) 179 180 buf := &bytes.Buffer{} 181 s.WriteTo(buf) 182 Expect(buf.String()).To(Equal(fmt.Sprintf("namespace.subsystem.name:%f|g\n", float64(i)))) 183 } 184 }) 185 }) 186 187 Context("when labels are specified and with is not called", func() { 188 It("panics with an appropriate message when Add is called", func() { 189 gauge := provider.NewGauge(gaugeOpts) 190 panicMessage := func() (panicMessage interface{}) { 191 defer func() { panicMessage = recover() }() 192 gauge.Add(float64(1)) 193 return 194 }() 195 Expect(panicMessage).To(Equal("label values must be provided by calling With")) 196 }) 197 198 It("panics with an appropriate message when Set is called", func() { 199 gauge := provider.NewGauge(gaugeOpts) 200 panicMessage := func() (panicMessage interface{}) { 201 defer func() { panicMessage = recover() }() 202 gauge.Set(float64(1)) 203 return 204 }() 205 Expect(panicMessage).To(Equal("label values must be provided by calling With")) 206 }) 207 }) 208 }) 209 210 Describe("NewHistogram", func() { 211 var histogramOpts metrics.HistogramOpts 212 213 BeforeEach(func() { 214 histogramOpts = metrics.HistogramOpts{ 215 Namespace: "namespace", 216 Subsystem: "subsystem", 217 Name: "name", 218 StatsdFormat: "%{#namespace}.%{#subsystem}.%{#name}.%{alpha}.%{beta}", 219 LabelNames: []string{"alpha", "beta"}, 220 } 221 }) 222 223 It("creates histograms that support Observe with label values in bucket names", func() { 224 histogram := provider.NewHistogram(histogramOpts) 225 for i := 1; i <= 5; i++ { 226 for _, alpha := range []string{"x", "y", "z"} { 227 histogram.With("alpha", alpha, "beta", "b").Observe(float64(i)) 228 buf := &bytes.Buffer{} 229 s.WriteTo(buf) 230 Expect(buf.String()).To(Equal(fmt.Sprintf("namespace.subsystem.name.%s.b:%f|ms\n", alpha, float64(i)))) 231 } 232 } 233 }) 234 235 Context("when a statsd format is not provided", func() { 236 BeforeEach(func() { 237 histogramOpts.LabelNames = nil 238 histogramOpts.StatsdFormat = "" 239 }) 240 241 It("uses the default format", func() { 242 histogram := provider.NewHistogram(histogramOpts) 243 histogram.Observe(1) 244 245 buf := &bytes.Buffer{} 246 s.WriteTo(buf) 247 Expect(buf.String()).To(Equal("namespace.subsystem.name:1.000000|ms\n")) 248 }) 249 }) 250 251 Context("when label values are not specified in counter options", func() { 252 BeforeEach(func() { 253 histogramOpts.LabelNames = nil 254 histogramOpts.StatsdFormat = "%{#namespace}.%{#subsystem}.%{#name}" 255 }) 256 257 It("creates histograms that do not require calls to With", func() { 258 histogram := provider.NewHistogram(histogramOpts) 259 for i := 0; i < 10; i++ { 260 histogram.Observe(float64(i)) 261 262 buf := &bytes.Buffer{} 263 s.WriteTo(buf) 264 Expect(buf.String()).To(Equal(fmt.Sprintf("namespace.subsystem.name:%f|ms\n", float64(i)))) 265 } 266 }) 267 }) 268 269 Context("when labels are specified and with is not called", func() { 270 It("panics with an appropriate message when Observe is called", func() { 271 histogram := provider.NewHistogram(histogramOpts) 272 panicMessage := func() (panicMessage interface{}) { 273 defer func() { panicMessage = recover() }() 274 histogram.Observe(float64(1)) 275 return 276 }() 277 Expect(panicMessage).To(Equal("label values must be provided by calling With")) 278 }) 279 }) 280 }) 281 })