1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-10-08 23:21:56 +02:00
Files
opentelemetry-go/bridge/opencensus/internal/ocmetric/metric_test.go
2024-02-29 07:05:28 +01:00

1171 lines
32 KiB
Go

// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal // import "go.opentelemetry.io/otel/bridge/opencensus/opencensusmetric/internal"
import (
"errors"
"fmt"
"math"
"reflect"
"testing"
"time"
"github.com/stretchr/testify/assert"
ocmetricdata "go.opencensus.io/metric/metricdata"
octrace "go.opencensus.io/trace"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/sdk/metric/metricdata"
"go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest"
)
func TestConvertMetrics(t *testing.T) {
endTime1 := time.Now()
exemplarTime := endTime1.Add(-10 * time.Second)
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, summary, 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,
Exemplar: &ocmetricdata.Exemplar{
Value: 0.8,
Timestamp: exemplarTime,
Attachments: map[string]interface{}{
ocmetricdata.AttachmentKeySpanContext: octrace.SpanContext{
TraceID: octrace.TraceID([16]byte{1}),
SpanID: octrace.SpanID([8]byte{2}),
},
"bool": true,
},
},
},
{
Count: 2,
Exemplar: &ocmetricdata.Exemplar{
Value: 1.5,
Timestamp: exemplarTime,
Attachments: map[string]interface{}{
ocmetricdata.AttachmentKeySpanContext: octrace.SpanContext{
TraceID: octrace.TraceID([16]byte{3}),
SpanID: octrace.SpanID([8]byte{4}),
},
},
},
},
{
Count: 5,
Exemplar: &ocmetricdata.Exemplar{
Value: 2.6,
Timestamp: exemplarTime,
Attachments: map[string]interface{}{
ocmetricdata.AttachmentKeySpanContext: octrace.SpanContext{
TraceID: octrace.TraceID([16]byte{5}),
SpanID: octrace.SpanID([8]byte{6}),
},
},
},
},
},
}),
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,
Exemplar: &ocmetricdata.Exemplar{
Value: 0.9,
Timestamp: exemplarTime,
Attachments: map[string]interface{}{
ocmetricdata.AttachmentKeySpanContext: octrace.SpanContext{
TraceID: octrace.TraceID([16]byte{7}),
SpanID: octrace.SpanID([8]byte{8}),
},
},
},
},
{
Count: 4,
Exemplar: &ocmetricdata.Exemplar{
Value: 1.1,
Timestamp: exemplarTime,
Attachments: map[string]interface{}{
ocmetricdata.AttachmentKeySpanContext: octrace.SpanContext{
TraceID: octrace.TraceID([16]byte{9}),
SpanID: octrace.SpanID([8]byte{10}),
},
},
},
},
{
Count: 5,
Exemplar: &ocmetricdata.Exemplar{
Value: 2.7,
Timestamp: exemplarTime,
Attachments: map[string]interface{}{
ocmetricdata.AttachmentKeySpanContext: octrace.SpanContext{
TraceID: octrace.TraceID([16]byte{11}),
SpanID: octrace.SpanID([8]byte{12}),
},
},
},
},
},
}),
},
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),
},
},
},
}, {
Descriptor: ocmetricdata.Descriptor{
Name: "foo.com/summary-a",
Description: "a testing summary",
Unit: ocmetricdata.UnitMilliseconds,
Type: ocmetricdata.TypeSummary,
LabelKeys: []ocmetricdata.LabelKey{
{Key: "g"},
{Key: "h"},
},
},
TimeSeries: []*ocmetricdata.TimeSeries{
{
LabelValues: []ocmetricdata.LabelValue{
{
Value: "ding",
Present: true,
}, {
Value: "dong",
Present: true,
},
},
Points: []ocmetricdata.Point{
ocmetricdata.NewSummaryPoint(endTime1, &ocmetricdata.Summary{
Count: 10,
Sum: 13.2,
HasCountAndSum: true,
Snapshot: ocmetricdata.Snapshot{
Percentiles: map[float64]float64{
50.0: 1.0,
0.0: 0.1,
100.0: 10.4,
},
},
}),
ocmetricdata.NewSummaryPoint(endTime2, &ocmetricdata.Summary{
Count: 12,
Snapshot: ocmetricdata.Snapshot{
Percentiles: map[float64]float64{
0.0: 0.2,
50.0: 1.1,
100.0: 10.5,
},
},
}),
},
},
},
},
},
expected: []metricdata.Metrics{
{
Name: "foo.com/histogram-a",
Description: "a testing histogram",
Unit: "1",
Data: metricdata.Histogram[float64]{
DataPoints: []metricdata.HistogramDataPoint[float64]{
{
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},
Exemplars: []metricdata.Exemplar[float64]{
{
Time: exemplarTime,
Value: 0.8,
TraceID: []byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
SpanID: []byte{2, 0, 0, 0, 0, 0, 0, 0},
FilteredAttributes: []attribute.KeyValue{
attribute.Bool("bool", true),
},
},
{
Time: exemplarTime,
Value: 1.5,
TraceID: []byte{3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
SpanID: []byte{4, 0, 0, 0, 0, 0, 0, 0},
},
{
Time: exemplarTime,
Value: 2.6,
TraceID: []byte{5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
SpanID: []byte{6, 0, 0, 0, 0, 0, 0, 0},
},
},
}, {
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},
Exemplars: []metricdata.Exemplar[float64]{
{
Time: exemplarTime,
Value: 0.9,
TraceID: []byte{7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
SpanID: []byte{8, 0, 0, 0, 0, 0, 0, 0},
},
{
Time: exemplarTime,
Value: 1.1,
TraceID: []byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
SpanID: []byte{10, 0, 0, 0, 0, 0, 0, 0},
},
{
Time: exemplarTime,
Value: 2.7,
TraceID: []byte{11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
SpanID: []byte{12, 0, 0, 0, 0, 0, 0, 0},
},
},
},
},
Temporality: metricdata.CumulativeTemporality,
},
}, {
Name: "foo.com/gauge-a",
Description: "an int testing gauge",
Unit: "By",
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: "By",
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: "ms",
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: "ms",
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,
},
},
},
}, {
Name: "foo.com/summary-a",
Description: "a testing summary",
Unit: "ms",
Data: metricdata.Summary{
DataPoints: []metricdata.SummaryDataPoint{
{
Attributes: attribute.NewSet(attribute.KeyValue{
Key: attribute.Key("g"),
Value: attribute.StringValue("ding"),
}, attribute.KeyValue{
Key: attribute.Key("h"),
Value: attribute.StringValue("dong"),
}),
Time: endTime1,
Count: 10,
Sum: 13.2,
QuantileValues: []metricdata.QuantileValue{
{
Quantile: 0.0,
Value: 0.1,
},
{
Quantile: 0.5,
Value: 1.0,
},
{
Quantile: 1.0,
Value: 10.4,
},
},
}, {
Attributes: attribute.NewSet(attribute.KeyValue{
Key: attribute.Key("g"),
Value: attribute.StringValue("ding"),
}, attribute.KeyValue{
Key: attribute.Key("h"),
Value: attribute.StringValue("dong"),
}),
Time: endTime2,
Count: 12,
QuantileValues: []metricdata.QuantileValue{
{
Quantile: 0.0,
Value: 0.2,
},
{
Quantile: 0.5,
Value: 1.1,
},
{
Quantile: 1.0,
Value: 10.5,
},
},
},
},
},
},
},
},
{
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: "1",
Data: metricdata.Histogram[float64]{
Temporality: metricdata.CumulativeTemporality,
DataPoints: []metricdata.HistogramDataPoint[float64]{},
},
},
},
},
{
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: "1",
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: "1",
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: errNegativeCount,
},
{
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: errNegativeBucketCount,
},
{
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: errMismatchedValueTypes,
},
{
desc: "summary with mismatched attributes",
input: []*ocmetricdata.Metric{
{
Descriptor: ocmetricdata.Descriptor{
Name: "foo.com/summary-mismatched",
Description: "a mismatched summary",
Unit: ocmetricdata.UnitMilliseconds,
Type: ocmetricdata.TypeSummary,
LabelKeys: []ocmetricdata.LabelKey{
{Key: "g"},
},
},
TimeSeries: []*ocmetricdata.TimeSeries{
{
LabelValues: []ocmetricdata.LabelValue{
{
Value: "ding",
Present: true,
}, {
Value: "dong",
Present: true,
},
},
Points: []ocmetricdata.Point{
ocmetricdata.NewSummaryPoint(endTime1, &ocmetricdata.Summary{
Count: 10,
Sum: 13.2,
HasCountAndSum: true,
Snapshot: ocmetricdata.Snapshot{
Percentiles: map[float64]float64{
0.0: 0.1,
0.5: 1.0,
1.0: 10.4,
},
},
}),
},
},
},
},
},
expectedErr: errMismatchedAttributeKeyValues,
},
{
desc: "summary with negative count",
input: []*ocmetricdata.Metric{
{
Descriptor: ocmetricdata.Descriptor{
Name: "foo.com/summary-negative",
Description: "a negative count summary",
Unit: ocmetricdata.UnitMilliseconds,
Type: ocmetricdata.TypeSummary,
},
TimeSeries: []*ocmetricdata.TimeSeries{
{
Points: []ocmetricdata.Point{
ocmetricdata.NewSummaryPoint(endTime1, &ocmetricdata.Summary{
Count: -10,
Sum: 13.2,
HasCountAndSum: true,
Snapshot: ocmetricdata.Snapshot{
Percentiles: map[float64]float64{
0.0: 0.1,
0.5: 1.0,
1.0: 10.4,
},
},
}),
},
},
},
},
},
expectedErr: errNegativeCount,
},
{
desc: "histogram with invalid span context exemplar",
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,
Sum: 100.0,
BucketOptions: &ocmetricdata.BucketOptions{
Bounds: []float64{1.0, 2.0, 3.0},
},
Buckets: []ocmetricdata.Bucket{
{
Count: 1,
Exemplar: &ocmetricdata.Exemplar{
Value: 0.8,
Timestamp: exemplarTime,
Attachments: map[string]interface{}{
ocmetricdata.AttachmentKeySpanContext: "notaspancontext",
},
},
},
},
}),
},
StartTime: startTime,
},
},
},
},
expectedErr: errInvalidExemplarSpanContext,
},
{
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: errMismatchedValueTypes,
},
{
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: errMismatchedValueTypes,
},
{
desc: "summary with non-summary datapoint type",
input: []*ocmetricdata.Metric{
{
Descriptor: ocmetricdata.Descriptor{
Name: "foo.com/bad-point",
Description: "a bad type",
Unit: ocmetricdata.UnitDimensionless,
Type: ocmetricdata.TypeSummary,
},
TimeSeries: []*ocmetricdata.TimeSeries{
{
Points: []ocmetricdata.Point{
ocmetricdata.NewDistributionPoint(endTime1, &ocmetricdata.Distribution{}),
},
StartTime: startTime,
},
},
},
},
expectedErr: errMismatchedValueTypes,
},
{
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: errAggregationType,
},
} {
t.Run(tc.desc, func(t *testing.T) {
output, err := ConvertMetrics(tc.input)
if !errors.Is(err, tc.expectedErr) {
t.Errorf("ConvertMetrics(%+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 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())
}
})
}
}
type fakeStringer string
func (f fakeStringer) String() string {
return string(f)
}
func TestConvertKV(t *testing.T) {
key := "foo"
for _, tt := range []struct {
value any
expected attribute.Value
}{
{
value: bool(true),
expected: attribute.BoolValue(true),
},
{
value: []bool{true, false},
expected: attribute.BoolSliceValue([]bool{true, false}),
},
{
value: int(10),
expected: attribute.IntValue(10),
},
{
value: []int{10, 20},
expected: attribute.IntSliceValue([]int{10, 20}),
},
{
value: int8(10),
expected: attribute.IntValue(10),
},
{
value: []int8{10, 20},
expected: attribute.IntSliceValue([]int{10, 20}),
},
{
value: int16(10),
expected: attribute.IntValue(10),
},
{
value: []int16{10, 20},
expected: attribute.IntSliceValue([]int{10, 20}),
},
{
value: int32(10),
expected: attribute.IntValue(10),
},
{
value: []int32{10, 20},
expected: attribute.IntSliceValue([]int{10, 20}),
},
{
value: int64(10),
expected: attribute.Int64Value(10),
},
{
value: []int64{10, 20},
expected: attribute.Int64SliceValue([]int64{10, 20}),
},
{
value: uint(10),
expected: attribute.IntValue(10),
},
{
value: uint(math.MaxUint),
expected: attribute.StringValue(fmt.Sprintf("%v", uint(math.MaxUint))),
},
{
value: []uint{10, 20},
expected: attribute.StringSliceValue([]string{"10", "20"}),
},
{
value: uint8(10),
expected: attribute.IntValue(10),
},
{
value: []uint8{10, 20},
expected: attribute.StringSliceValue([]string{"10", "20"}),
},
{
value: uint16(10),
expected: attribute.IntValue(10),
},
{
value: []uint16{10, 20},
expected: attribute.StringSliceValue([]string{"10", "20"}),
},
{
value: uint32(10),
expected: attribute.IntValue(10),
},
{
value: []uint32{10, 20},
expected: attribute.StringSliceValue([]string{"10", "20"}),
},
{
value: uint64(10),
expected: attribute.Int64Value(10),
},
{
value: uint64(math.MaxUint64),
expected: attribute.StringValue("18446744073709551615"),
},
{
value: []uint64{10, 20},
expected: attribute.StringSliceValue([]string{"10", "20"}),
},
{
value: uintptr(10),
expected: attribute.Int64Value(10),
},
{
value: []uintptr{10, 20},
expected: attribute.StringSliceValue([]string{"10", "20"}),
},
{
value: float32(10),
expected: attribute.Float64Value(10),
},
{
value: []float32{10, 20},
expected: attribute.Float64SliceValue([]float64{10, 20}),
},
{
value: float64(10),
expected: attribute.Float64Value(10),
},
{
value: []float64{10, 20},
expected: attribute.Float64SliceValue([]float64{10, 20}),
},
{
value: complex64(10),
expected: attribute.StringValue("(10+0i)"),
},
{
value: []complex64{10, 20},
expected: attribute.StringSliceValue([]string{"(10+0i)", "(20+0i)"}),
},
{
value: complex128(10),
expected: attribute.StringValue("(10+0i)"),
},
{
value: []complex128{10, 20},
expected: attribute.StringSliceValue([]string{"(10+0i)", "(20+0i)"}),
},
{
value: "string",
expected: attribute.StringValue("string"),
},
{
value: []string{"string", "slice"},
expected: attribute.StringSliceValue([]string{"string", "slice"}),
},
{
value: fakeStringer("stringer"),
expected: attribute.StringValue("stringer"),
},
{
value: metricdata.Histogram[float64]{},
expected: attribute.StringValue("unhandled attribute value: {DataPoints:[] Temporality:undefinedTemporality}"),
},
} {
t.Run(fmt.Sprintf("%v(%+v)", reflect.TypeOf(tt.value), tt.value), func(t *testing.T) {
got := convertKV(key, tt.value)
assert.Equal(t, key, string(got.Key))
assert.Equal(t, tt.expected, got.Value)
})
}
}