dubbo.apache.org/dubbo-go/v3@v3.1.1/metrics/prometheus/rt_vec_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  	"reflect"
    22  	"sync"
    23  	"testing"
    24  )
    25  
    26  import (
    27  	prom "github.com/prometheus/client_golang/prometheus"
    28  
    29  	"github.com/stretchr/testify/assert"
    30  )
    31  
    32  import (
    33  	"dubbo.apache.org/dubbo-go/v3/metrics/util/aggregate"
    34  )
    35  
    36  func TestRtVecCollect(t *testing.T) {
    37  	opts := &RtOpts{
    38  		Name:              "request_num",
    39  		bucketNum:         10,
    40  		timeWindowSeconds: 120,
    41  		Help:              "Request cost",
    42  	}
    43  	labels := []string{"app", "version"}
    44  	vecs := [2]*RtVec{NewRtVec(opts, labels), NewAggRtVec(opts, labels)}
    45  	for _, r := range vecs {
    46  		r.With(map[string]string{"app": "dubbo", "version": "1.0.0"}).Observe(100)
    47  		ch := make(chan prom.Metric, len(r.metrics))
    48  		r.Collect(ch)
    49  		close(ch)
    50  		assert.Equal(t, len(ch), len(r.metrics))
    51  		for _, m := range r.metrics {
    52  			metric, ok := <-ch
    53  			if !ok {
    54  				t.Error("not enough metrics")
    55  			} else {
    56  				str := metric.Desc().String()
    57  				assert.Contains(t, str, m.nameSuffix)
    58  				assert.Contains(t, str, m.helpPrefix)
    59  				assert.Contains(t, str, "app")
    60  				assert.Contains(t, str, "version")
    61  			}
    62  		}
    63  	}
    64  }
    65  
    66  func TestRtVecDescribe(t *testing.T) {
    67  	opts := &RtOpts{
    68  		Name:              "request_num",
    69  		bucketNum:         10,
    70  		timeWindowSeconds: 120,
    71  		Help:              "Request cost",
    72  	}
    73  	labels := []string{"app", "version"}
    74  	vecs := [2]*RtVec{NewRtVec(opts, labels), NewAggRtVec(opts, labels)}
    75  	for _, r := range vecs {
    76  		ch := make(chan *prom.Desc, len(r.metrics))
    77  		r.Describe(ch)
    78  		close(ch)
    79  		assert.Equal(t, len(ch), len(r.metrics))
    80  		for _, m := range r.metrics {
    81  			desc, ok := <-ch
    82  			if !ok {
    83  				t.Error(t, "not enough desc")
    84  			} else {
    85  				str := desc.String()
    86  				assert.Contains(t, str, m.nameSuffix)
    87  				assert.Contains(t, str, m.helpPrefix)
    88  				assert.Contains(t, str, "app")
    89  				assert.Contains(t, str, "version")
    90  			}
    91  		}
    92  	}
    93  }
    94  
    95  func TestValueObserve(t *testing.T) {
    96  	rts := []*Rt{
    97  		{
    98  			tags: map[string]string{},
    99  			obs:  &aggResult{agg: aggregate.NewTimeWindowAggregator(10, 10)},
   100  		},
   101  		{
   102  			tags: map[string]string{},
   103  			obs:  &valueResult{val: aggregate.NewResult()},
   104  		},
   105  	}
   106  	want := &aggregate.Result{
   107  		Avg:   1,
   108  		Min:   1,
   109  		Max:   1,
   110  		Count: 1,
   111  		Total: 1,
   112  		Last:  1,
   113  	}
   114  	for i, v := range rts {
   115  		v.Observe(float64(1))
   116  		r := v.obs.result()
   117  		if i == 0 {
   118  			r.Last = 1 // agg result no Last, value is NaN
   119  		}
   120  		if !reflect.DeepEqual(r, want) {
   121  			t.Errorf("Result() = %v, want %v", r, want)
   122  		}
   123  	}
   124  }
   125  
   126  func TestRtVecWith(t *testing.T) {
   127  	opts := &RtOpts{
   128  		Name:              "request_num",
   129  		bucketNum:         10,
   130  		timeWindowSeconds: 120,
   131  		Help:              "Request cost",
   132  	}
   133  	labels := []string{"app", "version"}
   134  	vecs := [2]*RtVec{NewRtVec(opts, labels), NewAggRtVec(opts, labels)}
   135  	tags := map[string]string{"app": "dubbo", "version": "1.0.0"}
   136  	for _, r := range vecs {
   137  		first := r.With(tags)
   138  		second := r.With(tags)
   139  		assert.True(t, first == second) // init once
   140  	}
   141  }
   142  
   143  func TestRtVecWithConcurrent(t *testing.T) {
   144  	opts := &RtOpts{
   145  		Name:              "request_num",
   146  		bucketNum:         10,
   147  		timeWindowSeconds: 120,
   148  		Help:              "Request cost",
   149  	}
   150  	labels := []string{"app", "version"}
   151  	labelValues := map[string]string{"app": "dubbo", "version": "1.0.0"}
   152  	vecs := [2]*RtVec{NewRtVec(opts, labels), NewAggRtVec(opts, labels)}
   153  	for _, r := range vecs {
   154  		var wg sync.WaitGroup
   155  		for i := 0; i < 10; i++ {
   156  			wg.Add(1)
   157  			go func() {
   158  				r.With(labelValues).Observe(100)
   159  				wg.Done()
   160  			}()
   161  		}
   162  		wg.Wait()
   163  		res := r.With(labelValues).(*Rt).obs.result()
   164  		assert.True(t, res.Count == uint64(10))
   165  	}
   166  }