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  }