1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2024-12-22 20:06:07 +02:00
opentelemetry-go/bridge/opencensus/internal/ocmetric/metric_test.go
Kuisong Tong 94ae231180
Set IsMonotonic to true for opencensus sum (#3389)
* Set IsMonotonic to true for opencensus sum 

fix #3388

* Update metric_test.go

* fix test

* add changelog

* Update CHANGELOG.md

Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>

Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>
2022-10-27 14:29:01 -07:00

668 lines
19 KiB
Go

// Copyright The OpenTelemetry 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 internal // import "go.opentelemetry.io/otel/bridge/opencensus/opencensusmetric/internal"
import (
"errors"
"testing"
"time"
ocmetricdata "go.opencensus.io/metric/metricdata"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric/unit"
"go.opentelemetry.io/otel/sdk/metric/metricdata"
"go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest"
)
func TestConvertMetrics(t *testing.T) {
endTime1 := time.Now()
endTime2 := endTime1.Add(-time.Millisecond)
startTime := endTime2.Add(-time.Minute)
for _, tc := range []struct {
desc string
input []*ocmetricdata.Metric
expected []metricdata.Metrics
expectedErr error
}{
{
desc: "empty",
expected: []metricdata.Metrics{},
},
{
desc: "normal Histogram, gauges, and sums",
input: []*ocmetricdata.Metric{
{
Descriptor: ocmetricdata.Descriptor{
Name: "foo.com/histogram-a",
Description: "a testing histogram",
Unit: ocmetricdata.UnitDimensionless,
Type: ocmetricdata.TypeCumulativeDistribution,
LabelKeys: []ocmetricdata.LabelKey{
{Key: "a"},
{Key: "b"},
},
},
TimeSeries: []*ocmetricdata.TimeSeries{
{
LabelValues: []ocmetricdata.LabelValue{
{
Value: "hello",
Present: true,
}, {
Value: "world",
Present: true,
},
},
Points: []ocmetricdata.Point{
ocmetricdata.NewDistributionPoint(endTime1, &ocmetricdata.Distribution{
Count: 8,
Sum: 100.0,
BucketOptions: &ocmetricdata.BucketOptions{
Bounds: []float64{1.0, 2.0, 3.0},
},
Buckets: []ocmetricdata.Bucket{
{Count: 1},
{Count: 2},
{Count: 5},
},
}),
ocmetricdata.NewDistributionPoint(endTime2, &ocmetricdata.Distribution{
Count: 10,
Sum: 110.0,
BucketOptions: &ocmetricdata.BucketOptions{
Bounds: []float64{1.0, 2.0, 3.0},
},
Buckets: []ocmetricdata.Bucket{
{Count: 1},
{Count: 4},
{Count: 5},
},
}),
},
StartTime: startTime,
},
},
}, {
Descriptor: ocmetricdata.Descriptor{
Name: "foo.com/gauge-a",
Description: "an int testing gauge",
Unit: ocmetricdata.UnitBytes,
Type: ocmetricdata.TypeGaugeInt64,
LabelKeys: []ocmetricdata.LabelKey{
{Key: "c"},
{Key: "d"},
},
},
TimeSeries: []*ocmetricdata.TimeSeries{
{
LabelValues: []ocmetricdata.LabelValue{
{
Value: "foo",
Present: true,
}, {
Value: "bar",
Present: true,
},
},
Points: []ocmetricdata.Point{
ocmetricdata.NewInt64Point(endTime1, 123),
ocmetricdata.NewInt64Point(endTime2, 1236),
},
},
},
}, {
Descriptor: ocmetricdata.Descriptor{
Name: "foo.com/gauge-b",
Description: "a float testing gauge",
Unit: ocmetricdata.UnitBytes,
Type: ocmetricdata.TypeGaugeFloat64,
LabelKeys: []ocmetricdata.LabelKey{
{Key: "cf"},
{Key: "df"},
},
},
TimeSeries: []*ocmetricdata.TimeSeries{
{
LabelValues: []ocmetricdata.LabelValue{
{
Value: "foof",
Present: true,
}, {
Value: "barf",
Present: true,
},
},
Points: []ocmetricdata.Point{
ocmetricdata.NewFloat64Point(endTime1, 123.4),
ocmetricdata.NewFloat64Point(endTime2, 1236.7),
},
},
},
}, {
Descriptor: ocmetricdata.Descriptor{
Name: "foo.com/sum-a",
Description: "an int testing sum",
Unit: ocmetricdata.UnitMilliseconds,
Type: ocmetricdata.TypeCumulativeInt64,
LabelKeys: []ocmetricdata.LabelKey{
{Key: "e"},
{Key: "f"},
},
},
TimeSeries: []*ocmetricdata.TimeSeries{
{
LabelValues: []ocmetricdata.LabelValue{
{
Value: "zig",
Present: true,
}, {
Value: "zag",
Present: true,
},
},
Points: []ocmetricdata.Point{
ocmetricdata.NewInt64Point(endTime1, 13),
ocmetricdata.NewInt64Point(endTime2, 14),
},
},
},
}, {
Descriptor: ocmetricdata.Descriptor{
Name: "foo.com/sum-b",
Description: "a float testing sum",
Unit: ocmetricdata.UnitMilliseconds,
Type: ocmetricdata.TypeCumulativeFloat64,
LabelKeys: []ocmetricdata.LabelKey{
{Key: "e"},
{Key: "f"},
},
},
TimeSeries: []*ocmetricdata.TimeSeries{
{
LabelValues: []ocmetricdata.LabelValue{
{
Value: "zig",
Present: true,
}, {
Value: "zag",
Present: true,
},
},
Points: []ocmetricdata.Point{
ocmetricdata.NewFloat64Point(endTime1, 12.3),
ocmetricdata.NewFloat64Point(endTime2, 123.4),
},
},
},
},
},
expected: []metricdata.Metrics{
{
Name: "foo.com/histogram-a",
Description: "a testing histogram",
Unit: unit.Dimensionless,
Data: metricdata.Histogram{
DataPoints: []metricdata.HistogramDataPoint{
{
Attributes: attribute.NewSet(attribute.KeyValue{
Key: attribute.Key("a"),
Value: attribute.StringValue("hello"),
}, attribute.KeyValue{
Key: attribute.Key("b"),
Value: attribute.StringValue("world"),
}),
StartTime: startTime,
Time: endTime1,
Count: 8,
Sum: 100.0,
Bounds: []float64{1.0, 2.0, 3.0},
BucketCounts: []uint64{1, 2, 5},
}, {
Attributes: attribute.NewSet(attribute.KeyValue{
Key: attribute.Key("a"),
Value: attribute.StringValue("hello"),
}, attribute.KeyValue{
Key: attribute.Key("b"),
Value: attribute.StringValue("world"),
}),
StartTime: startTime,
Time: endTime2,
Count: 10,
Sum: 110.0,
Bounds: []float64{1.0, 2.0, 3.0},
BucketCounts: []uint64{1, 4, 5},
},
},
Temporality: metricdata.CumulativeTemporality,
},
}, {
Name: "foo.com/gauge-a",
Description: "an int testing gauge",
Unit: unit.Bytes,
Data: metricdata.Gauge[int64]{
DataPoints: []metricdata.DataPoint[int64]{
{
Attributes: attribute.NewSet(attribute.KeyValue{
Key: attribute.Key("c"),
Value: attribute.StringValue("foo"),
}, attribute.KeyValue{
Key: attribute.Key("d"),
Value: attribute.StringValue("bar"),
}),
Time: endTime1,
Value: 123,
}, {
Attributes: attribute.NewSet(attribute.KeyValue{
Key: attribute.Key("c"),
Value: attribute.StringValue("foo"),
}, attribute.KeyValue{
Key: attribute.Key("d"),
Value: attribute.StringValue("bar"),
}),
Time: endTime2,
Value: 1236,
},
},
},
}, {
Name: "foo.com/gauge-b",
Description: "a float testing gauge",
Unit: unit.Bytes,
Data: metricdata.Gauge[float64]{
DataPoints: []metricdata.DataPoint[float64]{
{
Attributes: attribute.NewSet(attribute.KeyValue{
Key: attribute.Key("cf"),
Value: attribute.StringValue("foof"),
}, attribute.KeyValue{
Key: attribute.Key("df"),
Value: attribute.StringValue("barf"),
}),
Time: endTime1,
Value: 123.4,
}, {
Attributes: attribute.NewSet(attribute.KeyValue{
Key: attribute.Key("cf"),
Value: attribute.StringValue("foof"),
}, attribute.KeyValue{
Key: attribute.Key("df"),
Value: attribute.StringValue("barf"),
}),
Time: endTime2,
Value: 1236.7,
},
},
},
}, {
Name: "foo.com/sum-a",
Description: "an int testing sum",
Unit: unit.Milliseconds,
Data: metricdata.Sum[int64]{
IsMonotonic: true,
Temporality: metricdata.CumulativeTemporality,
DataPoints: []metricdata.DataPoint[int64]{
{
Attributes: attribute.NewSet(attribute.KeyValue{
Key: attribute.Key("e"),
Value: attribute.StringValue("zig"),
}, attribute.KeyValue{
Key: attribute.Key("f"),
Value: attribute.StringValue("zag"),
}),
Time: endTime1,
Value: 13,
}, {
Attributes: attribute.NewSet(attribute.KeyValue{
Key: attribute.Key("e"),
Value: attribute.StringValue("zig"),
}, attribute.KeyValue{
Key: attribute.Key("f"),
Value: attribute.StringValue("zag"),
}),
Time: endTime2,
Value: 14,
},
},
},
}, {
Name: "foo.com/sum-b",
Description: "a float testing sum",
Unit: unit.Milliseconds,
Data: metricdata.Sum[float64]{
IsMonotonic: true,
Temporality: metricdata.CumulativeTemporality,
DataPoints: []metricdata.DataPoint[float64]{
{
Attributes: attribute.NewSet(attribute.KeyValue{
Key: attribute.Key("e"),
Value: attribute.StringValue("zig"),
}, attribute.KeyValue{
Key: attribute.Key("f"),
Value: attribute.StringValue("zag"),
}),
Time: endTime1,
Value: 12.3,
}, {
Attributes: attribute.NewSet(attribute.KeyValue{
Key: attribute.Key("e"),
Value: attribute.StringValue("zig"),
}, attribute.KeyValue{
Key: attribute.Key("f"),
Value: attribute.StringValue("zag"),
}),
Time: endTime2,
Value: 123.4,
},
},
},
},
},
}, {
desc: "histogram without data points",
input: []*ocmetricdata.Metric{
{
Descriptor: ocmetricdata.Descriptor{
Name: "foo.com/histogram-a",
Description: "a testing histogram",
Unit: ocmetricdata.UnitDimensionless,
Type: ocmetricdata.TypeCumulativeDistribution,
},
},
},
expected: []metricdata.Metrics{
{
Name: "foo.com/histogram-a",
Description: "a testing histogram",
Unit: unit.Dimensionless,
Data: metricdata.Histogram{
Temporality: metricdata.CumulativeTemporality,
DataPoints: []metricdata.HistogramDataPoint{},
},
},
},
}, {
desc: "sum without data points",
input: []*ocmetricdata.Metric{
{
Descriptor: ocmetricdata.Descriptor{
Name: "foo.com/sum-a",
Description: "a testing sum",
Unit: ocmetricdata.UnitDimensionless,
Type: ocmetricdata.TypeCumulativeFloat64,
},
},
},
expected: []metricdata.Metrics{
{
Name: "foo.com/sum-a",
Description: "a testing sum",
Unit: unit.Dimensionless,
Data: metricdata.Sum[float64]{
IsMonotonic: true,
Temporality: metricdata.CumulativeTemporality,
DataPoints: []metricdata.DataPoint[float64]{},
},
},
},
}, {
desc: "gauge without data points",
input: []*ocmetricdata.Metric{
{
Descriptor: ocmetricdata.Descriptor{
Name: "foo.com/gauge-a",
Description: "a testing gauge",
Unit: ocmetricdata.UnitDimensionless,
Type: ocmetricdata.TypeGaugeInt64,
},
},
},
expected: []metricdata.Metrics{
{
Name: "foo.com/gauge-a",
Description: "a testing gauge",
Unit: unit.Dimensionless,
Data: metricdata.Gauge[int64]{
DataPoints: []metricdata.DataPoint[int64]{},
},
},
},
}, {
desc: "histogram with negative count",
input: []*ocmetricdata.Metric{
{
Descriptor: ocmetricdata.Descriptor{
Name: "foo.com/histogram-a",
Description: "a testing histogram",
Unit: ocmetricdata.UnitDimensionless,
Type: ocmetricdata.TypeCumulativeDistribution,
},
TimeSeries: []*ocmetricdata.TimeSeries{
{
Points: []ocmetricdata.Point{
ocmetricdata.NewDistributionPoint(endTime1, &ocmetricdata.Distribution{
Count: -8,
}),
},
StartTime: startTime,
},
},
},
},
expectedErr: errConversion,
}, {
desc: "histogram with negative bucket count",
input: []*ocmetricdata.Metric{
{
Descriptor: ocmetricdata.Descriptor{
Name: "foo.com/histogram-a",
Description: "a testing histogram",
Unit: ocmetricdata.UnitDimensionless,
Type: ocmetricdata.TypeCumulativeDistribution,
},
TimeSeries: []*ocmetricdata.TimeSeries{
{
Points: []ocmetricdata.Point{
ocmetricdata.NewDistributionPoint(endTime1, &ocmetricdata.Distribution{
Buckets: []ocmetricdata.Bucket{
{Count: -1},
{Count: 2},
{Count: 5},
},
}),
},
StartTime: startTime,
},
},
},
},
expectedErr: errConversion,
}, {
desc: "histogram with non-histogram datapoint type",
input: []*ocmetricdata.Metric{
{
Descriptor: ocmetricdata.Descriptor{
Name: "foo.com/bad-point",
Description: "a bad type",
Unit: ocmetricdata.UnitDimensionless,
Type: ocmetricdata.TypeCumulativeDistribution,
},
TimeSeries: []*ocmetricdata.TimeSeries{
{
Points: []ocmetricdata.Point{
ocmetricdata.NewFloat64Point(endTime1, 1.0),
},
StartTime: startTime,
},
},
},
},
expectedErr: errConversion,
}, {
desc: "sum with non-sum datapoint type",
input: []*ocmetricdata.Metric{
{
Descriptor: ocmetricdata.Descriptor{
Name: "foo.com/bad-point",
Description: "a bad type",
Unit: ocmetricdata.UnitDimensionless,
Type: ocmetricdata.TypeCumulativeFloat64,
},
TimeSeries: []*ocmetricdata.TimeSeries{
{
Points: []ocmetricdata.Point{
ocmetricdata.NewDistributionPoint(endTime1, &ocmetricdata.Distribution{}),
},
StartTime: startTime,
},
},
},
},
expectedErr: errConversion,
}, {
desc: "gauge with non-gauge datapoint type",
input: []*ocmetricdata.Metric{
{
Descriptor: ocmetricdata.Descriptor{
Name: "foo.com/bad-point",
Description: "a bad type",
Unit: ocmetricdata.UnitDimensionless,
Type: ocmetricdata.TypeGaugeFloat64,
},
TimeSeries: []*ocmetricdata.TimeSeries{
{
Points: []ocmetricdata.Point{
ocmetricdata.NewDistributionPoint(endTime1, &ocmetricdata.Distribution{}),
},
StartTime: startTime,
},
},
},
},
expectedErr: errConversion,
}, {
desc: "unsupported Gauge Distribution type",
input: []*ocmetricdata.Metric{
{
Descriptor: ocmetricdata.Descriptor{
Name: "foo.com/bad-point",
Description: "a bad type",
Unit: ocmetricdata.UnitDimensionless,
Type: ocmetricdata.TypeGaugeDistribution,
},
},
},
expectedErr: errConversion,
},
} {
t.Run(tc.desc, func(t *testing.T) {
output, err := ConvertMetrics(tc.input)
if !errors.Is(err, tc.expectedErr) {
t.Errorf("convertAggregation(%+v) = err(%v), want err(%v)", tc.input, err, tc.expectedErr)
}
metricdatatest.AssertEqual[metricdata.ScopeMetrics](t,
metricdata.ScopeMetrics{Metrics: tc.expected},
metricdata.ScopeMetrics{Metrics: output})
})
}
}
func TestConvertUnits(t *testing.T) {
var noUnit unit.Unit
for _, tc := range []struct {
desc string
input ocmetricdata.Unit
expected unit.Unit
}{{
desc: "unspecified unit",
expected: noUnit,
}, {
desc: "dimensionless",
input: ocmetricdata.UnitDimensionless,
expected: unit.Dimensionless,
}, {
desc: "milliseconds",
input: ocmetricdata.UnitMilliseconds,
expected: unit.Milliseconds,
}, {
desc: "bytes",
input: ocmetricdata.UnitBytes,
expected: unit.Bytes,
},
} {
t.Run(tc.desc, func(t *testing.T) {
output := convertUnit(tc.input)
if output != tc.expected {
t.Errorf("convertUnit(%v) = %q, want %q", tc.input, output, tc.expected)
}
})
}
}
func TestConvertAttributes(t *testing.T) {
setWithMultipleKeys := attribute.NewSet(
attribute.KeyValue{Key: attribute.Key("first"), Value: attribute.StringValue("1")},
attribute.KeyValue{Key: attribute.Key("second"), Value: attribute.StringValue("2")},
)
for _, tc := range []struct {
desc string
inputKeys []ocmetricdata.LabelKey
inputValues []ocmetricdata.LabelValue
expected *attribute.Set
expectedErr error
}{
{
desc: "no attributes",
expected: attribute.EmptySet(),
},
{
desc: "different numbers of keys and values",
inputKeys: []ocmetricdata.LabelKey{{Key: "foo"}},
expected: attribute.EmptySet(),
expectedErr: errMismatchedAttributeKeyValues,
},
{
desc: "multiple keys and values",
inputKeys: []ocmetricdata.LabelKey{{Key: "first"}, {Key: "second"}},
inputValues: []ocmetricdata.LabelValue{
{Value: "1", Present: true},
{Value: "2", Present: true},
},
expected: &setWithMultipleKeys,
},
{
desc: "multiple keys and values with some not present",
inputKeys: []ocmetricdata.LabelKey{{Key: "first"}, {Key: "second"}, {Key: "third"}},
inputValues: []ocmetricdata.LabelValue{
{Value: "1", Present: true},
{Value: "2", Present: true},
{Present: false},
},
expected: &setWithMultipleKeys,
},
} {
t.Run(tc.desc, func(t *testing.T) {
output, err := convertAttrs(tc.inputKeys, tc.inputValues)
if !errors.Is(err, tc.expectedErr) {
t.Errorf("convertAttrs(keys: %v, values: %v) = err(%v), want err(%v)", tc.inputKeys, tc.inputValues, err, tc.expectedErr)
}
if !output.Equals(tc.expected) {
t.Errorf("convertAttrs(keys: %v, values: %v) = %+v, want %+v", tc.inputKeys, tc.inputValues, output.ToSlice(), tc.expected.ToSlice())
}
})
}
}