github.com/GuanceCloud/cliutils@v1.1.21/metrics/metrics_test.go (about) 1 // Unless explicitly stated otherwise all files in this repository are licensed 2 // under the MIT License. 3 // This product includes software developed at Guance Cloud (https://www.guance.com/). 4 // Copyright 2021-present Guance, Inc. 5 6 package metrics 7 8 import ( 9 "bytes" 10 "path/filepath" 11 "sync" 12 T "testing" 13 14 "github.com/prometheus/client_golang/prometheus" 15 "github.com/prometheus/common/expfmt" 16 "github.com/stretchr/testify/assert" 17 ) 18 19 func TestHistogram(t *T.T) { 20 t.Run(`basic`, func(t *T.T) { 21 vec := prometheus.NewHistogramVec( 22 prometheus.HistogramOpts{ 23 Name: filepath.Base(t.Name()), 24 }, 25 []string{"api", "status"}, 26 ) 27 28 reg := prometheus.NewRegistry() 29 reg.MustRegister(vec) 30 31 div := 10000.0 32 33 for i := 0; i < 1000; i++ { 34 switch i % 3 { 35 case 0: 36 vec.WithLabelValues("/v1/write/metric", "ok").Observe(float64(i) / div) 37 case 1: 38 vec.WithLabelValues("/v1/write/logging", "ok").Observe(float64(i) / div) 39 default: 40 vec.WithLabelValues("/v1/write/tracing", "ok").Observe(float64(i) / div) 41 } 42 } 43 44 mfs, err := reg.Gather() 45 assert.NoError(t, err) 46 buf := bytes.NewBuffer(nil) 47 for _, mf := range mfs { 48 expfmt.MetricFamilyToText(buf, mf) 49 } 50 t.Logf("text:\n%s", buf.String()) 51 52 buf = bytes.NewBuffer(nil) 53 for _, mf := range mfs { 54 expfmt.MetricFamilyToOpenMetrics(buf, mf) 55 } 56 t.Logf("open metrics:\n%s", buf.String()) 57 }) 58 } 59 60 func TestConcurrentAdd(t *T.T) { 61 t.Run(`concurrent_set`, func(t *T.T) { 62 vec := prometheus.NewCounterVec( 63 prometheus.CounterOpts{ 64 Name: filepath.Base(t.Name()), 65 }, 66 []string{"api", "status"}, 67 ) 68 69 reg := prometheus.NewRegistry() 70 reg.MustRegister(vec) 71 72 var ( 73 nwrk = 10 74 wg sync.WaitGroup 75 max = 10 76 ) 77 78 wg.Add(nwrk) 79 for i := 0; i < nwrk; i++ { 80 go func() { 81 defer wg.Done() 82 83 n := 0 84 for { 85 vec.WithLabelValues("/v1/write/abc", "ok").Add(1.0) 86 n++ 87 if n >= max { 88 return 89 } 90 } 91 }() 92 } 93 94 wg.Wait() 95 mfs, err := reg.Gather() 96 assert.NoError(t, err) 97 98 m := GetMetricOnLabels(mfs, filepath.Base(t.Name()), `/v1/write/abc`, `ok`) 99 assert.NotNil(t, m) 100 assert.Equal(t, float64(nwrk*max), m.GetCounter().GetValue()) 101 }) 102 } 103 104 func TestAdd(t *T.T) { 105 t.Run(`add_count`, func(t *T.T) { 106 vec := prometheus.NewSummaryVec( 107 prometheus.SummaryOpts{ 108 Help: "not-set", 109 Name: filepath.Base(t.Name()), 110 }, 111 []string{"api", "status"}, 112 ) 113 114 reg := prometheus.NewRegistry() 115 reg.MustRegister(vec) 116 for i := 0; i < 100; i++ { 117 vec.WithLabelValues("/v1/write/abc", "ok").Observe(float64(i)) 118 vec.WithLabelValues("/v1/write/def", "fail").Observe(float64(100 - i)) 119 } 120 121 mfs, err := reg.Gather() 122 assert.NoError(t, err) 123 124 for _, mf := range mfs { 125 t.Logf("metric: %s", mf.String()) 126 } 127 128 m := GetMetricOnLabels(mfs, filepath.Base(t.Name()), "/v1/write/abc", "ok") 129 assert.NotNil(t, m) 130 assert.Equal(t, uint64(100), m.GetSummary().GetSampleCount()) 131 132 m = GetMetricOnLabels(mfs, filepath.Base(t.Name()), "/v1/write/def", "fail") 133 assert.NotNil(t, m) 134 assert.Equal(t, uint64(100), m.GetSummary().GetSampleCount()) 135 }) 136 } 137 138 func BenchmarkAddValue(b *T.B) { 139 b.Run(`summary_with_2_labels`, func(b *T.B) { 140 b.StopTimer() 141 vec := prometheus.NewSummaryVec( 142 prometheus.SummaryOpts{ 143 Namespace: "ns1", 144 Subsystem: "subsys", 145 Help: "not-set", 146 Name: filepath.Base(b.Name()), 147 }, 148 []string{"api", "status"}, 149 ) 150 151 reg := prometheus.NewRegistry() 152 reg.MustRegister(vec) 153 154 b.StartTimer() 155 for i := 0; i < b.N; i++ { 156 vec.WithLabelValues("/v1/write/abc", "ok").Observe(123.4) 157 vec.WithLabelValues("/v1/write/def", "fail").Observe(456.7) 158 } 159 160 b.StopTimer() 161 162 mfs, err := reg.Gather() 163 assert.NoError(b, err) 164 for _, mf := range mfs { 165 b.Logf("metric: %s", mf.String()) 166 } 167 }) 168 169 b.Run(`count_with_2_labels`, func(b *T.B) { 170 b.StopTimer() 171 vec := prometheus.NewCounterVec( 172 prometheus.CounterOpts{ 173 Namespace: "ns1", 174 Subsystem: "subsys", 175 Help: "not-set", 176 Name: filepath.Base(b.Name()), 177 }, 178 []string{"api", "status"}, 179 ) 180 181 reg := prometheus.NewRegistry() 182 reg.MustRegister(vec) 183 184 b.StartTimer() 185 for i := 0; i < b.N; i++ { 186 vec.WithLabelValues("/v1/write/a", "ok").Add(123.4) 187 vec.WithLabelValues("/v1/write/b", "fail").Add(456.7) 188 } 189 190 b.StopTimer() 191 192 mfs, err := reg.Gather() 193 assert.NoError(b, err) 194 for _, mf := range mfs { 195 b.Logf("metric: %s", mf.String()) 196 } 197 }) 198 199 b.Run("para", func(b *T.B) { 200 b.StopTimer() 201 vec := prometheus.NewCounterVec( 202 prometheus.CounterOpts{ 203 Namespace: "ns1", 204 Subsystem: "subsys", 205 Name: filepath.Base(b.Name()), 206 }, 207 []string{"api", "status"}, 208 ) 209 210 reg := prometheus.NewRegistry() 211 reg.MustRegister(vec) 212 213 b.StartTimer() 214 b.RunParallel(func(pb *T.PB) { 215 for pb.Next() { 216 vec.WithLabelValues("/v1/write/a", "ok").Add(123.4) 217 vec.WithLabelValues("/v1/write/b", "fail").Add(456.7) 218 } 219 }) 220 221 b.StopTimer() 222 223 mfs, err := reg.Gather() 224 assert.NoError(b, err) 225 for _, mf := range mfs { 226 b.Logf("metric: %s", mf.String()) 227 } 228 }) 229 }