blob: e9fd114c4ab6dd72c1ae4bbac1f99d4b31454582 [file] [log] [blame]
// Copyright 2016 The LUCI 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 monitor
import (
"testing"
"time"
"github.com/golang/protobuf/proto"
"go.chromium.org/luci/common/tsmon/distribution"
"go.chromium.org/luci/common/tsmon/field"
"go.chromium.org/luci/common/tsmon/target"
"go.chromium.org/luci/common/tsmon/types"
. "github.com/smartystreets/goconvey/convey"
pb "go.chromium.org/luci/common/tsmon/ts_mon_proto"
)
func TestSerializeDistribution(t *testing.T) {
Convey("Fixed width params", t, func() {
d := distribution.New(distribution.FixedWidthBucketer(10, 20))
dpb := serializeDistribution(d)
So(*dpb, ShouldResemble, pb.MetricsData_Distribution{
Count: proto.Int64(0),
BucketOptions: &pb.MetricsData_Distribution_LinearBuckets{
LinearBuckets: &pb.MetricsData_Distribution_LinearOptions{
NumFiniteBuckets: proto.Int32(20),
Width: proto.Float64(10),
Offset: proto.Float64(0),
},
},
})
})
Convey("Geometric params", t, func() {
d := distribution.New(distribution.GeometricBucketer(2, 20))
dpb := serializeDistribution(d)
So(*dpb, ShouldResemble, pb.MetricsData_Distribution{
Count: proto.Int64(0),
BucketOptions: &pb.MetricsData_Distribution_ExponentialBuckets{
ExponentialBuckets: &pb.MetricsData_Distribution_ExponentialOptions{
NumFiniteBuckets: proto.Int32(20),
GrowthFactor: proto.Float64(2),
Scale: proto.Float64(1),
},
},
})
})
Convey("Populates buckets", t, func() {
d := distribution.New(distribution.FixedWidthBucketer(10, 2))
d.Add(0)
d.Add(1)
d.Add(2)
d.Add(20)
dpb := serializeDistribution(d)
So(*dpb, ShouldResemble, pb.MetricsData_Distribution{
Count: proto.Int64(4),
Mean: proto.Float64(5.75),
BucketOptions: &pb.MetricsData_Distribution_LinearBuckets{
LinearBuckets: &pb.MetricsData_Distribution_LinearOptions{
NumFiniteBuckets: proto.Int32(2),
Width: proto.Float64(10),
Offset: proto.Float64(0),
},
},
BucketCount: []int64{0, 3, 0, 1},
})
})
}
func TestSerializeCell(t *testing.T) {
now := time.Date(2001, 1, 2, 3, 4, 5, 6, time.UTC)
reset := time.Date(2000, 1, 2, 3, 4, 5, 6, time.UTC)
nowTS := &pb.Timestamp{Seconds: proto.Int64(978404645), Nanos: proto.Int32(6)}
resetTS := &pb.Timestamp{Seconds: proto.Int64(946782245), Nanos: proto.Int32(6)}
emptyTask := &pb.MetricsCollection_Task{&pb.Task{
ServiceName: proto.String(""),
JobName: proto.String(""),
DataCenter: proto.String(""),
HostName: proto.String(""),
TaskNum: proto.Int(0),
}}
Convey("Int", t, func() {
ret := SerializeCells([]types.Cell{{
types.MetricInfo{
Name: "foo",
Description: "bar",
Fields: []field.Field{},
ValueType: types.NonCumulativeIntType,
},
types.MetricMetadata{},
types.CellData{
FieldVals: []interface{}{},
Target: &target.Task{},
ResetTime: reset,
Value: int64(42),
},
}}, now)
So(ret, ShouldResemble, []*pb.MetricsCollection{{
TargetSchema: emptyTask,
MetricsDataSet: []*pb.MetricsDataSet{{
MetricName: proto.String("/chrome/infra/foo"),
FieldDescriptor: []*pb.MetricsDataSet_MetricFieldDescriptor{},
StreamKind: pb.StreamKind_GAUGE.Enum(),
ValueType: pb.ValueType_INT64.Enum(),
Description: proto.String("bar"),
Data: []*pb.MetricsData{{
Value: &pb.MetricsData_Int64Value{42},
Field: []*pb.MetricsData_MetricField{},
StartTimestamp: nowTS,
EndTimestamp: nowTS,
}},
}},
}})
})
Convey("Counter", t, func() {
ret := SerializeCells([]types.Cell{{
types.MetricInfo{
Name: "foo",
Description: "bar",
Fields: []field.Field{},
ValueType: types.CumulativeIntType,
},
types.MetricMetadata{},
types.CellData{
FieldVals: []interface{}{},
Target: &target.Task{},
ResetTime: reset,
Value: int64(42),
},
}}, now)
So(ret, ShouldResemble, []*pb.MetricsCollection{{
TargetSchema: emptyTask,
MetricsDataSet: []*pb.MetricsDataSet{{
MetricName: proto.String("/chrome/infra/foo"),
FieldDescriptor: []*pb.MetricsDataSet_MetricFieldDescriptor{},
StreamKind: pb.StreamKind_CUMULATIVE.Enum(),
ValueType: pb.ValueType_INT64.Enum(),
Description: proto.String("bar"),
Data: []*pb.MetricsData{{
Value: &pb.MetricsData_Int64Value{42},
Field: []*pb.MetricsData_MetricField{},
StartTimestamp: resetTS,
EndTimestamp: nowTS,
}},
}},
}})
})
Convey("Float", t, func() {
ret := SerializeCells([]types.Cell{{
types.MetricInfo{
Name: "foo",
Description: "bar",
Fields: []field.Field{},
ValueType: types.NonCumulativeFloatType,
},
types.MetricMetadata{},
types.CellData{
FieldVals: []interface{}{},
Target: &target.Task{},
ResetTime: reset,
Value: float64(42),
},
}}, now)
So(ret, ShouldResemble, []*pb.MetricsCollection{{
TargetSchema: emptyTask,
MetricsDataSet: []*pb.MetricsDataSet{{
MetricName: proto.String("/chrome/infra/foo"),
FieldDescriptor: []*pb.MetricsDataSet_MetricFieldDescriptor{},
StreamKind: pb.StreamKind_GAUGE.Enum(),
ValueType: pb.ValueType_DOUBLE.Enum(),
Description: proto.String("bar"),
Data: []*pb.MetricsData{{
Value: &pb.MetricsData_DoubleValue{42},
Field: []*pb.MetricsData_MetricField{},
StartTimestamp: nowTS,
EndTimestamp: nowTS,
}},
}},
}})
})
Convey("FloatCounter", t, func() {
ret := SerializeCells([]types.Cell{{
types.MetricInfo{
Name: "foo",
Description: "bar",
Fields: []field.Field{},
ValueType: types.CumulativeFloatType,
},
types.MetricMetadata{},
types.CellData{
FieldVals: []interface{}{},
Target: &target.Task{},
ResetTime: reset,
Value: float64(42),
},
}}, now)
So(ret, ShouldResemble, []*pb.MetricsCollection{{
TargetSchema: emptyTask,
MetricsDataSet: []*pb.MetricsDataSet{{
MetricName: proto.String("/chrome/infra/foo"),
FieldDescriptor: []*pb.MetricsDataSet_MetricFieldDescriptor{},
StreamKind: pb.StreamKind_CUMULATIVE.Enum(),
ValueType: pb.ValueType_DOUBLE.Enum(),
Description: proto.String("bar"),
Data: []*pb.MetricsData{{
Value: &pb.MetricsData_DoubleValue{42},
Field: []*pb.MetricsData_MetricField{},
StartTimestamp: resetTS,
EndTimestamp: nowTS,
}},
}},
}})
})
Convey("String", t, func() {
ret := SerializeCells([]types.Cell{{
types.MetricInfo{
Name: "foo",
Description: "bar",
Fields: []field.Field{},
ValueType: types.StringType,
},
types.MetricMetadata{},
types.CellData{
FieldVals: []interface{}{},
Target: &target.Task{},
ResetTime: reset,
Value: "hello",
},
}}, now)
So(ret, ShouldResemble, []*pb.MetricsCollection{{
TargetSchema: emptyTask,
MetricsDataSet: []*pb.MetricsDataSet{{
MetricName: proto.String("/chrome/infra/foo"),
FieldDescriptor: []*pb.MetricsDataSet_MetricFieldDescriptor{},
StreamKind: pb.StreamKind_GAUGE.Enum(),
ValueType: pb.ValueType_STRING.Enum(),
Description: proto.String("bar"),
Data: []*pb.MetricsData{{
Value: &pb.MetricsData_StringValue{"hello"},
Field: []*pb.MetricsData_MetricField{},
StartTimestamp: nowTS,
EndTimestamp: nowTS,
}},
}},
}})
})
Convey("Boolean", t, func() {
ret := SerializeCells([]types.Cell{{
types.MetricInfo{
Name: "foo",
Description: "bar",
Fields: []field.Field{},
ValueType: types.BoolType,
},
types.MetricMetadata{},
types.CellData{
FieldVals: []interface{}{},
Target: &target.Task{},
ResetTime: reset,
Value: true,
},
}}, now)
So(ret, ShouldResemble, []*pb.MetricsCollection{{
TargetSchema: emptyTask,
MetricsDataSet: []*pb.MetricsDataSet{{
MetricName: proto.String("/chrome/infra/foo"),
FieldDescriptor: []*pb.MetricsDataSet_MetricFieldDescriptor{},
StreamKind: pb.StreamKind_GAUGE.Enum(),
ValueType: pb.ValueType_BOOL.Enum(),
Description: proto.String("bar"),
Data: []*pb.MetricsData{{
Value: &pb.MetricsData_BoolValue{true},
Field: []*pb.MetricsData_MetricField{},
StartTimestamp: nowTS,
EndTimestamp: nowTS,
}},
}},
}})
})
Convey("NonDefaultTarget", t, func() {
target := target.Task{
ServiceName: "hello",
JobName: "world",
}
ret := SerializeCells([]types.Cell{{
types.MetricInfo{
Name: "foo",
Description: "bar",
Fields: []field.Field{},
ValueType: types.NonCumulativeIntType,
},
types.MetricMetadata{},
types.CellData{
FieldVals: []interface{}{},
Target: &target,
ResetTime: reset,
Value: int64(42),
},
}}, now)
So(ret, ShouldResemble, []*pb.MetricsCollection{{
TargetSchema: &pb.MetricsCollection_Task{&pb.Task{
ServiceName: proto.String("hello"),
JobName: proto.String("world"),
DataCenter: proto.String(""),
HostName: proto.String(""),
TaskNum: proto.Int(0),
}},
MetricsDataSet: []*pb.MetricsDataSet{{
MetricName: proto.String("/chrome/infra/foo"),
FieldDescriptor: []*pb.MetricsDataSet_MetricFieldDescriptor{},
StreamKind: pb.StreamKind_GAUGE.Enum(),
ValueType: pb.ValueType_INT64.Enum(),
Description: proto.String("bar"),
Data: []*pb.MetricsData{{
Value: &pb.MetricsData_Int64Value{42},
Field: []*pb.MetricsData_MetricField{},
StartTimestamp: nowTS,
EndTimestamp: nowTS,
}},
}},
}})
})
}