dubbo.apache.org/dubbo-go/v3@v3.1.1/metrics/prometheus/registry_test.go (about) 1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package prometheus 19 20 import ( 21 "io" 22 "net/http" 23 "sync" 24 "testing" 25 "time" 26 ) 27 28 import ( 29 prom "github.com/prometheus/client_golang/prometheus" 30 31 "github.com/stretchr/testify/assert" 32 ) 33 34 import ( 35 "dubbo.apache.org/dubbo-go/v3/common" 36 "dubbo.apache.org/dubbo-go/v3/common/constant" 37 "dubbo.apache.org/dubbo-go/v3/metrics" 38 ) 39 40 var ( 41 tags = map[string]string{"app": "dubbo", "version": "1.0.0"} 42 metricId = &metrics.MetricId{Name: "dubbo_request", Desc: "request", Tags: tags} 43 url = common.NewURLWithOptions( 44 common.WithProtocol(constant.ProtocolPrometheus), 45 common.WithParamsValue(constant.PrometheusExporterEnabledKey, "true"), 46 common.WithParamsValue(constant.PrometheusExporterMetricsPortKey, "9999"), 47 common.WithParamsValue(constant.PrometheusExporterMetricsPathKey, "/prometheus"), 48 common.WithParamsValue(constant.ApplicationKey, "dubbo"), 49 common.WithParamsValue(constant.AppVersionKey, "1.0.0"), 50 common.WithParamsValue(constant.PrometheusPushgatewayEnabledKey, "true"), 51 common.WithParamsValue(constant.PrometheusPushgatewayBaseUrlKey, "localhost:9091"), 52 common.WithParamsValue(constant.PrometheusPushgatewayUsernameKey, ""), 53 common.WithParamsValue(constant.PrometheusPushgatewayPasswordKey, ""), 54 common.WithParamsValue(constant.PrometheusPushgatewayPushIntervalKey, "2"), 55 common.WithParamsValue(constant.PrometheusPushgatewayJobKey, "dubbo-push"), 56 ) 57 ) 58 59 func TestPromMetricRegistryCounter(t *testing.T) { 60 p := NewPromMetricRegistry(prom.NewRegistry(), url) 61 p.Counter(metricId).Inc() 62 text, err := p.Scrape() 63 assert.Nil(t, err) 64 assert.Contains(t, text, "# HELP dubbo_request request\n# TYPE dubbo_request counter") 65 assert.Contains(t, text, `dubbo_request{app="dubbo",version="1.0.0"} 1`) 66 } 67 68 func TestPromMetricRegistryGauge(t *testing.T) { 69 p := NewPromMetricRegistry(prom.NewRegistry(), url) 70 p.Gauge(metricId).Set(100) 71 text, err := p.Scrape() 72 assert.Nil(t, err) 73 assert.Contains(t, text, "# HELP dubbo_request request\n# TYPE dubbo_request gauge") 74 assert.Contains(t, text, `dubbo_request{app="dubbo",version="1.0.0"} 100`) 75 76 } 77 78 func TestPromMetricRegistryHistogram(t *testing.T) { 79 p := NewPromMetricRegistry(prom.NewRegistry(), url) 80 p.Histogram(metricId).Observe(100) 81 text, err := p.Scrape() 82 assert.Nil(t, err) 83 assert.Contains(t, text, "# HELP dubbo_request request\n# TYPE dubbo_request histogram") 84 assert.Contains(t, text, `dubbo_request_bucket{app="dubbo",version="1.0.0",le="+Inf"} 1`) 85 assert.Contains(t, text, `dubbo_request_sum{app="dubbo",version="1.0.0"} 100`) 86 assert.Contains(t, text, `dubbo_request_count{app="dubbo",version="1.0.0"} 1`) 87 } 88 89 func TestPromMetricRegistrySummary(t *testing.T) { 90 p := NewPromMetricRegistry(prom.NewRegistry(), url) 91 p.Summary(metricId).Observe(100) 92 text, err := p.Scrape() 93 assert.Nil(t, err) 94 assert.Contains(t, text, "# HELP dubbo_request request\n# TYPE dubbo_request summary") 95 assert.Contains(t, text, "dubbo_request_sum{app=\"dubbo\",version=\"1.0.0\"} 100") 96 assert.Contains(t, text, "dubbo_request_count{app=\"dubbo\",version=\"1.0.0\"} 1") 97 } 98 99 func TestPromMetricRegistryRt(t *testing.T) { 100 p := NewPromMetricRegistry(prom.NewRegistry(), url) 101 for i := 0; i < 10; i++ { 102 p.Rt(metricId, &metrics.RtOpts{}).Observe(10 * float64(i)) 103 } 104 text, err := p.Scrape() 105 assert.Nil(t, err) 106 assert.Contains(t, text, "# HELP dubbo_request_avg Average request\n# TYPE dubbo_request_avg gauge\ndubbo_request_avg{app=\"dubbo\",version=\"1.0.0\"} 45") 107 assert.Contains(t, text, "# HELP dubbo_request_last Last request\n# TYPE dubbo_request_last gauge\ndubbo_request_last{app=\"dubbo\",version=\"1.0.0\"} 90") 108 assert.Contains(t, text, "# HELP dubbo_request_max Max request\n# TYPE dubbo_request_max gauge\ndubbo_request_max{app=\"dubbo\",version=\"1.0.0\"} 90") 109 assert.Contains(t, text, "# HELP dubbo_request_min Min request\n# TYPE dubbo_request_min gauge\ndubbo_request_min{app=\"dubbo\",version=\"1.0.0\"} 0") 110 assert.Contains(t, text, "# HELP dubbo_request_sum Sum request\n# TYPE dubbo_request_sum gauge\ndubbo_request_sum{app=\"dubbo\",version=\"1.0.0\"} 450") 111 112 p = NewPromMetricRegistry(prom.NewRegistry(), url) 113 for i := 0; i < 10; i++ { 114 p.Rt(metricId, &metrics.RtOpts{Aggregate: true, BucketNum: 10, TimeWindowSeconds: 60}).Observe(10 * float64(i)) 115 } 116 text, err = p.Scrape() 117 assert.Nil(t, err) 118 assert.Contains(t, text, "# HELP dubbo_request_avg_milliseconds_aggregate The average request\n# TYPE dubbo_request_avg_milliseconds_aggregate gauge\ndubbo_request_avg_milliseconds_aggregate{app=\"dubbo\",version=\"1.0.0\"} 45") 119 assert.Contains(t, text, "# HELP dubbo_request_max_milliseconds_aggregate The maximum request\n# TYPE dubbo_request_max_milliseconds_aggregate gauge\ndubbo_request_max_milliseconds_aggregate{app=\"dubbo\",version=\"1.0.0\"} 90") 120 assert.Contains(t, text, "# HELP dubbo_request_min_milliseconds_aggregate The minimum request\n# TYPE dubbo_request_min_milliseconds_aggregate gauge\ndubbo_request_min_milliseconds_aggregate{app=\"dubbo\",version=\"1.0.0\"} 0") 121 } 122 123 func TestPromMetricRegistryCounterConcurrent(t *testing.T) { 124 p := NewPromMetricRegistry(prom.NewRegistry(), url) 125 var wg sync.WaitGroup 126 for i := 0; i < 10; i++ { 127 wg.Add(1) 128 go func() { 129 p.Counter(metricId).Inc() 130 wg.Done() 131 }() 132 } 133 wg.Wait() 134 text, err := p.Scrape() 135 assert.Nil(t, err) 136 assert.Contains(t, text, "# HELP dubbo_request request\n# TYPE dubbo_request counter") 137 assert.Contains(t, text, `dubbo_request{app="dubbo",version="1.0.0"} 10`) 138 } 139 140 func TestPromMetricRegistryExport(t *testing.T) { 141 p := NewPromMetricRegistry(prom.NewRegistry(), url) 142 go func() { 143 for { 144 p.Rt(metricId, &metrics.RtOpts{}).Observe(10 * float64(1)) 145 time.Sleep(1 * time.Second) 146 } 147 }() 148 p.Export() 149 // test push 150 var wg sync.WaitGroup 151 wg.Add(1) 152 go func() { 153 err := http.ListenAndServe(url.GetParam(constant.PrometheusPushgatewayBaseUrlKey, ""), 154 http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 155 bodyBytes, err := io.ReadAll(r.Body) 156 assert.Nil(t, err) 157 text := string(bodyBytes) 158 assert.Contains(t, text, "dubbo_request_avg") 159 wg.Done() 160 })) 161 assert.Nil(t, err) 162 }() 163 timeout := url.GetParamByIntValue(constant.PrometheusPushgatewayPushIntervalKey, constant.PrometheusDefaultPushInterval) 164 if waitTimeout(&wg, time.Duration(timeout+1)*time.Second) { 165 assert.Fail(t, "wait pushgateway data timeout") 166 } 167 // test pull 168 resp, err := http.Get("http://localhost:" + 169 url.GetParam(constant.PrometheusExporterMetricsPortKey, constant.PrometheusDefaultMetricsPort) + 170 url.GetParam(constant.PrometheusExporterMetricsPathKey, constant.PrometheusDefaultMetricsPath), 171 ) 172 assert.Nil(t, err) 173 defer resp.Body.Close() 174 bodyBytes, err := io.ReadAll(resp.Body) 175 assert.Nil(t, err) 176 text := string(bodyBytes) 177 assert.Contains(t, text, "dubbo_request_avg") 178 } 179 180 func waitTimeout(wg *sync.WaitGroup, timeout time.Duration) bool { 181 c := make(chan struct{}) 182 go func() { 183 defer close(c) 184 wg.Wait() 185 }() 186 select { 187 case <-c: 188 return false // completed normally 189 case <-time.After(timeout): 190 return true // timed out 191 } 192 }