1
0
mirror of https://github.com/golang/go synced 2024-11-19 09:54:49 -07:00
go/internal/telemetry/export/ocagent/metrics_test.go
Nathan Dias be03d4f470 internal/telemetry/export/ocagent: attach timestamps to metrics
This change attaches start timestamps to timeseries and end
timestamps to the points in each timeseries. Int64Data,
Float64Data, HistogramInt64Data, and HistogramFloat64Data
have also had an EndTime field added to keep track of the last
time the metric was updated.

What works:
* Start and end timestamps will now be attached to timeseries.

What does not work yet:
* MetricDescriptors will not have a unit attached.
* No labels will be attached to timeseries.
* Distributions will not have SumOfSquaredDeviation attached.

Updates golang/go#33819

Change-Id: I692e1676bb1e31de26c1f799b96428fc9a55d6c7
Reviewed-on: https://go-review.googlesource.com/c/tools/+/203060
Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
2019-10-24 07:31:07 +00:00

994 lines
17 KiB
Go

package ocagent
import (
"reflect"
"testing"
"time"
"golang.org/x/tools/internal/telemetry"
"golang.org/x/tools/internal/telemetry/export/ocagent/wire"
"golang.org/x/tools/internal/telemetry/metric"
)
func TestDataToMetricDescriptor(t *testing.T) {
tests := []struct {
name string
data telemetry.MetricData
want *wire.MetricDescriptor
}{
{
"nil data",
nil,
nil,
},
{
"Int64Data gauge",
&metric.Int64Data{
Info: &metric.Scalar{
Name: "int",
Description: "int metric",
Keys: []interface{}{"hello"},
},
IsGauge: true,
},
&wire.MetricDescriptor{
Name: "int",
Description: "int metric",
Type: wire.MetricDescriptor_GAUGE_INT64,
LabelKeys: []*wire.LabelKey{
&wire.LabelKey{
Key: "hello",
},
},
},
},
{
"Float64Data cumulative",
&metric.Float64Data{
Info: &metric.Scalar{
Name: "float",
Description: "float metric",
Keys: []interface{}{"world"},
},
IsGauge: false,
},
&wire.MetricDescriptor{
Name: "float",
Description: "float metric",
Type: wire.MetricDescriptor_CUMULATIVE_DOUBLE,
LabelKeys: []*wire.LabelKey{
&wire.LabelKey{
Key: "world",
},
},
},
},
{
"HistogramInt64",
&metric.HistogramInt64Data{
Info: &metric.HistogramInt64{
Name: "histogram int",
Description: "histogram int metric",
Keys: []interface{}{"hello"},
},
},
&wire.MetricDescriptor{
Name: "histogram int",
Description: "histogram int metric",
Type: wire.MetricDescriptor_CUMULATIVE_DISTRIBUTION,
LabelKeys: []*wire.LabelKey{
&wire.LabelKey{
Key: "hello",
},
},
},
},
{
"HistogramFloat64",
&metric.HistogramFloat64Data{
Info: &metric.HistogramFloat64{
Name: "histogram float",
Description: "histogram float metric",
Keys: []interface{}{"hello"},
},
},
&wire.MetricDescriptor{
Name: "histogram float",
Description: "histogram float metric",
Type: wire.MetricDescriptor_CUMULATIVE_DISTRIBUTION,
LabelKeys: []*wire.LabelKey{
&wire.LabelKey{
Key: "hello",
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := dataToMetricDescriptor(tt.data)
if !reflect.DeepEqual(got, tt.want) {
t.Fatalf("Got:\n%s\nWant:\n%s", marshaled(got), marshaled(tt.want))
}
})
}
}
func TestGetDescription(t *testing.T) {
tests := []struct {
name string
data telemetry.MetricData
want string
}{
{
"nil data",
nil,
"",
},
{
"Int64Data description",
&metric.Int64Data{
Info: &metric.Scalar{
Description: "int metric",
},
},
"int metric",
},
{
"Float64Data description",
&metric.Float64Data{
Info: &metric.Scalar{
Description: "float metric",
},
},
"float metric",
},
{
"HistogramInt64Data description",
&metric.HistogramInt64Data{
Info: &metric.HistogramInt64{
Description: "histogram int metric",
},
},
"histogram int metric",
},
{
"HistogramFloat64Data description",
&metric.HistogramFloat64Data{
Info: &metric.HistogramFloat64{
Description: "histogram float metric",
},
},
"histogram float metric",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := getDescription(tt.data)
if !reflect.DeepEqual(got, tt.want) {
t.Fatalf("Got:\n%s\nWant:\n%s", marshaled(got), marshaled(tt.want))
}
})
}
}
func TestGetLabelKeys(t *testing.T) {
tests := []struct {
name string
data telemetry.MetricData
want []*wire.LabelKey
}{
{
"nil label keys",
nil,
nil,
},
{
"Int64Data label keys",
&metric.Int64Data{
Info: &metric.Scalar{
Keys: []interface{}{
"hello",
},
},
},
[]*wire.LabelKey{
&wire.LabelKey{
Key: "hello",
},
},
},
{
"Float64Data label keys",
&metric.Float64Data{
Info: &metric.Scalar{
Keys: []interface{}{
"world",
},
},
},
[]*wire.LabelKey{
&wire.LabelKey{
Key: "world",
},
},
},
{
"HistogramInt64Data label keys",
&metric.HistogramInt64Data{
Info: &metric.HistogramInt64{
Keys: []interface{}{
"hello",
},
},
},
[]*wire.LabelKey{
&wire.LabelKey{
Key: "hello",
},
},
},
{
"HistogramFloat64Data label keys",
&metric.HistogramFloat64Data{
Info: &metric.HistogramFloat64{
Keys: []interface{}{
"hello",
},
},
},
[]*wire.LabelKey{
&wire.LabelKey{
Key: "hello",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := getLabelKeys(tt.data)
if !reflect.DeepEqual(got, tt.want) {
t.Fatalf("Got:\n%s\nWant:\n%s", marshaled(got), marshaled(tt.want))
}
})
}
}
func TestDataToMetricDescriptorType(t *testing.T) {
tests := []struct {
name string
data telemetry.MetricData
want wire.MetricDescriptor_Type
}{
{
"Nil data",
nil,
wire.MetricDescriptor_UNSPECIFIED,
},
{
"Gauge Int64",
&metric.Int64Data{
IsGauge: true,
},
wire.MetricDescriptor_GAUGE_INT64,
},
{
"Cumulative Int64",
&metric.Int64Data{
IsGauge: false,
},
wire.MetricDescriptor_CUMULATIVE_INT64,
},
{
"Gauge Float64",
&metric.Float64Data{
IsGauge: true,
},
wire.MetricDescriptor_GAUGE_DOUBLE,
},
{
"Cumulative Float64",
&metric.Float64Data{
IsGauge: false,
},
wire.MetricDescriptor_CUMULATIVE_DOUBLE,
},
{
"HistogramInt64",
&metric.HistogramInt64Data{},
wire.MetricDescriptor_CUMULATIVE_DISTRIBUTION,
},
{
"HistogramFloat64",
&metric.HistogramFloat64Data{},
wire.MetricDescriptor_CUMULATIVE_DISTRIBUTION,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := dataToMetricDescriptorType(tt.data)
if !reflect.DeepEqual(got, tt.want) {
t.Fatalf("Got:\n%s\nWant:\n%s", marshaled(got), marshaled(tt.want))
}
})
}
}
func TestDataToTimeseries(t *testing.T) {
epoch := time.Unix(0, 0)
epochTimestamp := convertTimestamp(epoch)
end := time.Unix(30, 0)
endTimestamp := convertTimestamp(end)
tests := []struct {
name string
data telemetry.MetricData
start time.Time
want []*wire.TimeSeries
}{
{
"nil data",
nil,
time.Time{},
nil,
},
{
"Int64Data",
&metric.Int64Data{
Rows: []int64{
1,
2,
3,
},
EndTime: &end,
},
epoch,
[]*wire.TimeSeries{
&wire.TimeSeries{
Points: []*wire.Point{
&wire.Point{
Value: wire.PointInt64Value{Int64Value: 1},
Timestamp: &endTimestamp,
},
},
StartTimestamp: &epochTimestamp,
},
&wire.TimeSeries{
Points: []*wire.Point{
&wire.Point{
Value: wire.PointInt64Value{Int64Value: 2},
Timestamp: &endTimestamp,
},
},
StartTimestamp: &epochTimestamp,
},
&wire.TimeSeries{
Points: []*wire.Point{
&wire.Point{
Value: wire.PointInt64Value{Int64Value: 3},
Timestamp: &endTimestamp,
},
},
StartTimestamp: &epochTimestamp,
},
},
},
{
"Float64Data",
&metric.Float64Data{
Rows: []float64{
1.5,
4.5,
},
EndTime: &end,
},
epoch,
[]*wire.TimeSeries{
&wire.TimeSeries{
Points: []*wire.Point{
&wire.Point{
Value: wire.PointDoubleValue{DoubleValue: 1.5},
Timestamp: &endTimestamp,
},
},
StartTimestamp: &epochTimestamp,
},
&wire.TimeSeries{
Points: []*wire.Point{
&wire.Point{
Value: wire.PointDoubleValue{DoubleValue: 4.5},
Timestamp: &endTimestamp,
},
},
StartTimestamp: &epochTimestamp,
},
},
},
{
"HistogramInt64Data",
&metric.HistogramInt64Data{
Rows: []*metric.HistogramInt64Row{
{
Count: 6,
Sum: 40,
Values: []int64{
1,
2,
3,
},
},
},
Info: &metric.HistogramInt64{
Buckets: []int64{
0, 5, 10,
},
},
EndTime: &end,
},
epoch,
[]*wire.TimeSeries{
&wire.TimeSeries{
Points: []*wire.Point{
&wire.Point{
Value: wire.PointDistributionValue{
DistributionValue: &wire.DistributionValue{
Count: 6,
Sum: 40,
Buckets: []*wire.Bucket{
{
Count: 1,
},
{
Count: 2,
},
{
Count: 3,
},
},
BucketOptions: wire.BucketOptionsExplicit{
Bounds: []float64{
0, 5, 10,
},
},
},
},
Timestamp: &endTimestamp,
},
},
StartTimestamp: &epochTimestamp,
},
},
},
{
"HistogramFloat64Data",
&metric.HistogramFloat64Data{
Rows: []*metric.HistogramFloat64Row{
{
Count: 3,
Sum: 10,
Values: []int64{
1,
2,
},
},
},
Info: &metric.HistogramFloat64{
Buckets: []float64{
0, 5,
},
},
EndTime: &end,
},
epoch,
[]*wire.TimeSeries{
&wire.TimeSeries{
Points: []*wire.Point{
&wire.Point{
Value: wire.PointDistributionValue{
DistributionValue: &wire.DistributionValue{
Count: 3,
Sum: 10,
Buckets: []*wire.Bucket{
{
Count: 1,
},
{
Count: 2,
},
},
BucketOptions: wire.BucketOptionsExplicit{
Bounds: []float64{
0, 5,
},
},
},
},
Timestamp: &endTimestamp,
},
},
StartTimestamp: &epochTimestamp,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := dataToTimeseries(tt.data, tt.start)
if !reflect.DeepEqual(got, tt.want) {
t.Fatalf("Got:\n%s\nWant:\n%s", marshaled(got), marshaled(tt.want))
}
})
}
}
func TestNumRows(t *testing.T) {
tests := []struct {
name string
data telemetry.MetricData
want int
}{
{
"nil data",
nil,
0,
},
{
"1 row Int64Data",
&metric.Int64Data{
Rows: []int64{
0,
},
},
1,
},
{
"2 row Float64Data",
&metric.Float64Data{
Rows: []float64{
0,
1.0,
},
},
2,
},
{
"1 row HistogramInt64Data",
&metric.HistogramInt64Data{
Rows: []*metric.HistogramInt64Row{
{},
},
},
1,
},
{
"3 row HistogramFloat64Data",
&metric.HistogramFloat64Data{
Rows: []*metric.HistogramFloat64Row{
{},
{},
{},
},
},
3,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := numRows(tt.data)
if !reflect.DeepEqual(got, tt.want) {
t.Fatalf("Got:\n%s\nWant:\n%s", marshaled(got), marshaled(tt.want))
}
})
}
}
func TestDataToPoints(t *testing.T) {
end := time.Unix(30, 0)
endTimestamp := convertTimestamp(end)
int64Data := &metric.Int64Data{
Rows: []int64{
0,
10,
},
EndTime: &end,
}
float64Data := &metric.Float64Data{
Rows: []float64{
0.5,
0.25,
},
EndTime: &end,
}
histogramInt64Data := &metric.HistogramInt64Data{
Rows: []*metric.HistogramInt64Row{
{
Count: 6,
Sum: 40,
Values: []int64{
1,
2,
3,
},
},
{
Count: 12,
Sum: 80,
Values: []int64{
2,
4,
6,
},
},
},
Info: &metric.HistogramInt64{
Buckets: []int64{
0, 5, 10,
},
},
EndTime: &end,
}
histogramFloat64Data := &metric.HistogramFloat64Data{
Rows: []*metric.HistogramFloat64Row{
{
Count: 6,
Sum: 40,
Values: []int64{
1,
2,
3,
},
},
{
Count: 18,
Sum: 80,
Values: []int64{
3,
6,
9,
},
},
},
Info: &metric.HistogramFloat64{
Buckets: []float64{
0, 5, 10,
},
},
EndTime: &end,
}
tests := []struct {
name string
data telemetry.MetricData
i int
want []*wire.Point
}{
{
"nil data",
nil,
0,
nil,
},
{
"Int64data index 0",
int64Data,
0,
[]*wire.Point{
{
Value: wire.PointInt64Value{
Int64Value: 0,
},
Timestamp: &endTimestamp,
},
},
},
{
"Int64data index 1",
int64Data,
1,
[]*wire.Point{
{
Value: wire.PointInt64Value{
Int64Value: 10,
},
Timestamp: &endTimestamp,
},
},
},
{
"Float64Data index 0",
float64Data,
0,
[]*wire.Point{
{
Value: wire.PointDoubleValue{
DoubleValue: 0.5,
},
Timestamp: &endTimestamp,
},
},
},
{
"Float64Data index 1",
float64Data,
1,
[]*wire.Point{
{
Value: wire.PointDoubleValue{
DoubleValue: 0.25,
},
Timestamp: &endTimestamp,
},
},
},
{
"HistogramInt64Data index 0",
histogramInt64Data,
0,
[]*wire.Point{
{
Value: wire.PointDistributionValue{
DistributionValue: &wire.DistributionValue{
Count: 6,
Sum: 40,
Buckets: []*wire.Bucket{
{
Count: 1,
},
{
Count: 2,
},
{
Count: 3,
},
},
BucketOptions: wire.BucketOptionsExplicit{
Bounds: []float64{
0, 5, 10,
},
},
},
},
Timestamp: &endTimestamp,
},
},
},
{
"HistogramInt64Data index 1",
histogramInt64Data,
1,
[]*wire.Point{
{
Value: wire.PointDistributionValue{
DistributionValue: &wire.DistributionValue{
Count: 12,
Sum: 80,
Buckets: []*wire.Bucket{
{
Count: 2,
},
{
Count: 4,
},
{
Count: 6,
},
},
BucketOptions: wire.BucketOptionsExplicit{
Bounds: []float64{
0, 5, 10,
},
},
},
},
Timestamp: &endTimestamp,
},
},
},
{
"HistogramFloat64Data index 0",
histogramFloat64Data,
0,
[]*wire.Point{
{
Value: wire.PointDistributionValue{
DistributionValue: &wire.DistributionValue{
Count: 6,
Sum: 40,
Buckets: []*wire.Bucket{
{
Count: 1,
},
{
Count: 2,
},
{
Count: 3,
},
},
BucketOptions: wire.BucketOptionsExplicit{
Bounds: []float64{
0, 5, 10,
},
},
},
},
Timestamp: &endTimestamp,
},
},
},
{
"HistogramFloat64Data index 1",
histogramFloat64Data,
1,
[]*wire.Point{
{
Value: wire.PointDistributionValue{
DistributionValue: &wire.DistributionValue{
Count: 18,
Sum: 80,
Buckets: []*wire.Bucket{
{
Count: 3,
},
{
Count: 6,
},
{
Count: 9,
},
},
BucketOptions: wire.BucketOptionsExplicit{
Bounds: []float64{
0, 5, 10,
},
},
},
},
Timestamp: &endTimestamp,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := dataToPoints(tt.data, tt.i)
if !reflect.DeepEqual(got, tt.want) {
t.Fatalf("Got:\n%s\nWant:\n%s", marshaled(got), marshaled(tt.want))
}
})
}
}
func TestDistributionToPoints(t *testing.T) {
end := time.Unix(30, 0)
endTimestamp := convertTimestamp(end)
tests := []struct {
name string
counts []int64
count int64
sum float64
buckets []float64
end time.Time
want []*wire.Point
}{
{
name: "3 buckets",
counts: []int64{
1,
2,
3,
},
count: 6,
sum: 40,
buckets: []float64{
0, 5, 10,
},
end: end,
want: []*wire.Point{
{
Value: wire.PointDistributionValue{
DistributionValue: &wire.DistributionValue{
Count: 6,
Sum: 40,
// TODO: SumOfSquaredDeviation?
Buckets: []*wire.Bucket{
&wire.Bucket{
Count: 1,
},
&wire.Bucket{
Count: 2,
},
&wire.Bucket{
Count: 3,
},
},
BucketOptions: wire.BucketOptionsExplicit{
Bounds: []float64{
0, 5, 10,
},
},
},
},
Timestamp: &endTimestamp,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := distributionToPoints(tt.counts, tt.count, tt.sum, tt.buckets, tt.end)
if !reflect.DeepEqual(got, tt.want) {
t.Fatalf("Got:\n%s\nWant:\n%s", marshaled(got), marshaled(tt.want))
}
})
}
}
func TestInfoKeysToLabelKeys(t *testing.T) {
tests := []struct {
name string
infoKeys []interface{}
want []*wire.LabelKey
}{
{
"empty infoKeys",
[]interface{}{},
[]*wire.LabelKey{},
},
{
"empty string infoKey",
[]interface{}{""},
[]*wire.LabelKey{
&wire.LabelKey{
Key: "",
},
},
},
{
"non-empty string infoKey",
[]interface{}{"hello"},
[]*wire.LabelKey{
&wire.LabelKey{
Key: "hello",
},
},
},
{
"multiple element infoKey",
[]interface{}{"hello", "world"},
[]*wire.LabelKey{
&wire.LabelKey{
Key: "hello",
},
&wire.LabelKey{
Key: "world",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := infoKeysToLabelKeys(tt.infoKeys)
if !reflect.DeepEqual(got, tt.want) {
t.Fatalf("Got:\n%s\nWant:\n%s", marshaled(got), marshaled(tt.want))
}
})
}
}