blob: 8964798f99aa5ab33d153cd9e78531b475242a01 [file] [log] [blame]
/*
* 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))
}
}