Add helper functions for metric tests in serving (#1564)

* Add helper functions for metric tests in seving

* typo

* Add WithResource to simply the code
This commit is contained in:
jjzeng-seattle 2020-07-29 03:08:59 -07:00 committed by GitHub
parent 7ea21a17b9
commit 68b3eeeaab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 112 additions and 23 deletions

View File

@ -41,6 +41,10 @@ type Value struct {
Int64 *int64 Int64 *int64
Float64 *float64 Float64 *float64
Distribution *metricdata.Distribution Distribution *metricdata.Distribution
// VerifyDistributionCountOnly makes Equal compare the Distribution with the
// field Count only, and ingore all other fields of Distribution.
// This is ingored when the value is not a Distribution.
VerifyDistributionCountOnly bool
} }
// Metric provides a simplified (for testing) implementation of a metric report // Metric provides a simplified (for testing) implementation of a metric report
@ -93,8 +97,10 @@ func NewMetric(metric *metricdata.Metric) Metric {
for _, ts := range metric.TimeSeries { for _, ts := range metric.TimeSeries {
tags := make(map[string]string, len(metric.Descriptor.LabelKeys)) tags := make(map[string]string, len(metric.Descriptor.LabelKeys))
for i, k := range metric.Descriptor.LabelKeys { for i, k := range metric.Descriptor.LabelKeys {
if ts.LabelValues[i].Present {
tags[k.Key] = ts.LabelValues[i].Value tags[k.Key] = ts.LabelValues[i].Value
} }
}
v := Value{Tags: tags} v := Value{Tags: tags}
ts.Points[0].ReadValue(&v) ts.Points[0].ReadValue(&v)
value.Values = append(value.Values, v) value.Values = append(value.Values, v)
@ -139,30 +145,37 @@ func GetOneMetric(name string) Metric {
return m[0] return m[0]
} }
func genericMetricFactory(name string, v Value, keyvalues ...string) Metric { // IntMetric creates an Int64 metric.
if len(keyvalues)%2 != 0 { func IntMetric(name string, value int64, tags map[string]string) Metric {
panic("Odd number of arguments to CountMetric")
}
if v.Tags == nil {
v.Tags = make(map[string]string, len(keyvalues)/2)
}
for i := 0; i < len(keyvalues); i += 2 {
v.Tags[keyvalues[i]] = keyvalues[i+1]
}
return Metric{ return Metric{
Name: name, Name: name,
Values: []Value{v}, Values: []Value{{Int64: &value, Tags: tags}},
} }
} }
// IntMetric is a shortcut factory for creating an Int64 metric. // FloatMetric creates a Float64 metric
func IntMetric(name string, value int64, keyvalues ...string) Metric { func FloatMetric(name string, value float64, tags map[string]string) Metric {
return genericMetricFactory(name, Value{Int64: &value}, keyvalues...) return Metric{
Name: name,
Values: []Value{{Float64: &value, Tags: tags}},
}
} }
// FloatMetric is a shortcut factor for creating a Float64 metric // DistributionCountOnlyMetric creates a distrubtion metric for test, and verifying only the count.
func FloatMetric(name string, value float64, keyvalues ...string) Metric { func DistributionCountOnlyMetric(name string, count int64, tags map[string]string) Metric {
return genericMetricFactory(name, Value{Float64: &value}, keyvalues...) return Metric{
Name: name,
Values: []Value{{
Distribution: &metricdata.Distribution{Count: count},
Tags: tags,
VerifyDistributionCountOnly: true}},
}
}
// WithResource sets the resource of the metric.
func (m Metric) WithResource(r *resource.Resource) Metric {
m.Resource = r
return m
} }
// AssertMetric verifies that the metrics have the specified values. Note that // AssertMetric verifies that the metrics have the specified values. Note that
@ -298,6 +311,9 @@ func (v Value) Equal(other Value) bool {
if v.Distribution.Count != other.Distribution.Count { if v.Distribution.Count != other.Distribution.Count {
return false return false
} }
if v.VerifyDistributionCountOnly || other.VerifyDistributionCountOnly {
return true
}
if v.Distribution.Sum != other.Distribution.Sum { if v.Distribution.Sum != other.Distribution.Sum {
return false return false
} }

View File

@ -222,6 +222,24 @@ func TestDistributionEqual(t *testing.T) {
Buckets: buckets(1, 0, 3, 1), Buckets: buckets(1, 0, 3, 1),
}, },
}, },
}, {
name: "Equal when count only is set",
want: Value{
Tags: map[string]string{"key1": "val1"},
Distribution: &metricdata.Distribution{
Count: 5,
},
VerifyDistributionCountOnly: true,
},
}, {
name: "Not equal when count only is not set",
want: Value{
Tags: map[string]string{"key1": "val1"},
Distribution: &metricdata.Distribution{
Count: 5,
},
},
notEqual: true,
}, { }, {
name: "Missing summary", name: "Missing summary",
want: Value{ want: Value{
@ -281,13 +299,20 @@ func TestDistributionEqual(t *testing.T) {
} }
func TestMetricShortcuts(t *testing.T) { func TestMetricShortcuts(t *testing.T) {
tags := map[string]string{
"foo": "bar",
}
r := &resource.Resource{
Type: "test-resource",
Labels: map[string]string{"foo1": "bar1"},
}
tests := []struct { tests := []struct {
name string name string
want Metric want Metric
got metricdata.Metric got metricdata.Metric
}{{ }{{
name: "IntMetric", name: "IntMetric",
want: IntMetric("test/int", 17, "key1", "val1", "key2", "val2"), want: IntMetric("test/int", 17, map[string]string{"key1": "val1", "key2": "val2"}),
got: metricdata.Metric{ got: metricdata.Metric{
Descriptor: metricdata.Descriptor{ Descriptor: metricdata.Descriptor{
Name: "test/int", Name: "test/int",
@ -300,7 +325,7 @@ func TestMetricShortcuts(t *testing.T) {
}, },
}, { }, {
name: "FloatMetric", name: "FloatMetric",
want: FloatMetric("test/float", 0.17, "key1", "val1", "key2", "val2"), want: FloatMetric("test/float", 0.17, map[string]string{"key1": "val1", "key2": "val2"}),
got: metricdata.Metric{ got: metricdata.Metric{
Descriptor: metricdata.Descriptor{ Descriptor: metricdata.Descriptor{
Name: "test/float", Name: "test/float",
@ -311,6 +336,54 @@ func TestMetricShortcuts(t *testing.T) {
Points: []metricdata.Point{metricdata.NewFloat64Point(time.Now(), 0.17)}, Points: []metricdata.Point{metricdata.NewFloat64Point(time.Now(), 0.17)},
}}, }},
}, },
}, {
name: "IntMetricWithResource",
want: IntMetric("test/int", 18, tags).WithResource(r),
got: metricdata.Metric{
Descriptor: metricdata.Descriptor{
Name: "test/int",
LabelKeys: []metricdata.LabelKey{{"foo", ""}},
},
Resource: r,
TimeSeries: []*metricdata.TimeSeries{{
LabelValues: []metricdata.LabelValue{{"bar", true}},
Points: []metricdata.Point{metricdata.NewInt64Point(time.Now(), 18)},
}},
},
}, {
name: "FloatMetricWithResource",
want: FloatMetric("test/float", 0.18, tags).WithResource(r),
got: metricdata.Metric{
Descriptor: metricdata.Descriptor{
Name: "test/float",
LabelKeys: []metricdata.LabelKey{{"foo", ""}},
},
Resource: r,
TimeSeries: []*metricdata.TimeSeries{{
LabelValues: []metricdata.LabelValue{{"bar", true}},
Points: []metricdata.Point{metricdata.NewFloat64Point(time.Now(), 0.18)},
}},
},
}, {
name: "DistributionCountOnlyMetricWithResource",
want: DistributionCountOnlyMetric("test/distribution", 19, tags).WithResource(r),
got: metricdata.Metric{
Descriptor: metricdata.Descriptor{
Name: "test/distribution",
LabelKeys: []metricdata.LabelKey{{"foo", ""}},
},
Resource: r,
TimeSeries: []*metricdata.TimeSeries{{
LabelValues: []metricdata.LabelValue{{"bar", true}},
Points: []metricdata.Point{metricdata.NewDistributionPoint(time.Now(), &metricdata.Distribution{
Count: 19,
Sum: 25.5,
SumOfSquaredDeviation: 45.2,
BucketOptions: bucketOpts(2, 4, 8),
Buckets: buckets(1, 3, 1, 0),
})},
}},
},
}} }}
for _, tc := range tests { for _, tc := range tests {

View File

@ -85,8 +85,8 @@ func TestWorkqueueMetrics(t *testing.T) {
metricstest.AssertMetricExists(t, "adds", "depth") metricstest.AssertMetricExists(t, "adds", "depth")
metricstest.AssertNoMetric(t, "latency", "retries", "work_duration", metricstest.AssertNoMetric(t, "latency", "retries", "work_duration",
"unfinished_work_seconds", "longest_running_processor_seconds") "unfinished_work_seconds", "longest_running_processor_seconds")
wantAdd := metricstest.IntMetric("adds", 1, "name", queueName) wantAdd := metricstest.IntMetric("adds", 1, map[string]string{"name": queueName})
wantDepth := metricstest.IntMetric("depth", 1, "name", queueName) wantDepth := metricstest.IntMetric("depth", 1, map[string]string{"name": queueName})
metricstest.AssertMetric(t, wantAdd, wantDepth) metricstest.AssertMetric(t, wantAdd, wantDepth)
wq.Add("bar") wq.Add("bar")
@ -123,7 +123,7 @@ func TestWorkqueueMetrics(t *testing.T) {
// It should show up as a retry now. // It should show up as a retry now.
metricstest.AssertMetricExists(t, "retries") metricstest.AssertMetricExists(t, "retries")
metricstest.AssertNoMetric(t, "unfinished_work_seconds", "longest_running_processor_seconds") metricstest.AssertNoMetric(t, "unfinished_work_seconds", "longest_running_processor_seconds")
wantRetries := metricstest.IntMetric("retries", 1, "name", queueName) wantRetries := metricstest.IntMetric("retries", 1, map[string]string{"name": queueName})
metricstest.AssertMetric(t, wantRetries, wantAdd) // It is not added right away. metricstest.AssertMetric(t, wantRetries, wantAdd) // It is not added right away.
// It doesn't show up as an "add" until the rate limit has elapsed. // It doesn't show up as an "add" until the rate limit has elapsed.