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  })