pkg/metrics/stackdriver_exporter_test.go

369 lines
12 KiB
Go

/*
Copyright 2019 The Knative 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 metrics
import (
"path"
"testing"
"contrib.go.opencensus.io/exporter/stackdriver"
"go.opencensus.io/stats"
"go.opencensus.io/stats/view"
"go.opencensus.io/tag"
. "knative.dev/pkg/logging/testing"
"knative.dev/pkg/metrics/metricskey"
)
// TODO UTs should move to eventing and serving, as appropriate.
// See https://github.com/knative/pkg/issues/608
var (
testGcpMetadata = gcpMetadata{
project: "test-project",
location: "test-location",
cluster: "test-cluster",
}
supportedServingMetricsTestCases = []struct {
name string
domain string
component string
metricName string
}{{
name: "activator metric",
domain: servingDomain,
component: "activator",
metricName: "request_count",
}, {
name: "autoscaler metric",
domain: servingDomain,
component: "autoscaler",
metricName: "desired_pods",
}}
supportedEventingBrokerMetricsTestCases = []struct {
name string
domain string
component string
metricName string
}{{
name: "broker metric",
domain: eventingDomain,
component: "broker",
metricName: "event_count",
}}
supportedEventingTriggerMetricsTestCases = []struct {
name string
domain string
component string
metricName string
}{{
name: "trigger metric",
domain: eventingDomain,
component: "trigger",
metricName: "event_count",
}, {
name: "trigger metric",
domain: eventingDomain,
component: "trigger",
metricName: "event_processing_latencies",
}, {
name: "trigger metric",
domain: eventingDomain,
component: "trigger",
metricName: "event_dispatch_latencies",
}}
supportedEventingSourceMetricsTestCases = []struct {
name string
domain string
component string
metricName string
}{{
name: "source metric",
domain: eventingDomain,
component: "source",
metricName: "event_count",
}}
unsupportedMetricsTestCases = []struct {
name string
domain string
component string
metricName string
}{{
name: "unsupported domain",
domain: "unsupported",
component: "activator",
metricName: "request_count",
}, {
name: "unsupported component",
domain: servingDomain,
component: "unsupported",
metricName: "request_count",
}, {
name: "unsupported metric",
domain: servingDomain,
component: "activator",
metricName: "unsupported",
}, {
name: "unsupported component",
domain: eventingDomain,
component: "unsupported",
metricName: "event_count",
}, {
name: "unsupported metric",
domain: eventingDomain,
component: "broker",
metricName: "unsupported",
}}
)
func fakeGcpMetadataFun() *gcpMetadata {
return &testGcpMetadata
}
type fakeExporter struct{}
func (fe *fakeExporter) ExportView(vd *view.Data) {}
func (fe *fakeExporter) Flush() {}
func newFakeExporter(o stackdriver.Options) (view.Exporter, error) {
return &fakeExporter{}, nil
}
func TestGetMonitoredResourceFunc_UseKnativeRevision(t *testing.T) {
for _, testCase := range supportedServingMetricsTestCases {
testView = &view.View{
Description: "Test View",
Measure: stats.Int64(testCase.metricName, "Test Measure", stats.UnitNone),
Aggregation: view.LastValue(),
TagKeys: []tag.Key{},
}
mrf := getMonitoredResourceFunc(path.Join(testCase.domain, testCase.component), &testGcpMetadata)
newTags, monitoredResource := mrf(testView, revisionTestTags)
gotResType, labels := monitoredResource.MonitoredResource()
wantedResType := "knative_revision"
if gotResType != wantedResType {
t.Fatalf("MonitoredResource=%v, want %v", gotResType, wantedResType)
}
got := getResourceLabelValue(metricskey.LabelRouteName, newTags)
if got != testRoute {
t.Errorf("expected new tag: %v, got: %v", routeKey, newTags)
}
got, ok := labels[metricskey.LabelNamespaceName]
if !ok || got != testNS {
t.Errorf("expected label %v with value %v, got: %v", metricskey.LabelNamespaceName, testNS, got)
}
got, ok = labels[metricskey.LabelConfigurationName]
if !ok || got != metricskey.ValueUnknown {
t.Errorf("expected label %v with value %v, got: %v", metricskey.LabelConfigurationName, metricskey.ValueUnknown, got)
}
}
}
func TestGetMonitoredResourceFunc_UseKnativeBroker(t *testing.T) {
for _, testCase := range supportedEventingBrokerMetricsTestCases {
testView = &view.View{
Description: "Test View",
Measure: stats.Int64(testCase.metricName, "Test Measure", stats.UnitDimensionless),
Aggregation: view.LastValue(),
TagKeys: []tag.Key{},
}
mrf := getMonitoredResourceFunc(path.Join(testCase.domain, testCase.component), &testGcpMetadata)
newTags, monitoredResource := mrf(testView, brokerTestTags)
gotResType, labels := monitoredResource.MonitoredResource()
wantedResType := "knative_broker"
if gotResType != wantedResType {
t.Fatalf("MonitoredResource=%v, want %v", gotResType, wantedResType)
}
got := getResourceLabelValue(metricskey.LabelEventType, newTags)
if got != testEventType {
t.Errorf("expected new tag: %v, got: %v", eventTypeKey, newTags)
}
got = getResourceLabelValue(metricskey.LabelEventSource, newTags)
if got != testEventSource {
t.Errorf("expected new tag: %v, got: %v", eventSourceKey, newTags)
}
got, ok := labels[metricskey.LabelNamespaceName]
if !ok || got != testNS {
t.Errorf("expected label %v with value %v, got: %v", metricskey.LabelNamespaceName, testNS, got)
}
got, ok = labels[metricskey.LabelBrokerName]
if !ok || got != testBroker {
t.Errorf("expected label %v with value %v, got: %v", metricskey.LabelBrokerName, testBroker, got)
}
}
}
func TestGetMonitoredResourceFunc_UseKnativeTrigger(t *testing.T) {
for _, testCase := range supportedEventingTriggerMetricsTestCases {
testView = &view.View{
Description: "Test View",
Measure: stats.Int64(testCase.metricName, "Test Measure", stats.UnitDimensionless),
Aggregation: view.LastValue(),
TagKeys: []tag.Key{},
}
mrf := getMonitoredResourceFunc(path.Join(testCase.domain, testCase.component), &testGcpMetadata)
newTags, monitoredResource := mrf(testView, triggerTestTags)
gotResType, labels := monitoredResource.MonitoredResource()
wantedResType := "knative_trigger"
if gotResType != wantedResType {
t.Fatalf("MonitoredResource=%v, want %v", gotResType, wantedResType)
}
got := getResourceLabelValue(metricskey.LabelFilterType, newTags)
if got != testFilterType {
t.Errorf("expected new tag: %v, got: %v", filterTypeKey, newTags)
}
got = getResourceLabelValue(metricskey.LabelFilterSource, newTags)
if got != testFilterSource {
t.Errorf("expected new tag: %v, got: %v", filterSourceKey, newTags)
}
got, ok := labels[metricskey.LabelNamespaceName]
if !ok || got != testNS {
t.Errorf("expected label %v with value %v, got: %v", metricskey.LabelNamespaceName, testNS, got)
}
got, ok = labels[metricskey.LabelBrokerName]
if !ok || got != testBroker {
t.Errorf("expected label %v with value %v, got: %v", metricskey.LabelBrokerName, testBroker, got)
}
}
}
func TestGetMonitoredResourceFunc_UseKnativeSource(t *testing.T) {
for _, testCase := range supportedEventingSourceMetricsTestCases {
testView = &view.View{
Description: "Test View",
Measure: stats.Int64(testCase.metricName, "Test Measure", stats.UnitDimensionless),
Aggregation: view.LastValue(),
TagKeys: []tag.Key{},
}
mrf := getMonitoredResourceFunc(path.Join(testCase.domain, testCase.component), &testGcpMetadata)
newTags, monitoredResource := mrf(testView, sourceTestTags)
gotResType, labels := monitoredResource.MonitoredResource()
wantedResType := "knative_source"
if gotResType != wantedResType {
t.Fatalf("MonitoredResource=%v, want %v", gotResType, wantedResType)
}
got := getResourceLabelValue(metricskey.LabelEventType, newTags)
if got != testEventType {
t.Errorf("expected new tag: %v, got: %v", eventTypeKey, newTags)
}
got = getResourceLabelValue(metricskey.LabelEventSource, newTags)
if got != testEventSource {
t.Errorf("expected new tag: %v, got: %v", eventSourceKey, newTags)
}
got, ok := labels[metricskey.LabelNamespaceName]
if !ok || got != testNS {
t.Errorf("expected label %v with value %v, got: %v", metricskey.LabelNamespaceName, testNS, got)
}
got, ok = labels[metricskey.LabelSourceName]
if !ok || got != testSource {
t.Errorf("expected label %v with value %v, got: %v", metricskey.LabelSourceName, testSource, got)
}
got, ok = labels[metricskey.LabelSourceResourceGroup]
if !ok || got != testSourceResourceGroup {
t.Errorf("expected label %v with value %v, got: %v", metricskey.LabelSourceResourceGroup, testSourceResourceGroup, got)
}
}
}
func TestGetMonitoredResourceFunc_UseGlobal(t *testing.T) {
for _, testCase := range unsupportedMetricsTestCases {
testView = &view.View{
Description: "Test View",
Measure: stats.Int64(testCase.metricName, "Test Measure", stats.UnitNone),
Aggregation: view.LastValue(),
TagKeys: []tag.Key{},
}
mrf := getMonitoredResourceFunc(path.Join(testCase.domain, testCase.component), &testGcpMetadata)
newTags, monitoredResource := mrf(testView, revisionTestTags)
gotResType, labels := monitoredResource.MonitoredResource()
wantedResType := "global"
if gotResType != wantedResType {
t.Fatalf("MonitoredResource=%v, want: %v", gotResType, wantedResType)
}
got := getResourceLabelValue(metricskey.LabelNamespaceName, newTags)
if got != testNS {
t.Errorf("expected new tag %v with value %v, got: %v", routeKey, testNS, newTags)
}
if len(labels) != 0 {
t.Errorf("expected no label, got: %v", labels)
}
}
}
func TestGetgetMetricTypeFunc_UseKnativeDomain(t *testing.T) {
for _, testCase := range supportedServingMetricsTestCases {
testView = &view.View{
Description: "Test View",
Measure: stats.Int64(testCase.metricName, "Test Measure", stats.UnitNone),
Aggregation: view.LastValue(),
TagKeys: []tag.Key{},
}
mtf := getMetricTypeFunc(
path.Join(testCase.domain, testCase.component),
path.Join(customMetricTypePrefix, testCase.component))
gotMetricType := mtf(testView)
wantedMetricType := path.Join(testCase.domain, testCase.component, testView.Measure.Name())
if gotMetricType != wantedMetricType {
t.Fatalf("getMetricType=%v, want %v", gotMetricType, wantedMetricType)
}
}
}
func TestGetgetMetricTypeFunc_UseCustomDomain(t *testing.T) {
for _, testCase := range unsupportedMetricsTestCases {
testView = &view.View{
Description: "Test View",
Measure: stats.Int64(testCase.metricName, "Test Measure", stats.UnitNone),
Aggregation: view.LastValue(),
TagKeys: []tag.Key{},
}
mtf := getMetricTypeFunc(
path.Join(testCase.domain, testCase.component),
path.Join(customMetricTypePrefix, testCase.component))
gotMetricType := mtf(testView)
wantedMetricType := path.Join(customMetricTypePrefix, testCase.component, testView.Measure.Name())
if gotMetricType != wantedMetricType {
t.Fatalf("getMetricType=%v, want %v", gotMetricType, wantedMetricType)
}
}
}
func TestNewStackdriverExporterWithMetadata(t *testing.T) {
e, err := newStackdriverExporter(&metricsConfig{
domain: servingDomain,
component: "autoscaler",
backendDestination: Stackdriver,
stackdriverProjectID: testProj}, TestLogger(t))
if err != nil {
t.Error(err)
}
if e == nil {
t.Error("expected a non-nil metrics exporter")
}
}