|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- // Copyright 2018, OpenCensus Authors
- //
- // Licensed 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 metric
-
- import (
- "fmt"
- "go.opencensus.io/metric/metricdata"
- "sort"
- "testing"
- "time"
-
- "github.com/google/go-cmp/cmp"
- )
-
- func TestGauge(t *testing.T) {
- r := NewRegistry()
- f, _ := r.AddFloat64Gauge("TestGauge", "", "", "k1", "k2")
- e, _ := f.GetEntry(metricdata.LabelValue{}, metricdata.LabelValue{})
- e.Set(5)
- e, _ = f.GetEntry(metricdata.NewLabelValue("k1v1"), metricdata.LabelValue{})
- e.Add(1)
- e, _ = f.GetEntry(metricdata.NewLabelValue("k1v1"), metricdata.LabelValue{})
- e.Add(1)
- e, _ = f.GetEntry(metricdata.NewLabelValue("k1v2"), metricdata.NewLabelValue("k2v2"))
- e.Add(1)
- m := r.Read()
- want := []*metricdata.Metric{
- {
- Descriptor: metricdata.Descriptor{
- Name: "TestGauge",
- LabelKeys: []string{"k1", "k2"},
- },
- TimeSeries: []*metricdata.TimeSeries{
- {
- LabelValues: []metricdata.LabelValue{
- {}, {},
- },
- Points: []metricdata.Point{
- metricdata.NewFloat64Point(time.Time{}, 5),
- },
- },
- {
- LabelValues: []metricdata.LabelValue{
- metricdata.NewLabelValue("k1v1"),
- {},
- },
- Points: []metricdata.Point{
- metricdata.NewFloat64Point(time.Time{}, 2),
- },
- },
- {
- LabelValues: []metricdata.LabelValue{
- metricdata.NewLabelValue("k1v2"),
- metricdata.NewLabelValue("k2v2"),
- },
- Points: []metricdata.Point{
- metricdata.NewFloat64Point(time.Time{}, 1),
- },
- },
- },
- },
- }
- canonicalize(m)
- canonicalize(want)
- if diff := cmp.Diff(m, want, cmp.Comparer(ignoreTimes)); diff != "" {
- t.Errorf("-got +want: %s", diff)
- }
- }
-
- func TestFloat64Entry_Add(t *testing.T) {
- r := NewRegistry()
- g, _ := r.AddFloat64Gauge("g", "", metricdata.UnitDimensionless)
- e, _ := g.GetEntry()
- e.Add(0)
- ms := r.Read()
- if got, want := ms[0].TimeSeries[0].Points[0].Value.(float64), 0.0; got != want {
- t.Errorf("value = %v, want %v", got, want)
- }
- e, _ = g.GetEntry()
- e.Add(1)
- ms = r.Read()
- if got, want := ms[0].TimeSeries[0].Points[0].Value.(float64), 1.0; got != want {
- t.Errorf("value = %v, want %v", got, want)
- }
- e, _ = g.GetEntry()
- e.Add(-1)
- ms = r.Read()
- if got, want := ms[0].TimeSeries[0].Points[0].Value.(float64), 0.0; got != want {
- t.Errorf("value = %v, want %v", got, want)
- }
- }
-
- func TestFloat64Gauge_Add_NegativeTotals(t *testing.T) {
- r := NewRegistry()
- g, _ := r.AddFloat64Gauge("g", "", metricdata.UnitDimensionless)
- e, _ := g.GetEntry()
- e.Add(-1.0)
- ms := r.Read()
- if got, want := ms[0].TimeSeries[0].Points[0].Value.(float64), float64(0); got != want {
- t.Errorf("value = %v, want %v", got, want)
- }
- }
-
- func TestInt64GaugeEntry_Add(t *testing.T) {
- r := NewRegistry()
- g, _ := r.AddInt64Gauge("g", "", metricdata.UnitDimensionless)
- e, _ := g.GetEntry()
- e.Add(0)
- ms := r.Read()
- if got, want := ms[0].TimeSeries[0].Points[0].Value.(int64), int64(0); got != want {
- t.Errorf("value = %v, want %v", got, want)
- }
- e, _ = g.GetEntry()
- e.Add(1)
- ms = r.Read()
- if got, want := ms[0].TimeSeries[0].Points[0].Value.(int64), int64(1); got != want {
- t.Errorf("value = %v, want %v", got, want)
- }
- }
-
- func TestInt64Gauge_Add_NegativeTotals(t *testing.T) {
- r := NewRegistry()
- g, _ := r.AddInt64Gauge("g", "", metricdata.UnitDimensionless)
- e, _ := g.GetEntry()
- e.Add(-1)
- ms := r.Read()
- if got, want := ms[0].TimeSeries[0].Points[0].Value.(int64), int64(0); got != want {
- t.Errorf("value = %v, want %v", got, want)
- }
- }
-
- func TestGaugeWithSameNameDiffType(t *testing.T) {
- r := NewRegistry()
- r.AddInt64Gauge("g", "", metricdata.UnitDimensionless)
- _, gotErr := r.AddFloat64Gauge("g", "", metricdata.UnitDimensionless)
- if gotErr == nil {
- t.Errorf("got: nil, want error: %v", errGaugeExistsWithDiffType)
- }
- _, gotErr = r.AddInt64DerivedGauge("g", "", metricdata.UnitDimensionless)
- if gotErr == nil {
- t.Errorf("got: nil, want error: %v", errGaugeExistsWithDiffType)
- }
- _, gotErr = r.AddFloat64DerivedGauge("g", "", metricdata.UnitDimensionless)
- if gotErr == nil {
- t.Errorf("got: nil, want error: %v", errGaugeExistsWithDiffType)
- }
- }
-
- func TestGaugeWithLabelMismatch(t *testing.T) {
- r := NewRegistry()
- g, _ := r.AddInt64Gauge("g", "", metricdata.UnitDimensionless, "k1")
- _, gotErr := g.GetEntry(metricdata.NewLabelValue("k1v2"), metricdata.NewLabelValue("k2v2"))
- if gotErr == nil {
- t.Errorf("got: nil, want error: %v", errKeyValueMismatch)
- }
- }
-
- func TestMapKey(t *testing.T) {
- cases := [][]metricdata.LabelValue{
- {},
- {metricdata.LabelValue{}},
- {metricdata.NewLabelValue("")},
- {metricdata.NewLabelValue("-")},
- {metricdata.NewLabelValue(",")},
- {metricdata.NewLabelValue("v1"), metricdata.NewLabelValue("v2")},
- {metricdata.NewLabelValue("v1"), metricdata.LabelValue{}},
- {metricdata.NewLabelValue("v1"), metricdata.LabelValue{}, metricdata.NewLabelValue(string([]byte{0}))},
- {metricdata.LabelValue{}, metricdata.LabelValue{}},
- }
- for i, tc := range cases {
- t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
- g := &gauge{
- keys: make([]string, len(tc)),
- }
- mk := g.mapKey(tc)
- vals := g.labelValues(mk)
- if diff := cmp.Diff(vals, tc); diff != "" {
- t.Errorf("values differ after serialization -got +want: %s", diff)
- }
- })
- }
- }
-
- func TestRaceCondition(t *testing.T) {
- r := NewRegistry()
-
- // start reader before adding Gauge metric.
- var ms = []*metricdata.Metric{}
- for i := 0; i < 5; i++ {
- go func(k int) {
- for j := 0; j < 5; j++ {
- g, _ := r.AddInt64Gauge(fmt.Sprintf("g%d%d", k, j), "", metricdata.UnitDimensionless)
- e, _ := g.GetEntry()
- e.Add(1)
- }
- }(i)
- }
- time.Sleep(1 * time.Second)
- ms = r.Read()
- if got, want := ms[0].TimeSeries[0].Points[0].Value.(int64), int64(1); got != want {
- t.Errorf("value = %v, want %v", got, want)
- }
- }
-
- func ignoreTimes(_, _ time.Time) bool {
- return true
- }
-
- func canonicalize(ms []*metricdata.Metric) {
- for _, m := range ms {
- sort.Slice(m.TimeSeries, func(i, j int) bool {
- // sort time series by their label values
- iLabels := m.TimeSeries[i].LabelValues
- jLabels := m.TimeSeries[j].LabelValues
- for k := 0; k < len(iLabels); k++ {
- if !iLabels[k].Present {
- if jLabels[k].Present {
- return true
- }
- } else if !jLabels[k].Present {
- return false
- } else {
- return iLabels[k].Value < jLabels[k].Value
- }
- }
- panic("should have returned")
- })
- }
- }
-
- type queueInt64 struct {
- size int64
- }
-
- func (q *queueInt64) ToInt64() int64 {
- return q.size
- }
-
- func TestInt64DerivedGaugeEntry_Add(t *testing.T) {
- r := NewRegistry()
- q := &queueInt64{3}
- g, _ := r.AddInt64DerivedGauge("g", "", metricdata.UnitDimensionless, "k1", "k2")
- err := g.UpsertEntry(q.ToInt64, metricdata.NewLabelValue("k1v1"), metricdata.LabelValue{})
- if err != nil {
- t.Errorf("want: nil, got: %v", err)
- }
- ms := r.Read()
- if got, want := ms[0].TimeSeries[0].Points[0].Value.(int64), int64(3); got != want {
- t.Errorf("value = %v, want %v", got, want)
- }
- q.size = 5
- ms = r.Read()
- if got, want := ms[0].TimeSeries[0].Points[0].Value.(int64), int64(5); got != want {
- t.Errorf("value = %v, want %v", got, want)
- }
- }
-
- func TestInt64DerivedGaugeEntry_AddWithNilObj(t *testing.T) {
- r := NewRegistry()
- g, _ := r.AddInt64DerivedGauge("g", "", metricdata.UnitDimensionless, "k1", "k2")
- gotErr := g.UpsertEntry(nil, metricdata.NewLabelValue("k1v1"), metricdata.LabelValue{})
- if gotErr == nil {
- t.Errorf("expected error but got nil")
- }
- }
-
- func TestInt64DerivedGaugeEntry_AddWithInvalidLabels(t *testing.T) {
- r := NewRegistry()
- q := &queueInt64{3}
- g, _ := r.AddInt64DerivedGauge("g", "", metricdata.UnitDimensionless, "k1", "k2")
- gotErr := g.UpsertEntry(q.ToInt64, metricdata.NewLabelValue("k1v1"))
- if gotErr == nil {
- t.Errorf("expected error but got nil")
- }
- }
-
- func TestInt64DerivedGaugeEntry_Update(t *testing.T) {
- r := NewRegistry()
- q := &queueInt64{3}
- q2 := &queueInt64{5}
- g, _ := r.AddInt64DerivedGauge("g", "", metricdata.UnitDimensionless, "k1", "k2")
- g.UpsertEntry(q.ToInt64, metricdata.NewLabelValue("k1v1"), metricdata.LabelValue{})
- gotErr := g.UpsertEntry(q2.ToInt64, metricdata.NewLabelValue("k1v1"), metricdata.LabelValue{})
- if gotErr != nil {
- t.Errorf("got: %v, want: nil", gotErr)
- }
- ms := r.Read()
- if got, want := ms[0].TimeSeries[0].Points[0].Value.(int64), int64(5); got != want {
- t.Errorf("value = %v, want %v", got, want)
- }
- }
-
- type queueFloat64 struct {
- size float64
- }
-
- func (q *queueFloat64) ToFloat64() float64 {
- return q.size
- }
-
- func TestFloat64DerivedGaugeEntry_Add(t *testing.T) {
- r := NewRegistry()
- q := &queueFloat64{5.0}
- g, _ := r.AddFloat64DerivedGauge("g", "", metricdata.UnitDimensionless, "k1", "k2")
- err := g.UpsertEntry(q.ToFloat64, metricdata.NewLabelValue("k1v1"), metricdata.LabelValue{})
- if err != nil {
- t.Errorf("want: nil, got: %v", err)
- }
- ms := r.Read()
- if got, want := ms[0].TimeSeries[0].Points[0].Value.(float64), float64(5.0); got != want {
- t.Errorf("value = %v, want %v", got, want)
- }
- q.size = 5
- ms = r.Read()
- if got, want := ms[0].TimeSeries[0].Points[0].Value.(float64), float64(5.0); got != want {
- t.Errorf("value = %v, want %v", got, want)
- }
- }
-
- func TestFloat64DerivedGaugeEntry_AddWithNilObj(t *testing.T) {
- r := NewRegistry()
- g, _ := r.AddFloat64DerivedGauge("g", "", metricdata.UnitDimensionless, "k1", "k2")
- gotErr := g.UpsertEntry(nil, metricdata.NewLabelValue("k1v1"), metricdata.LabelValue{})
- if gotErr == nil {
- t.Errorf("expected error but got nil")
- }
- }
-
- func TestFloat64DerivedGaugeEntry_AddWithInvalidLabels(t *testing.T) {
- r := NewRegistry()
- q := &queueFloat64{3}
- g, _ := r.AddFloat64DerivedGauge("g", "", metricdata.UnitDimensionless, "k1", "k2")
- gotErr := g.UpsertEntry(q.ToFloat64, metricdata.NewLabelValue("k1v1"))
- if gotErr == nil {
- t.Errorf("expected error but got nil")
- }
- }
-
- func TestFloat64DerivedGaugeEntry_Update(t *testing.T) {
- r := NewRegistry()
- q := &queueFloat64{3.0}
- q2 := &queueFloat64{5.0}
- g, _ := r.AddFloat64DerivedGauge("g", "", metricdata.UnitDimensionless, "k1", "k2")
- g.UpsertEntry(q.ToFloat64, metricdata.NewLabelValue("k1v1"), metricdata.LabelValue{})
- gotErr := g.UpsertEntry(q2.ToFloat64, metricdata.NewLabelValue("k1v1"), metricdata.LabelValue{})
- if gotErr != nil {
- t.Errorf("got: %v, want: nil", gotErr)
- }
- ms := r.Read()
- if got, want := ms[0].TimeSeries[0].Points[0].Value.(float64), float64(5.0); got != want {
- t.Errorf("value = %v, want %v", got, want)
- }
- }
|