| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package prometheus |
| |
| import ( |
| "reflect" |
| "sync" |
| "testing" |
| ) |
| |
| import ( |
| prom "github.com/prometheus/client_golang/prometheus" |
| |
| "github.com/stretchr/testify/assert" |
| ) |
| |
| import ( |
| "dubbo.apache.org/dubbo-go/v3/metrics/util/aggregate" |
| ) |
| |
| func TestRtVecCollect(t *testing.T) { |
| opts := &RtOpts{ |
| Name: "request_num", |
| bucketNum: 10, |
| timeWindowSeconds: 120, |
| Help: "Request cost", |
| } |
| labels := []string{"app", "version"} |
| vecs := [2]*RtVec{NewRtVec(opts, labels), NewAggRtVec(opts, labels)} |
| for _, r := range vecs { |
| r.With(map[string]string{"app": "dubbo", "version": "1.0.0"}).Observe(100) |
| ch := make(chan prom.Metric, len(r.metrics)) |
| r.Collect(ch) |
| close(ch) |
| assert.Equal(t, len(ch), len(r.metrics)) |
| for _, m := range r.metrics { |
| metric, ok := <-ch |
| if !ok { |
| t.Error("not enough metrics") |
| } else { |
| str := metric.Desc().String() |
| assert.Contains(t, str, m.nameSuffix) |
| assert.Contains(t, str, m.helpPrefix) |
| assert.Contains(t, str, "app") |
| assert.Contains(t, str, "version") |
| } |
| } |
| } |
| } |
| |
| func TestRtVecDescribe(t *testing.T) { |
| opts := &RtOpts{ |
| Name: "request_num", |
| bucketNum: 10, |
| timeWindowSeconds: 120, |
| Help: "Request cost", |
| } |
| labels := []string{"app", "version"} |
| vecs := [2]*RtVec{NewRtVec(opts, labels), NewAggRtVec(opts, labels)} |
| for _, r := range vecs { |
| ch := make(chan *prom.Desc, len(r.metrics)) |
| r.Describe(ch) |
| close(ch) |
| assert.Equal(t, len(ch), len(r.metrics)) |
| for _, m := range r.metrics { |
| desc, ok := <-ch |
| if !ok { |
| t.Error(t, "not enough desc") |
| } else { |
| str := desc.String() |
| assert.Contains(t, str, m.nameSuffix) |
| assert.Contains(t, str, m.helpPrefix) |
| assert.Contains(t, str, "app") |
| assert.Contains(t, str, "version") |
| } |
| } |
| } |
| } |
| |
| func TestValueObserve(t *testing.T) { |
| rts := []*Rt{ |
| { |
| tags: map[string]string{}, |
| obs: &aggResult{agg: aggregate.NewTimeWindowAggregator(10, 10)}, |
| }, |
| { |
| tags: map[string]string{}, |
| obs: &valueResult{val: aggregate.NewResult()}, |
| }, |
| } |
| want := &aggregate.Result{ |
| Avg: 1, |
| Min: 1, |
| Max: 1, |
| Count: 1, |
| Total: 1, |
| Last: 1, |
| } |
| for i, v := range rts { |
| v.Observe(float64(1)) |
| r := v.obs.result() |
| if i == 0 { |
| r.Last = 1 // agg result no Last, value is NaN |
| } |
| if !reflect.DeepEqual(r, want) { |
| t.Errorf("Result() = %v, want %v", r, want) |
| } |
| } |
| } |
| |
| func TestRtVecWith(t *testing.T) { |
| opts := &RtOpts{ |
| Name: "request_num", |
| bucketNum: 10, |
| timeWindowSeconds: 120, |
| Help: "Request cost", |
| } |
| labels := []string{"app", "version"} |
| vecs := [2]*RtVec{NewRtVec(opts, labels), NewAggRtVec(opts, labels)} |
| tags := map[string]string{"app": "dubbo", "version": "1.0.0"} |
| for _, r := range vecs { |
| first := r.With(tags) |
| second := r.With(tags) |
| assert.True(t, first == second) // init once |
| } |
| } |
| |
| func TestRtVecWithConcurrent(t *testing.T) { |
| opts := &RtOpts{ |
| Name: "request_num", |
| bucketNum: 10, |
| timeWindowSeconds: 120, |
| Help: "Request cost", |
| } |
| labels := []string{"app", "version"} |
| labelValues := map[string]string{"app": "dubbo", "version": "1.0.0"} |
| vecs := [2]*RtVec{NewRtVec(opts, labels), NewAggRtVec(opts, labels)} |
| for _, r := range vecs { |
| var wg sync.WaitGroup |
| for i := 0; i < 10; i++ { |
| wg.Add(1) |
| go func() { |
| r.With(labelValues).Observe(100) |
| wg.Done() |
| }() |
| } |
| wg.Wait() |
| res := r.With(labelValues).(*Rt).obs.result() |
| assert.True(t, res.Count == uint64(10)) |
| } |
| } |