blob: be089d3dea43ec753cf38341bb05f448a439a4d0 [file] [log] [blame]
// Copyright Istio 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 model
import (
"reflect"
"testing"
)
import (
listener "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
httpwasm "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/wasm/v3"
httppb "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
wasmfilter "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/wasm/v3"
"github.com/google/go-cmp/cmp"
"google.golang.org/protobuf/types/known/structpb"
wrappers "google.golang.org/protobuf/types/known/wrapperspb"
meshconfig "istio.io/api/mesh/v1alpha1"
tpb "istio.io/api/telemetry/v1alpha1"
"istio.io/api/type/v1beta1"
)
import (
"github.com/apache/dubbo-go-pixiu/pilot/pkg/networking"
"github.com/apache/dubbo-go-pixiu/pkg/config"
"github.com/apache/dubbo-go-pixiu/pkg/config/mesh"
"github.com/apache/dubbo-go-pixiu/pkg/config/schema/collection"
"github.com/apache/dubbo-go-pixiu/pkg/config/schema/collections"
"github.com/apache/dubbo-go-pixiu/pkg/test/util/assert"
)
func createTestTelemetries(configs []config.Config, t *testing.T) *Telemetries {
t.Helper()
store := &telemetryStore{}
for _, cfg := range configs {
store.add(cfg)
}
m := mesh.DefaultMeshConfig()
jsonTextProvider := &meshconfig.MeshConfig_ExtensionProvider{
Name: "envoy-json",
Provider: &meshconfig.MeshConfig_ExtensionProvider_EnvoyFileAccessLog{
EnvoyFileAccessLog: &meshconfig.MeshConfig_ExtensionProvider_EnvoyFileAccessLogProvider{
Path: "/dev/null",
LogFormat: &meshconfig.MeshConfig_ExtensionProvider_EnvoyFileAccessLogProvider_LogFormat{
LogFormat: &meshconfig.MeshConfig_ExtensionProvider_EnvoyFileAccessLogProvider_LogFormat_Labels{
Labels: &structpb.Struct{},
},
},
},
},
}
m.ExtensionProviders = append(m.ExtensionProviders, jsonTextProvider)
environment := &Environment{
ConfigStore: MakeIstioStore(store),
Watcher: mesh.NewFixedWatcher(m),
}
telemetries, err := getTelemetries(environment)
if err != nil {
t.Fatalf("getTelemetries failed: %v", err)
}
return telemetries
}
func newTelemetry(ns string, spec config.Spec) config.Config {
return config.Config{
Meta: config.Meta{
GroupVersionKind: collections.IstioTelemetryV1Alpha1Telemetries.Resource().GroupVersionKind(),
Name: "default",
Namespace: ns,
},
Spec: spec,
}
}
type telemetryStore struct {
ConfigStore
data []struct {
typ config.GroupVersionKind
ns string
cfg config.Config
}
}
func (ts *telemetryStore) add(cfg config.Config) {
ts.data = append(ts.data, struct {
typ config.GroupVersionKind
ns string
cfg config.Config
}{
typ: cfg.GroupVersionKind,
ns: cfg.Namespace,
cfg: cfg,
})
}
func (ts *telemetryStore) Schemas() collection.Schemas {
return collection.SchemasFor()
}
func (ts *telemetryStore) Get(_ config.GroupVersionKind, _, _ string) *config.Config {
return nil
}
func (ts *telemetryStore) List(typ config.GroupVersionKind, namespace string) ([]config.Config, error) {
var configs []config.Config
for _, data := range ts.data {
if data.typ == typ {
if namespace != "" && data.ns == namespace {
continue
}
configs = append(configs, data.cfg)
}
}
return configs, nil
}
func TestAccessLogging(t *testing.T) {
labels := map[string]string{"app": "test"}
sidecar := &Proxy{ConfigNamespace: "default", Metadata: &NodeMetadata{Labels: labels}}
envoy := &tpb.Telemetry{
AccessLogging: []*tpb.AccessLogging{
{
Providers: []*tpb.ProviderRef{
{
Name: "envoy",
},
},
},
},
}
client := &tpb.Telemetry{
AccessLogging: []*tpb.AccessLogging{
{
Match: &tpb.AccessLogging_LogSelector{
Mode: tpb.WorkloadMode_CLIENT,
},
Providers: []*tpb.ProviderRef{
{
Name: "envoy",
},
},
},
},
}
clientDisabled := &tpb.Telemetry{
AccessLogging: []*tpb.AccessLogging{
{
Match: &tpb.AccessLogging_LogSelector{
Mode: tpb.WorkloadMode_CLIENT,
},
Providers: []*tpb.ProviderRef{
{
Name: "envoy",
},
},
Disabled: &wrappers.BoolValue{
Value: true,
},
},
},
}
sidecarClient := &tpb.Telemetry{
Selector: &v1beta1.WorkloadSelector{
MatchLabels: labels,
},
AccessLogging: []*tpb.AccessLogging{
{
Match: &tpb.AccessLogging_LogSelector{
Mode: tpb.WorkloadMode_CLIENT,
},
Providers: []*tpb.ProviderRef{
{
Name: "envoy",
},
},
},
},
}
server := &tpb.Telemetry{
AccessLogging: []*tpb.AccessLogging{
{
Match: &tpb.AccessLogging_LogSelector{
Mode: tpb.WorkloadMode_SERVER,
},
Providers: []*tpb.ProviderRef{
{
Name: "envoy",
},
},
},
},
}
serverDisabled := &tpb.Telemetry{
AccessLogging: []*tpb.AccessLogging{
{
Match: &tpb.AccessLogging_LogSelector{
Mode: tpb.WorkloadMode_SERVER,
},
Providers: []*tpb.ProviderRef{
{
Name: "envoy",
},
},
Disabled: &wrappers.BoolValue{
Value: true,
},
},
},
}
serverAndClient := &tpb.Telemetry{
AccessLogging: []*tpb.AccessLogging{
{
Match: &tpb.AccessLogging_LogSelector{
Mode: tpb.WorkloadMode_CLIENT_AND_SERVER,
},
Providers: []*tpb.ProviderRef{
{
Name: "envoy",
},
},
},
},
}
stackdriver := &tpb.Telemetry{
AccessLogging: []*tpb.AccessLogging{
{
Providers: []*tpb.ProviderRef{
{
Name: "stackdriver",
},
},
},
},
}
empty := &tpb.Telemetry{
AccessLogging: []*tpb.AccessLogging{{}},
}
defaultJSON := &tpb.Telemetry{
AccessLogging: []*tpb.AccessLogging{
{
Providers: []*tpb.ProviderRef{
{
Name: "envoy-json",
},
},
},
},
}
disabled := &tpb.Telemetry{
AccessLogging: []*tpb.AccessLogging{
{
Disabled: &wrappers.BoolValue{Value: true},
},
},
}
nonExistant := &tpb.Telemetry{
AccessLogging: []*tpb.AccessLogging{
{
Providers: []*tpb.ProviderRef{
{
Name: "custom-provider",
},
},
},
},
}
tests := []struct {
name string
cfgs []config.Config
class networking.ListenerClass
proxy *Proxy
defaultProviders []string
want []string
}{
{
"empty",
nil,
networking.ListenerClassSidecarOutbound,
sidecar,
nil,
nil,
},
{
"default provider only",
nil,
networking.ListenerClassSidecarOutbound,
sidecar,
[]string{"envoy"},
[]string{"envoy"},
},
{
"provider only",
[]config.Config{newTelemetry("dubbo-system", envoy)},
networking.ListenerClassSidecarOutbound,
sidecar,
nil,
[]string{"envoy"},
},
{
"client - gateway",
[]config.Config{newTelemetry("dubbo-system", client)},
networking.ListenerClassGateway,
sidecar,
nil,
[]string{"envoy"},
},
{
"client - outbound",
[]config.Config{newTelemetry("dubbo-system", client)},
networking.ListenerClassSidecarOutbound,
sidecar,
nil,
[]string{"envoy"},
},
{
"client - inbound",
[]config.Config{newTelemetry("dubbo-system", client)},
networking.ListenerClassSidecarInbound,
sidecar,
nil,
[]string{},
},
{
"client - disabled server",
[]config.Config{newTelemetry("dubbo-system", client), newTelemetry("default", serverDisabled)},
networking.ListenerClassSidecarOutbound,
sidecar,
nil,
[]string{"envoy"},
},
{
"client - disabled client",
[]config.Config{newTelemetry("dubbo-system", client), newTelemetry("default", clientDisabled)},
networking.ListenerClassSidecarOutbound,
sidecar,
nil,
[]string{},
},
{
"client - disabled - enabled",
[]config.Config{newTelemetry("dubbo-system", client), newTelemetry("default", clientDisabled), newTelemetry("default", sidecarClient)},
networking.ListenerClassSidecarOutbound,
sidecar,
nil,
[]string{"envoy"},
},
{
"server - gateway",
[]config.Config{newTelemetry("dubbo-system", server)},
networking.ListenerClassGateway,
sidecar,
nil,
[]string{},
},
{
"server - inbound",
[]config.Config{newTelemetry("dubbo-system", server)},
networking.ListenerClassSidecarInbound,
sidecar,
nil,
[]string{"envoy"},
},
{
"server - outbound",
[]config.Config{newTelemetry("dubbo-system", server)},
networking.ListenerClassSidecarOutbound,
sidecar,
nil,
[]string{},
},
{
"server and client - gateway",
[]config.Config{newTelemetry("dubbo-system", serverAndClient)},
networking.ListenerClassGateway,
sidecar,
nil,
[]string{"envoy"},
},
{
"server and client - inbound",
[]config.Config{newTelemetry("dubbo-system", serverAndClient)},
networking.ListenerClassSidecarInbound,
sidecar,
nil,
[]string{"envoy"},
},
{
"server and client - outbound",
[]config.Config{newTelemetry("dubbo-system", serverAndClient)},
networking.ListenerClassSidecarOutbound,
sidecar,
nil,
[]string{"envoy"},
},
{
"override default",
[]config.Config{newTelemetry("dubbo-system", envoy)},
networking.ListenerClassSidecarOutbound,
sidecar,
[]string{"stackdriver"},
[]string{"envoy"},
},
{
"override namespace",
[]config.Config{newTelemetry("dubbo-system", envoy), newTelemetry("default", stackdriver)},
networking.ListenerClassSidecarOutbound,
sidecar,
nil,
[]string{"stackdriver"},
},
{
"empty config inherits",
[]config.Config{newTelemetry("dubbo-system", envoy), newTelemetry("default", empty)},
networking.ListenerClassSidecarOutbound,
sidecar,
nil,
[]string{"envoy"},
},
{
"default envoy JSON",
[]config.Config{newTelemetry("dubbo-system", defaultJSON)},
networking.ListenerClassSidecarOutbound,
sidecar,
nil,
[]string{"envoy-json"},
},
{
"disable config",
[]config.Config{newTelemetry("dubbo-system", envoy), newTelemetry("default", disabled)},
networking.ListenerClassSidecarOutbound,
sidecar,
nil,
[]string{},
},
{
"disable default",
[]config.Config{newTelemetry("default", disabled)},
networking.ListenerClassSidecarOutbound,
sidecar,
[]string{"envoy"},
[]string{},
},
{
"non existing",
[]config.Config{newTelemetry("default", nonExistant)},
networking.ListenerClassSidecarOutbound,
sidecar,
[]string{"envoy"},
[]string{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
telemetry := createTestTelemetries(tt.cfgs, t)
telemetry.meshConfig.DefaultProviders.AccessLogging = tt.defaultProviders
al := telemetry.AccessLogging(tt.proxy, tt.class)
var got []string
if al != nil {
got = []string{} // We distinguish between nil vs empty in the test
for _, p := range al.Providers {
got = append(got, p.Name)
}
}
if !reflect.DeepEqual(got, tt.want) {
t.Fatalf("got %v want %v", got, tt.want)
}
})
}
}
func TestAccessLoggingWithFilter(t *testing.T) {
sidecar := &Proxy{ConfigNamespace: "default", Metadata: &NodeMetadata{Labels: map[string]string{"app": "test"}}}
filter1 := &tpb.Telemetry{
AccessLogging: []*tpb.AccessLogging{
{
Providers: []*tpb.ProviderRef{
{
Name: "custom-provider",
},
},
Filter: &tpb.AccessLogging_Filter{
Expression: "response.code >= 400",
},
},
},
}
filter2 := &tpb.Telemetry{
AccessLogging: []*tpb.AccessLogging{
{
Providers: []*tpb.ProviderRef{
{
Name: "custom-provider",
},
},
Filter: &tpb.AccessLogging_Filter{
Expression: "response.code >= 500",
},
},
},
}
tests := []struct {
name string
cfgs []config.Config
proxy *Proxy
defaultProviders []string
want *LoggingConfig
}{
{
"filter",
[]config.Config{newTelemetry("default", filter1)},
sidecar,
[]string{"custom-provider"},
&LoggingConfig{
Filter: &tpb.AccessLogging_Filter{
Expression: "response.code >= 400",
},
},
},
{
"multi-filter",
[]config.Config{newTelemetry("default", filter2), newTelemetry("default", filter1)},
sidecar,
[]string{"custom-provider"},
&LoggingConfig{
Filter: &tpb.AccessLogging_Filter{
Expression: "response.code >= 500",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
telemetry := createTestTelemetries(tt.cfgs, t)
telemetry.meshConfig.DefaultProviders.AccessLogging = tt.defaultProviders
got := telemetry.AccessLogging(tt.proxy, networking.ListenerClassSidecarOutbound)
if !reflect.DeepEqual(got, tt.want) {
t.Fatalf("got %v want %v", got, tt.want)
}
})
}
}
func newTracingConfig(providerName string, disabled bool) *TracingConfig {
return &TracingConfig{
ClientSpec: TracingSpec{
Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: providerName},
Disabled: disabled,
UseRequestIDForTraceSampling: true,
},
ServerSpec: TracingSpec{
Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: providerName},
Disabled: disabled,
UseRequestIDForTraceSampling: true,
},
}
}
const (
reportingEnabled = false
reportingDisabled = !reportingEnabled
)
func TestTracing(t *testing.T) {
sidecar := &Proxy{ConfigNamespace: "default", Metadata: &NodeMetadata{Labels: map[string]string{"app": "test"}}}
envoy := &tpb.Telemetry{
Tracing: []*tpb.Tracing{
{
Providers: []*tpb.ProviderRef{
{
Name: "envoy",
},
},
},
},
}
stackdriver := &tpb.Telemetry{
Tracing: []*tpb.Tracing{
{
Providers: []*tpb.ProviderRef{
{
Name: "stackdriver",
},
},
},
},
}
empty := &tpb.Telemetry{
Tracing: []*tpb.Tracing{{}},
}
disabled := &tpb.Telemetry{
Tracing: []*tpb.Tracing{
{
DisableSpanReporting: &wrappers.BoolValue{Value: true},
},
},
}
overidesA := &tpb.Telemetry{
Tracing: []*tpb.Tracing{
{
RandomSamplingPercentage: &wrappers.DoubleValue{Value: 50.0},
CustomTags: map[string]*tpb.Tracing_CustomTag{
"foo": {},
"bar": {},
},
UseRequestIdForTraceSampling: &wrappers.BoolValue{Value: false},
},
},
}
overidesB := &tpb.Telemetry{
Tracing: []*tpb.Tracing{
{
RandomSamplingPercentage: &wrappers.DoubleValue{Value: 80.0},
CustomTags: map[string]*tpb.Tracing_CustomTag{
"foo": {},
"baz": {},
},
UseRequestIdForTraceSampling: &wrappers.BoolValue{Value: true},
},
},
}
overridesWithDefaultSampling := &tpb.Telemetry{
Tracing: []*tpb.Tracing{
{
CustomTags: map[string]*tpb.Tracing_CustomTag{
"foo": {},
"baz": {},
},
},
},
}
nonExistant := &tpb.Telemetry{
Tracing: []*tpb.Tracing{
{
Providers: []*tpb.ProviderRef{
{
Name: "custom-provider",
},
},
},
},
}
clientSideSampling := &tpb.Telemetry{
Tracing: []*tpb.Tracing{
{
Match: &tpb.Tracing_TracingSelector{
Mode: tpb.WorkloadMode_CLIENT,
},
Providers: []*tpb.ProviderRef{
{
Name: "stackdriver",
},
},
RandomSamplingPercentage: &wrappers.DoubleValue{Value: 99.9},
},
},
}
serverSideDisabled := &tpb.Telemetry{
Tracing: []*tpb.Tracing{
{
Match: &tpb.Tracing_TracingSelector{
Mode: tpb.WorkloadMode_SERVER,
},
DisableSpanReporting: &wrappers.BoolValue{Value: true},
},
},
}
tests := []struct {
name string
cfgs []config.Config
proxy *Proxy
defaultProviders []string
want *TracingConfig
}{
{
"empty",
nil,
sidecar,
nil,
nil,
},
{
"default provider only",
nil,
sidecar,
[]string{"envoy"},
newTracingConfig("envoy", reportingEnabled),
},
{
"provider only",
[]config.Config{newTelemetry("dubbo-system", envoy)},
sidecar,
nil,
newTracingConfig("envoy", reportingEnabled),
},
{
"override default",
[]config.Config{newTelemetry("dubbo-system", envoy)},
sidecar,
[]string{"stackdriver"},
newTracingConfig("envoy", reportingEnabled),
},
{
"override namespace",
[]config.Config{newTelemetry("dubbo-system", envoy), newTelemetry("default", stackdriver)},
sidecar,
nil,
newTracingConfig("stackdriver", reportingEnabled),
},
{
"empty config inherits",
[]config.Config{newTelemetry("dubbo-system", envoy), newTelemetry("default", empty)},
sidecar,
nil,
newTracingConfig("envoy", reportingEnabled),
},
{
"disable config",
[]config.Config{newTelemetry("dubbo-system", envoy), newTelemetry("default", disabled)},
sidecar,
nil,
newTracingConfig("envoy", reportingDisabled),
},
{
"disable default",
[]config.Config{newTelemetry("default", disabled)},
sidecar,
[]string{"envoy"},
newTracingConfig("envoy", reportingDisabled),
},
{
"non existing",
[]config.Config{newTelemetry("default", nonExistant)},
sidecar,
[]string{"envoy"},
&TracingConfig{
ClientSpec: TracingSpec{Disabled: true, UseRequestIDForTraceSampling: true},
ServerSpec: TracingSpec{Disabled: true, UseRequestIDForTraceSampling: true},
},
},
{
"overrides",
[]config.Config{newTelemetry("dubbo-system", overidesA)},
sidecar,
[]string{"envoy"},
&TracingConfig{
ClientSpec: TracingSpec{
Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: "envoy"},
RandomSamplingPercentage: 50.0,
CustomTags: map[string]*tpb.Tracing_CustomTag{
"foo": {},
"bar": {},
},
UseRequestIDForTraceSampling: false,
}, ServerSpec: TracingSpec{
Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: "envoy"},
RandomSamplingPercentage: 50.0,
CustomTags: map[string]*tpb.Tracing_CustomTag{
"foo": {},
"bar": {},
},
UseRequestIDForTraceSampling: false,
},
},
},
{
"overrides with default sampling",
[]config.Config{newTelemetry("dubbo-system", overridesWithDefaultSampling)},
sidecar,
[]string{"envoy"},
&TracingConfig{
ClientSpec: TracingSpec{
Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: "envoy"},
RandomSamplingPercentage: 0.0,
CustomTags: map[string]*tpb.Tracing_CustomTag{
"foo": {},
"baz": {},
},
UseRequestIDForTraceSampling: true,
}, ServerSpec: TracingSpec{
Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: "envoy"},
RandomSamplingPercentage: 0.0,
CustomTags: map[string]*tpb.Tracing_CustomTag{
"foo": {},
"baz": {},
},
UseRequestIDForTraceSampling: true,
},
},
},
{
"multi overrides",
[]config.Config{
newTelemetry("dubbo-system", overidesA),
newTelemetry("default", overidesB),
},
sidecar,
[]string{"envoy"},
&TracingConfig{
ClientSpec: TracingSpec{
Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: "envoy"},
RandomSamplingPercentage: 80,
CustomTags: map[string]*tpb.Tracing_CustomTag{
"foo": {},
"baz": {},
},
UseRequestIDForTraceSampling: true,
},
ServerSpec: TracingSpec{
Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: "envoy"},
RandomSamplingPercentage: 80,
CustomTags: map[string]*tpb.Tracing_CustomTag{
"foo": {},
"baz": {},
},
UseRequestIDForTraceSampling: true,
},
},
},
{
"client-only override",
[]config.Config{newTelemetry("dubbo-system", envoy), newTelemetry("default", clientSideSampling)},
sidecar,
[]string{"envoy"},
&TracingConfig{
ClientSpec: TracingSpec{
Provider: &meshconfig.MeshConfig_ExtensionProvider{
Name: "stackdriver",
Provider: &meshconfig.MeshConfig_ExtensionProvider_Stackdriver{
Stackdriver: &meshconfig.MeshConfig_ExtensionProvider_StackdriverProvider{},
},
},
RandomSamplingPercentage: 99.9,
UseRequestIDForTraceSampling: true,
},
ServerSpec: TracingSpec{
Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: "envoy"},
UseRequestIDForTraceSampling: true,
},
},
},
{
"server-only override",
[]config.Config{newTelemetry("dubbo-system", envoy), newTelemetry("default", serverSideDisabled)},
sidecar,
[]string{"envoy"},
&TracingConfig{
ClientSpec: TracingSpec{
Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: "envoy"},
UseRequestIDForTraceSampling: true,
},
ServerSpec: TracingSpec{
Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: "envoy"},
Disabled: true,
UseRequestIDForTraceSampling: true,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
telemetry := createTestTelemetries(tt.cfgs, t)
telemetry.meshConfig.DefaultProviders.Tracing = tt.defaultProviders
got := telemetry.Tracing(tt.proxy)
if got != nil && got.ServerSpec.Provider != nil {
// We don't match on this, just the name for test simplicity
got.ServerSpec.Provider.Provider = nil
}
assert.Equal(t, got, tt.want)
})
}
}
func TestTelemetryFilters(t *testing.T) {
overrides := []*tpb.MetricsOverrides{{
Match: &tpb.MetricSelector{
MetricMatch: &tpb.MetricSelector_Metric{
Metric: tpb.MetricSelector_REQUEST_COUNT,
},
},
TagOverrides: map[string]*tpb.MetricsOverrides_TagOverride{
"remove": {
Operation: tpb.MetricsOverrides_TagOverride_REMOVE,
},
"add": {
Operation: tpb.MetricsOverrides_TagOverride_UPSERT,
Value: "bar",
},
},
}}
sidecar := &Proxy{ConfigNamespace: "default", Metadata: &NodeMetadata{Labels: map[string]string{"app": "test"}}}
emptyPrometheus := &tpb.Telemetry{
Metrics: []*tpb.Metrics{
{
Providers: []*tpb.ProviderRef{{Name: "prometheus"}},
},
},
}
overridesPrometheus := &tpb.Telemetry{
Metrics: []*tpb.Metrics{
{
Providers: []*tpb.ProviderRef{{Name: "prometheus"}},
Overrides: overrides,
},
},
}
emptyStackdriver := &tpb.Telemetry{
Metrics: []*tpb.Metrics{
{
Providers: []*tpb.ProviderRef{{Name: "stackdriver"}},
},
},
}
overridesStackdriver := &tpb.Telemetry{
Metrics: []*tpb.Metrics{
{
Providers: []*tpb.ProviderRef{{Name: "stackdriver"}},
Overrides: overrides,
},
},
AccessLogging: []*tpb.AccessLogging{
{
Providers: []*tpb.ProviderRef{{Name: "stackdriver"}},
Filter: &tpb.AccessLogging_Filter{
Expression: `response.code >= 500 && response.code <= 800`,
},
},
},
}
overridesEmptyProvider := &tpb.Telemetry{
Metrics: []*tpb.Metrics{
{
Overrides: overrides,
},
},
}
sdLogging := &tpb.Telemetry{
AccessLogging: []*tpb.AccessLogging{
{
Providers: []*tpb.ProviderRef{{Name: "stackdriver"}},
},
},
}
emptyLogging := &tpb.Telemetry{
AccessLogging: []*tpb.AccessLogging{
{},
},
}
disbaledAllMetrics := &tpb.Telemetry{
Metrics: []*tpb.Metrics{
{
Overrides: []*tpb.MetricsOverrides{{
Match: &tpb.MetricSelector{
MetricMatch: &tpb.MetricSelector_Metric{
Metric: tpb.MetricSelector_ALL_METRICS,
},
},
Disabled: &wrappers.BoolValue{
Value: true,
},
}},
Providers: []*tpb.ProviderRef{{Name: "prometheus"}},
},
},
}
tests := []struct {
name string
cfgs []config.Config
proxy *Proxy
class networking.ListenerClass
protocol networking.ListenerProtocol
defaultProviders *meshconfig.MeshConfig_DefaultProviders
want map[string]string
}{
{
"empty",
nil,
sidecar,
networking.ListenerClassSidecarOutbound,
networking.ListenerProtocolHTTP,
nil,
map[string]string{},
},
{
"disabled-prometheus",
[]config.Config{newTelemetry("dubbo-system", disbaledAllMetrics)},
sidecar,
networking.ListenerClassSidecarOutbound,
networking.ListenerProtocolHTTP,
nil,
map[string]string{},
},
{
"disabled-then-empty",
[]config.Config{
newTelemetry("dubbo-system", disbaledAllMetrics),
newTelemetry("default", emptyPrometheus),
},
sidecar,
networking.ListenerClassSidecarOutbound,
networking.ListenerProtocolHTTP,
nil,
map[string]string{},
},
{
"disabled-then-overrides",
[]config.Config{
newTelemetry("dubbo-system", disbaledAllMetrics),
newTelemetry("default", overridesPrometheus),
},
sidecar,
networking.ListenerClassSidecarOutbound,
networking.ListenerProtocolHTTP,
nil,
map[string]string{
"istio.stats": `{"metrics":[{"dimensions":{"add":"bar"},"name":"requests_total","tags_to_remove":["remove"]}]}`,
},
},
{
"default prometheus",
[]config.Config{newTelemetry("dubbo-system", emptyPrometheus)},
sidecar,
networking.ListenerClassSidecarOutbound,
networking.ListenerProtocolHTTP,
nil,
map[string]string{
"istio.stats": "{}",
},
},
{
"default provider prometheus",
[]config.Config{},
sidecar,
networking.ListenerClassSidecarOutbound,
networking.ListenerProtocolHTTP,
&meshconfig.MeshConfig_DefaultProviders{Metrics: []string{"prometheus"}},
map[string]string{
"istio.stats": "{}",
},
},
{
"prometheus overrides",
[]config.Config{newTelemetry("dubbo-system", overridesPrometheus)},
sidecar,
networking.ListenerClassSidecarOutbound,
networking.ListenerProtocolHTTP,
nil,
map[string]string{
"istio.stats": `{"metrics":[{"dimensions":{"add":"bar"},"name":"requests_total","tags_to_remove":["remove"]}]}`,
},
},
{
"prometheus overrides TCP",
[]config.Config{newTelemetry("dubbo-system", overridesPrometheus)},
sidecar,
networking.ListenerClassSidecarOutbound,
networking.ListenerProtocolTCP,
nil,
map[string]string{
"istio.stats": `{"metrics":[{"dimensions":{"add":"bar"},"name":"requests_total","tags_to_remove":["remove"]}]}`,
},
},
{
"empty stackdriver",
[]config.Config{newTelemetry("dubbo-system", emptyStackdriver)},
sidecar,
networking.ListenerClassSidecarOutbound,
networking.ListenerProtocolHTTP,
nil,
map[string]string{
"istio.stackdriver": `{"disable_server_access_logging":true,"metric_expiry_duration":"3600s"}`,
},
},
{
"overrides stackdriver",
[]config.Config{newTelemetry("dubbo-system", overridesStackdriver)},
sidecar,
networking.ListenerClassSidecarOutbound,
networking.ListenerProtocolHTTP,
nil,
map[string]string{
"istio.stackdriver": `{"access_logging_filter_expression":"response.code >= 500 && response.code <= 800",` +
`"metric_expiry_duration":"3600s","metrics_overrides":{"client/request_count":{"tag_overrides":{"add":"bar"}}}}`,
},
},
{
"namespace empty merge",
[]config.Config{
newTelemetry("dubbo-system", emptyPrometheus),
newTelemetry("default", emptyStackdriver),
},
sidecar,
networking.ListenerClassSidecarOutbound,
networking.ListenerProtocolHTTP,
nil,
map[string]string{
"istio.stackdriver": `{"disable_server_access_logging":true,"metric_expiry_duration":"3600s"}`,
},
},
{
"namespace overrides merge without provider",
[]config.Config{
newTelemetry("dubbo-system", emptyPrometheus),
newTelemetry("default", overridesEmptyProvider),
},
sidecar,
networking.ListenerClassSidecarOutbound,
networking.ListenerProtocolHTTP,
nil,
map[string]string{
"istio.stats": `{"metrics":[{"dimensions":{"add":"bar"},"name":"requests_total","tags_to_remove":["remove"]}]}`,
},
},
{
"namespace overrides merge with default provider",
[]config.Config{
newTelemetry("default", overridesEmptyProvider),
},
sidecar,
networking.ListenerClassSidecarOutbound,
networking.ListenerProtocolHTTP,
&meshconfig.MeshConfig_DefaultProviders{Metrics: []string{"prometheus"}},
map[string]string{
"istio.stats": `{"metrics":[{"dimensions":{"add":"bar"},"name":"requests_total","tags_to_remove":["remove"]}]}`,
},
},
{
"namespace overrides default provider",
[]config.Config{
newTelemetry("default", emptyStackdriver),
},
sidecar,
networking.ListenerClassSidecarOutbound,
networking.ListenerProtocolHTTP,
&meshconfig.MeshConfig_DefaultProviders{Metrics: []string{"prometheus"}},
map[string]string{
"istio.stackdriver": `{"disable_server_access_logging":true,"metric_expiry_duration":"3600s"}`,
},
},
{
"stackdriver logging",
[]config.Config{
newTelemetry("default", sdLogging),
},
sidecar,
networking.ListenerClassSidecarOutbound,
networking.ListenerProtocolHTTP,
nil,
map[string]string{
"istio.stackdriver": `{"access_logging":"ERRORS_ONLY","metric_expiry_duration":"3600s"}`,
},
},
{
"stackdriver logging default provider",
[]config.Config{
newTelemetry("default", emptyLogging),
},
sidecar,
networking.ListenerClassSidecarInbound,
networking.ListenerProtocolHTTP,
&meshconfig.MeshConfig_DefaultProviders{AccessLogging: []string{"stackdriver"}},
map[string]string{
"istio.stackdriver": `{"disable_host_header_fallback":true,"access_logging":"FULL","metric_expiry_duration":"3600s"}`,
},
},
{
"stackdriver default for all",
[]config.Config{},
sidecar,
networking.ListenerClassSidecarInbound,
networking.ListenerProtocolHTTP,
&meshconfig.MeshConfig_DefaultProviders{
Metrics: []string{"stackdriver"},
AccessLogging: []string{"stackdriver"},
},
map[string]string{
"istio.stackdriver": `{"disable_host_header_fallback":true,"access_logging":"FULL","metric_expiry_duration":"3600s"}`,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
telemetry := createTestTelemetries(tt.cfgs, t)
telemetry.meshConfig.DefaultProviders = tt.defaultProviders
got := telemetry.telemetryFilters(tt.proxy, tt.class, tt.protocol)
res := map[string]string{}
http, ok := got.([]*httppb.HttpFilter)
if ok {
for _, f := range http {
w := &httpwasm.Wasm{}
if err := f.GetTypedConfig().UnmarshalTo(w); err != nil {
t.Fatal(err)
}
cfg := &wrappers.StringValue{}
if err := w.GetConfig().GetConfiguration().UnmarshalTo(cfg); err != nil {
t.Fatal(err)
}
if _, dupe := res[f.GetName()]; dupe {
t.Fatalf("duplicate filter found: %v", f.GetName())
}
res[f.GetName()] = cfg.GetValue()
}
}
tcp, ok := got.([]*listener.Filter)
if ok {
for _, f := range tcp {
w := &wasmfilter.Wasm{}
if err := f.GetTypedConfig().UnmarshalTo(w); err != nil {
t.Fatal(err)
}
cfg := &wrappers.StringValue{}
if err := w.GetConfig().GetConfiguration().UnmarshalTo(cfg); err != nil {
t.Fatal(err)
}
if _, dupe := res[f.GetName()]; dupe {
t.Fatalf("duplicate filter found: %v", f.GetName())
}
res[f.GetName()] = cfg.GetValue()
}
}
if diff := cmp.Diff(res, tt.want); diff != "" {
t.Errorf("got diff: %v", diff)
}
})
}
}