istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/model/telemetry_test.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package model 16 17 import ( 18 "strings" 19 "testing" 20 "time" 21 22 core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" 23 listener "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" 24 fileaccesslog "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/file/v3" 25 httpwasm "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/wasm/v3" 26 hcm "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" 27 wasmfilter "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/wasm/v3" 28 "github.com/google/go-cmp/cmp" 29 "google.golang.org/protobuf/types/known/durationpb" 30 "google.golang.org/protobuf/types/known/structpb" 31 wrappers "google.golang.org/protobuf/types/known/wrapperspb" 32 "k8s.io/apimachinery/pkg/types" 33 34 "istio.io/api/envoy/extensions/stats" 35 meshconfig "istio.io/api/mesh/v1alpha1" 36 tpb "istio.io/api/telemetry/v1alpha1" 37 "istio.io/api/type/v1beta1" 38 "istio.io/istio/pilot/pkg/networking" 39 "istio.io/istio/pkg/config" 40 "istio.io/istio/pkg/config/mesh" 41 "istio.io/istio/pkg/config/schema/collection" 42 "istio.io/istio/pkg/config/schema/gvk" 43 "istio.io/istio/pkg/ptr" 44 "istio.io/istio/pkg/test/util/assert" 45 "istio.io/istio/pkg/util/protomarshal" 46 ) 47 48 var ( 49 jsonTextProvider = &meshconfig.MeshConfig_ExtensionProvider{ 50 Name: "envoy-json", 51 Provider: &meshconfig.MeshConfig_ExtensionProvider_EnvoyFileAccessLog{ 52 EnvoyFileAccessLog: &meshconfig.MeshConfig_ExtensionProvider_EnvoyFileAccessLogProvider{ 53 Path: "/dev/stdout", 54 LogFormat: &meshconfig.MeshConfig_ExtensionProvider_EnvoyFileAccessLogProvider_LogFormat{ 55 LogFormat: &meshconfig.MeshConfig_ExtensionProvider_EnvoyFileAccessLogProvider_LogFormat_Labels{ 56 Labels: &structpb.Struct{}, 57 }, 58 }, 59 }, 60 }, 61 } 62 63 textFormattersProvider = &meshconfig.MeshConfig_ExtensionProvider{ 64 Name: "envoy-text-formatters", 65 Provider: &meshconfig.MeshConfig_ExtensionProvider_EnvoyFileAccessLog{ 66 EnvoyFileAccessLog: &meshconfig.MeshConfig_ExtensionProvider_EnvoyFileAccessLogProvider{ 67 Path: "/dev/stdout", 68 LogFormat: &meshconfig.MeshConfig_ExtensionProvider_EnvoyFileAccessLogProvider_LogFormat{ 69 LogFormat: &meshconfig.MeshConfig_ExtensionProvider_EnvoyFileAccessLogProvider_LogFormat_Text{ 70 Text: "%REQ_WITHOUT_QUERY(key1:val1)% REQ_WITHOUT_QUERY(key2:val1)% %METADATA(UPSTREAM_HOST:istio)% %METADATA(CLUSTER:istio)%\n", 71 }, 72 }, 73 }, 74 }, 75 } 76 77 jsonFormattersProvider = &meshconfig.MeshConfig_ExtensionProvider{ 78 Name: "envoy-json-formatters", 79 Provider: &meshconfig.MeshConfig_ExtensionProvider_EnvoyFileAccessLog{ 80 EnvoyFileAccessLog: &meshconfig.MeshConfig_ExtensionProvider_EnvoyFileAccessLogProvider{ 81 Path: "/dev/stdout", 82 LogFormat: &meshconfig.MeshConfig_ExtensionProvider_EnvoyFileAccessLogProvider_LogFormat{ 83 LogFormat: &meshconfig.MeshConfig_ExtensionProvider_EnvoyFileAccessLogProvider_LogFormat_Labels{ 84 Labels: &structpb.Struct{ 85 Fields: map[string]*structpb.Value{ 86 "req1": {Kind: &structpb.Value_StringValue{StringValue: "%REQ_WITHOUT_QUERY(key1:val1)%"}}, 87 "req2": {Kind: &structpb.Value_StringValue{StringValue: "%REQ_WITHOUT_QUERY(key2:val1)%"}}, 88 "key1": {Kind: &structpb.Value_StringValue{StringValue: "%METADATA(CLUSTER:istio)%"}}, 89 "key2": {Kind: &structpb.Value_StringValue{StringValue: "%METADATA(UPSTREAM_HOST:istio)%"}}, 90 }, 91 }, 92 }, 93 }, 94 }, 95 }, 96 } 97 98 defaultJSONLabelsOut = &fileaccesslog.FileAccessLog{ 99 Path: "/dev/stdout", 100 AccessLogFormat: &fileaccesslog.FileAccessLog_LogFormat{ 101 LogFormat: &core.SubstitutionFormatString{ 102 Format: &core.SubstitutionFormatString_JsonFormat{ 103 JsonFormat: EnvoyJSONLogFormatIstio, 104 }, 105 JsonFormatOptions: &core.JsonFormatOptions{SortProperties: true}, 106 }, 107 }, 108 } 109 110 formattersJSONLabelsOut = &fileaccesslog.FileAccessLog{ 111 Path: "/dev/stdout", 112 AccessLogFormat: &fileaccesslog.FileAccessLog_LogFormat{ 113 LogFormat: &core.SubstitutionFormatString{ 114 Formatters: []*core.TypedExtensionConfig{ 115 reqWithoutQueryFormatter, 116 metadataFormatter, 117 }, 118 Format: &core.SubstitutionFormatString_JsonFormat{ 119 JsonFormat: &structpb.Struct{ 120 Fields: map[string]*structpb.Value{ 121 "req1": {Kind: &structpb.Value_StringValue{StringValue: "%REQ_WITHOUT_QUERY(key1:val1)%"}}, 122 "req2": {Kind: &structpb.Value_StringValue{StringValue: "%REQ_WITHOUT_QUERY(key2:val1)%"}}, 123 "key1": {Kind: &structpb.Value_StringValue{StringValue: "%METADATA(CLUSTER:istio)%"}}, 124 "key2": {Kind: &structpb.Value_StringValue{StringValue: "%METADATA(UPSTREAM_HOST:istio)%"}}, 125 }, 126 }, 127 }, 128 JsonFormatOptions: &core.JsonFormatOptions{SortProperties: true}, 129 }, 130 }, 131 } 132 133 formattersTextLabelsOut = &fileaccesslog.FileAccessLog{ 134 Path: "/dev/stdout", 135 AccessLogFormat: &fileaccesslog.FileAccessLog_LogFormat{ 136 LogFormat: &core.SubstitutionFormatString{ 137 Formatters: []*core.TypedExtensionConfig{ 138 reqWithoutQueryFormatter, 139 metadataFormatter, 140 }, 141 Format: &core.SubstitutionFormatString_TextFormatSource{ 142 TextFormatSource: &core.DataSource{ 143 Specifier: &core.DataSource_InlineString{ 144 InlineString: "%REQ_WITHOUT_QUERY(key1:val1)% REQ_WITHOUT_QUERY(key2:val1)% %METADATA(UPSTREAM_HOST:istio)% %METADATA(CLUSTER:istio)%\n", 145 }, 146 }, 147 }, 148 }, 149 }, 150 } 151 ) 152 153 func createTestTelemetries(configs []config.Config, t *testing.T) (*Telemetries, *PushContext) { 154 t.Helper() 155 156 store := &telemetryStore{} 157 for _, cfg := range configs { 158 store.add(cfg) 159 } 160 m := mesh.DefaultMeshConfig() 161 162 m.ExtensionProviders = append(m.ExtensionProviders, jsonTextProvider, textFormattersProvider, jsonFormattersProvider) 163 164 environment := &Environment{ 165 ConfigStore: store, 166 Watcher: mesh.NewFixedWatcher(m), 167 } 168 telemetries := getTelemetries(environment) 169 170 ctx := NewPushContext() 171 ctx.Mesh = m 172 return telemetries, ctx 173 } 174 175 func newTelemetry(ns string, spec config.Spec) config.Config { 176 return config.Config{ 177 Meta: config.Meta{ 178 GroupVersionKind: gvk.Telemetry, 179 Name: "default", 180 Namespace: ns, 181 }, 182 Spec: spec, 183 } 184 } 185 186 type telemetryStore struct { 187 ConfigStore 188 189 data []struct { 190 typ config.GroupVersionKind 191 ns string 192 cfg config.Config 193 } 194 } 195 196 func (ts *telemetryStore) add(cfg config.Config) { 197 ts.data = append(ts.data, struct { 198 typ config.GroupVersionKind 199 ns string 200 cfg config.Config 201 }{ 202 typ: cfg.GroupVersionKind, 203 ns: cfg.Namespace, 204 cfg: cfg, 205 }) 206 } 207 208 func (ts *telemetryStore) Schemas() collection.Schemas { 209 return collection.SchemasFor() 210 } 211 212 func (ts *telemetryStore) Get(_ config.GroupVersionKind, _, _ string) *config.Config { 213 return nil 214 } 215 216 func (ts *telemetryStore) List(typ config.GroupVersionKind, namespace string) []config.Config { 217 var configs []config.Config 218 for _, data := range ts.data { 219 if data.typ == typ { 220 if namespace != "" && data.ns == namespace { 221 continue 222 } 223 configs = append(configs, data.cfg) 224 } 225 } 226 return configs 227 } 228 229 func newTracingConfig(providerName string, disabled bool) *TracingConfig { 230 return &TracingConfig{ 231 ClientSpec: TracingSpec{ 232 Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: providerName}, 233 Disabled: disabled, 234 UseRequestIDForTraceSampling: true, 235 }, 236 ServerSpec: TracingSpec{ 237 Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: providerName}, 238 Disabled: disabled, 239 UseRequestIDForTraceSampling: true, 240 }, 241 } 242 } 243 244 const ( 245 reportingEnabled = false 246 reportingDisabled = !reportingEnabled 247 ) 248 249 func TestTracing(t *testing.T) { 250 sidecar := &Proxy{ 251 ConfigNamespace: "default", 252 Labels: map[string]string{"app": "test"}, 253 Metadata: &NodeMetadata{Labels: map[string]string{"app": "test"}}, 254 } 255 envoy := &tpb.Telemetry{ 256 Tracing: []*tpb.Tracing{ 257 { 258 Providers: []*tpb.ProviderRef{ 259 { 260 Name: "envoy", 261 }, 262 }, 263 }, 264 }, 265 } 266 stackdriver := &tpb.Telemetry{ 267 Tracing: []*tpb.Tracing{ 268 { 269 Providers: []*tpb.ProviderRef{ 270 { 271 Name: "stackdriver", 272 }, 273 }, 274 }, 275 }, 276 } 277 empty := &tpb.Telemetry{ 278 Tracing: []*tpb.Tracing{{}}, 279 } 280 disabled := &tpb.Telemetry{ 281 Tracing: []*tpb.Tracing{ 282 { 283 DisableSpanReporting: &wrappers.BoolValue{Value: true}, 284 }, 285 }, 286 } 287 overidesA := &tpb.Telemetry{ 288 Tracing: []*tpb.Tracing{ 289 { 290 RandomSamplingPercentage: &wrappers.DoubleValue{Value: 50.0}, 291 CustomTags: map[string]*tpb.Tracing_CustomTag{ 292 "foo": {}, 293 "bar": {}, 294 }, 295 UseRequestIdForTraceSampling: &wrappers.BoolValue{Value: false}, 296 }, 297 }, 298 } 299 overidesB := &tpb.Telemetry{ 300 Tracing: []*tpb.Tracing{ 301 { 302 RandomSamplingPercentage: &wrappers.DoubleValue{Value: 80.0}, 303 CustomTags: map[string]*tpb.Tracing_CustomTag{ 304 "foo": {}, 305 "baz": {}, 306 }, 307 UseRequestIdForTraceSampling: &wrappers.BoolValue{Value: true}, 308 }, 309 }, 310 } 311 overridesWithDefaultSampling := &tpb.Telemetry{ 312 Tracing: []*tpb.Tracing{ 313 { 314 CustomTags: map[string]*tpb.Tracing_CustomTag{ 315 "foo": {}, 316 "baz": {}, 317 }, 318 }, 319 }, 320 } 321 nonExistant := &tpb.Telemetry{ 322 Tracing: []*tpb.Tracing{ 323 { 324 Providers: []*tpb.ProviderRef{ 325 { 326 Name: "custom-provider", 327 }, 328 }, 329 }, 330 }, 331 } 332 clientSideSampling := &tpb.Telemetry{ 333 Tracing: []*tpb.Tracing{ 334 { 335 Match: &tpb.Tracing_TracingSelector{ 336 Mode: tpb.WorkloadMode_CLIENT, 337 }, 338 Providers: []*tpb.ProviderRef{ 339 { 340 Name: "stackdriver", 341 }, 342 }, 343 RandomSamplingPercentage: &wrappers.DoubleValue{Value: 99.9}, 344 }, 345 }, 346 } 347 serverSideDisabled := &tpb.Telemetry{ 348 Tracing: []*tpb.Tracing{ 349 { 350 Match: &tpb.Tracing_TracingSelector{ 351 Mode: tpb.WorkloadMode_SERVER, 352 }, 353 DisableSpanReporting: &wrappers.BoolValue{Value: true}, 354 }, 355 }, 356 } 357 358 tests := []struct { 359 name string 360 cfgs []config.Config 361 proxy *Proxy 362 defaultProviders []string 363 want *TracingConfig 364 }{ 365 { 366 "empty", 367 nil, 368 sidecar, 369 nil, 370 nil, 371 }, 372 { 373 "default provider only", 374 nil, 375 sidecar, 376 []string{"envoy"}, 377 newTracingConfig("envoy", reportingEnabled), 378 }, 379 { 380 "provider only", 381 []config.Config{newTelemetry("istio-system", envoy)}, 382 sidecar, 383 nil, 384 newTracingConfig("envoy", reportingEnabled), 385 }, 386 { 387 "override default", 388 []config.Config{newTelemetry("istio-system", envoy)}, 389 sidecar, 390 []string{"stackdriver"}, 391 newTracingConfig("envoy", reportingEnabled), 392 }, 393 { 394 "override namespace", 395 []config.Config{newTelemetry("istio-system", envoy), newTelemetry("default", stackdriver)}, 396 sidecar, 397 nil, 398 newTracingConfig("stackdriver", reportingEnabled), 399 }, 400 { 401 "empty config inherits", 402 []config.Config{newTelemetry("istio-system", envoy), newTelemetry("default", empty)}, 403 sidecar, 404 nil, 405 newTracingConfig("envoy", reportingEnabled), 406 }, 407 { 408 "disable config", 409 []config.Config{newTelemetry("istio-system", envoy), newTelemetry("default", disabled)}, 410 sidecar, 411 nil, 412 newTracingConfig("envoy", reportingDisabled), 413 }, 414 { 415 "disable default", 416 []config.Config{newTelemetry("default", disabled)}, 417 sidecar, 418 []string{"envoy"}, 419 newTracingConfig("envoy", reportingDisabled), 420 }, 421 { 422 "non existing", 423 []config.Config{newTelemetry("default", nonExistant)}, 424 sidecar, 425 []string{"envoy"}, 426 &TracingConfig{ 427 ClientSpec: TracingSpec{Disabled: true, UseRequestIDForTraceSampling: true}, 428 ServerSpec: TracingSpec{Disabled: true, UseRequestIDForTraceSampling: true}, 429 }, 430 }, 431 { 432 "overrides", 433 []config.Config{newTelemetry("istio-system", overidesA)}, 434 sidecar, 435 []string{"envoy"}, 436 &TracingConfig{ 437 ClientSpec: TracingSpec{ 438 Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: "envoy"}, 439 RandomSamplingPercentage: ptr.Of(50.0), 440 CustomTags: map[string]*tpb.Tracing_CustomTag{ 441 "foo": {}, 442 "bar": {}, 443 }, 444 UseRequestIDForTraceSampling: false, 445 }, ServerSpec: TracingSpec{ 446 Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: "envoy"}, 447 RandomSamplingPercentage: ptr.Of(50.0), 448 CustomTags: map[string]*tpb.Tracing_CustomTag{ 449 "foo": {}, 450 "bar": {}, 451 }, 452 UseRequestIDForTraceSampling: false, 453 }, 454 }, 455 }, 456 { 457 "overrides with default sampling", 458 []config.Config{newTelemetry("istio-system", overridesWithDefaultSampling)}, 459 sidecar, 460 []string{"envoy"}, 461 &TracingConfig{ 462 ClientSpec: TracingSpec{ 463 Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: "envoy"}, 464 CustomTags: map[string]*tpb.Tracing_CustomTag{ 465 "foo": {}, 466 "baz": {}, 467 }, 468 UseRequestIDForTraceSampling: true, 469 }, ServerSpec: TracingSpec{ 470 Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: "envoy"}, 471 CustomTags: map[string]*tpb.Tracing_CustomTag{ 472 "foo": {}, 473 "baz": {}, 474 }, 475 UseRequestIDForTraceSampling: true, 476 }, 477 }, 478 }, 479 { 480 "multi overrides", 481 []config.Config{ 482 newTelemetry("istio-system", overidesA), 483 newTelemetry("default", overidesB), 484 }, 485 sidecar, 486 []string{"envoy"}, 487 &TracingConfig{ 488 ClientSpec: TracingSpec{ 489 Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: "envoy"}, 490 RandomSamplingPercentage: ptr.Of(80.0), 491 CustomTags: map[string]*tpb.Tracing_CustomTag{ 492 "foo": {}, 493 "baz": {}, 494 }, 495 UseRequestIDForTraceSampling: true, 496 }, 497 ServerSpec: TracingSpec{ 498 Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: "envoy"}, 499 RandomSamplingPercentage: ptr.Of(80.0), 500 CustomTags: map[string]*tpb.Tracing_CustomTag{ 501 "foo": {}, 502 "baz": {}, 503 }, 504 UseRequestIDForTraceSampling: true, 505 }, 506 }, 507 }, 508 { 509 "client-only override", 510 []config.Config{newTelemetry("istio-system", envoy), newTelemetry("default", clientSideSampling)}, 511 sidecar, 512 []string{"envoy"}, 513 &TracingConfig{ 514 ClientSpec: TracingSpec{ 515 Provider: &meshconfig.MeshConfig_ExtensionProvider{ 516 Name: "stackdriver", 517 Provider: &meshconfig.MeshConfig_ExtensionProvider_Stackdriver{ 518 Stackdriver: &meshconfig.MeshConfig_ExtensionProvider_StackdriverProvider{}, 519 }, 520 }, 521 RandomSamplingPercentage: ptr.Of(99.9), 522 UseRequestIDForTraceSampling: true, 523 }, 524 ServerSpec: TracingSpec{ 525 Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: "envoy"}, 526 UseRequestIDForTraceSampling: true, 527 }, 528 }, 529 }, 530 { 531 "server-only override", 532 []config.Config{newTelemetry("istio-system", envoy), newTelemetry("default", serverSideDisabled)}, 533 sidecar, 534 []string{"envoy"}, 535 &TracingConfig{ 536 ClientSpec: TracingSpec{ 537 Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: "envoy"}, 538 UseRequestIDForTraceSampling: true, 539 }, 540 ServerSpec: TracingSpec{ 541 Provider: &meshconfig.MeshConfig_ExtensionProvider{Name: "envoy"}, 542 Disabled: true, 543 UseRequestIDForTraceSampling: true, 544 }, 545 }, 546 }, 547 } 548 for _, tt := range tests { 549 t.Run(tt.name, func(t *testing.T) { 550 telemetry, _ := createTestTelemetries(tt.cfgs, t) 551 telemetry.meshConfig.DefaultProviders.Tracing = tt.defaultProviders 552 got := telemetry.Tracing(tt.proxy, nil) 553 if got != nil && got.ServerSpec.Provider != nil { 554 // We don't match on this, just the name for test simplicity 555 got.ServerSpec.Provider.Provider = nil 556 } 557 assert.Equal(t, got, tt.want) 558 }) 559 } 560 } 561 562 func TestTelemetryFilters(t *testing.T) { 563 overrides := []*tpb.MetricsOverrides{{ 564 Match: &tpb.MetricSelector{ 565 MetricMatch: &tpb.MetricSelector_Metric{ 566 Metric: tpb.MetricSelector_REQUEST_COUNT, 567 }, 568 }, 569 TagOverrides: map[string]*tpb.MetricsOverrides_TagOverride{ 570 "remove": { 571 Operation: tpb.MetricsOverrides_TagOverride_REMOVE, 572 }, 573 "add": { 574 Operation: tpb.MetricsOverrides_TagOverride_UPSERT, 575 Value: "bar", 576 }, 577 }, 578 }} 579 sidecar := &Proxy{ 580 ConfigNamespace: "default", 581 Labels: map[string]string{"app": "test"}, 582 Metadata: &NodeMetadata{Labels: map[string]string{"app": "test"}}, 583 } 584 emptyPrometheus := &tpb.Telemetry{ 585 Metrics: []*tpb.Metrics{ 586 { 587 Providers: []*tpb.ProviderRef{{Name: "prometheus"}}, 588 }, 589 }, 590 } 591 overridesPrometheus := &tpb.Telemetry{ 592 Metrics: []*tpb.Metrics{ 593 { 594 Providers: []*tpb.ProviderRef{{Name: "prometheus"}}, 595 Overrides: overrides, 596 }, 597 }, 598 } 599 reportingInterval := &tpb.Telemetry{ 600 Metrics: []*tpb.Metrics{ 601 { 602 Providers: []*tpb.ProviderRef{{Name: "prometheus"}}, 603 ReportingInterval: durationpb.New(15 * time.Second), 604 }, 605 }, 606 } 607 overridesInterval := &tpb.Telemetry{ 608 Metrics: []*tpb.Metrics{ 609 { 610 Providers: []*tpb.ProviderRef{{Name: "prometheus"}}, 611 ReportingInterval: durationpb.New(10 * time.Second), 612 }, 613 }, 614 } 615 overridesEmptyProvider := &tpb.Telemetry{ 616 Metrics: []*tpb.Metrics{ 617 { 618 Overrides: overrides, 619 }, 620 }, 621 } 622 disabledAllMetrics := &tpb.Telemetry{ 623 Metrics: []*tpb.Metrics{ 624 { 625 Overrides: []*tpb.MetricsOverrides{{ 626 Match: &tpb.MetricSelector{ 627 MetricMatch: &tpb.MetricSelector_Metric{ 628 Metric: tpb.MetricSelector_ALL_METRICS, 629 }, 630 }, 631 Disabled: &wrappers.BoolValue{ 632 Value: true, 633 }, 634 }}, 635 636 Providers: []*tpb.ProviderRef{{Name: "prometheus"}}, 637 }, 638 }, 639 } 640 disabledAllMetricsImplicit := &tpb.Telemetry{ 641 Metrics: []*tpb.Metrics{ 642 { 643 Overrides: []*tpb.MetricsOverrides{{ 644 Disabled: &wrappers.BoolValue{ 645 Value: true, 646 }, 647 }}, 648 649 Providers: []*tpb.ProviderRef{{Name: "prometheus"}}, 650 }, 651 }, 652 } 653 cfg := `{"metrics":[{"dimensions":{"add":"bar"},"name":"requests_total","tags_to_remove":["remove"]}]}` 654 655 tests := []struct { 656 name string 657 cfgs []config.Config 658 proxy *Proxy 659 class networking.ListenerClass 660 protocol networking.ListenerProtocol 661 defaultProviders *meshconfig.MeshConfig_DefaultProviders 662 want map[string]string 663 }{ 664 { 665 "empty", 666 nil, 667 sidecar, 668 networking.ListenerClassSidecarOutbound, 669 networking.ListenerProtocolHTTP, 670 nil, 671 map[string]string{}, 672 }, 673 { 674 "disabled-prometheus", 675 []config.Config{newTelemetry("istio-system", disabledAllMetrics)}, 676 sidecar, 677 networking.ListenerClassSidecarOutbound, 678 networking.ListenerProtocolHTTP, 679 nil, 680 map[string]string{}, 681 }, 682 { 683 "disabled-prometheus-implicit", 684 []config.Config{newTelemetry("istio-system", disabledAllMetricsImplicit)}, 685 sidecar, 686 networking.ListenerClassSidecarOutbound, 687 networking.ListenerProtocolHTTP, 688 nil, 689 map[string]string{}, 690 }, 691 { 692 "disabled-then-empty", 693 []config.Config{ 694 newTelemetry("istio-system", disabledAllMetrics), 695 newTelemetry("default", emptyPrometheus), 696 }, 697 sidecar, 698 networking.ListenerClassSidecarOutbound, 699 networking.ListenerProtocolHTTP, 700 nil, 701 map[string]string{}, 702 }, 703 { 704 "disabled-then-overrides", 705 []config.Config{ 706 newTelemetry("istio-system", disabledAllMetrics), 707 newTelemetry("default", overridesPrometheus), 708 }, 709 sidecar, 710 networking.ListenerClassSidecarOutbound, 711 networking.ListenerProtocolHTTP, 712 nil, 713 map[string]string{ 714 "istio.stats": cfg, 715 }, 716 }, 717 { 718 "default prometheus", 719 []config.Config{newTelemetry("istio-system", emptyPrometheus)}, 720 sidecar, 721 networking.ListenerClassSidecarOutbound, 722 networking.ListenerProtocolHTTP, 723 nil, 724 map[string]string{ 725 "istio.stats": "{}", 726 }, 727 }, 728 { 729 "default provider prometheus", 730 []config.Config{}, 731 sidecar, 732 networking.ListenerClassSidecarOutbound, 733 networking.ListenerProtocolHTTP, 734 &meshconfig.MeshConfig_DefaultProviders{Metrics: []string{"prometheus"}}, 735 map[string]string{ 736 "istio.stats": "{}", 737 }, 738 }, 739 { 740 "prometheus overrides", 741 []config.Config{newTelemetry("istio-system", overridesPrometheus)}, 742 sidecar, 743 networking.ListenerClassSidecarOutbound, 744 networking.ListenerProtocolHTTP, 745 nil, 746 map[string]string{ 747 "istio.stats": cfg, 748 }, 749 }, 750 { 751 "prometheus overrides all metrics", 752 []config.Config{newTelemetry("istio-system", &tpb.Telemetry{ 753 Metrics: []*tpb.Metrics{ 754 { 755 Providers: []*tpb.ProviderRef{{Name: "prometheus"}}, 756 Overrides: []*tpb.MetricsOverrides{ 757 { 758 TagOverrides: map[string]*tpb.MetricsOverrides_TagOverride{ 759 "remove": { 760 Operation: tpb.MetricsOverrides_TagOverride_REMOVE, 761 }, 762 "add": { 763 Operation: tpb.MetricsOverrides_TagOverride_UPSERT, 764 Value: "bar", 765 }, 766 }, 767 }, 768 }, 769 }, 770 }, 771 })}, 772 sidecar, 773 networking.ListenerClassSidecarOutbound, 774 networking.ListenerProtocolHTTP, 775 nil, 776 // TODO: the following should be simple to `{"metrics":[{"dimensions":{"add":"bar"},"tags_to_remove":["remove"]}]}` 777 map[string]string{ 778 "istio.stats": `{"metrics":[` + 779 `{"dimensions":{"add":"bar"},"name":"request_messages_total","tags_to_remove":["remove"]},` + 780 `{"dimensions":{"add":"bar"},"name":"response_messages_total","tags_to_remove":["remove"]},` + 781 `{"dimensions":{"add":"bar"},"name":"requests_total","tags_to_remove":["remove"]},` + 782 `{"dimensions":{"add":"bar"},"name":"request_duration_milliseconds","tags_to_remove":["remove"]},` + 783 `{"dimensions":{"add":"bar"},"name":"request_bytes","tags_to_remove":["remove"]},` + 784 `{"dimensions":{"add":"bar"},"name":"response_bytes","tags_to_remove":["remove"]},` + 785 `{"dimensions":{"add":"bar"},"name":"tcp_connections_closed_total","tags_to_remove":["remove"]},` + 786 `{"dimensions":{"add":"bar"},"name":"tcp_connections_opened_total","tags_to_remove":["remove"]},` + 787 `{"dimensions":{"add":"bar"},"name":"tcp_received_bytes_total","tags_to_remove":["remove"]},` + 788 `{"dimensions":{"add":"bar"},"name":"tcp_sent_bytes_total","tags_to_remove":["remove"]}` + 789 `]}`, 790 }, 791 }, 792 { 793 "prometheus overrides all metrics first", 794 []config.Config{newTelemetry("istio-system", &tpb.Telemetry{ 795 Metrics: []*tpb.Metrics{ 796 { 797 Providers: []*tpb.ProviderRef{{Name: "prometheus"}}, 798 Overrides: []*tpb.MetricsOverrides{ 799 { 800 TagOverrides: map[string]*tpb.MetricsOverrides_TagOverride{ 801 "remove": { 802 Operation: tpb.MetricsOverrides_TagOverride_REMOVE, 803 }, 804 "add": { 805 Operation: tpb.MetricsOverrides_TagOverride_UPSERT, 806 Value: "bar", 807 }, 808 }, 809 }, 810 { 811 Match: &tpb.MetricSelector{ 812 MetricMatch: &tpb.MetricSelector_Metric{ 813 Metric: tpb.MetricSelector_REQUEST_COUNT, 814 }, 815 }, 816 TagOverrides: map[string]*tpb.MetricsOverrides_TagOverride{ 817 "add": { 818 Value: "add-override", 819 }, 820 }, 821 }, 822 }, 823 }, 824 }, 825 })}, 826 sidecar, 827 networking.ListenerClassSidecarOutbound, 828 networking.ListenerProtocolHTTP, 829 nil, 830 map[string]string{ 831 "istio.stats": `{"metrics":[` + 832 `{"dimensions":{"add":"bar"},"name":"request_messages_total","tags_to_remove":["remove"]},` + 833 `{"dimensions":{"add":"bar"},"name":"response_messages_total","tags_to_remove":["remove"]},` + 834 `{"dimensions":{"add":"add-override"},"name":"requests_total","tags_to_remove":["remove"]},` + 835 `{"dimensions":{"add":"bar"},"name":"request_duration_milliseconds","tags_to_remove":["remove"]},` + 836 `{"dimensions":{"add":"bar"},"name":"request_bytes","tags_to_remove":["remove"]},` + 837 `{"dimensions":{"add":"bar"},"name":"response_bytes","tags_to_remove":["remove"]},` + 838 `{"dimensions":{"add":"bar"},"name":"tcp_connections_closed_total","tags_to_remove":["remove"]},` + 839 `{"dimensions":{"add":"bar"},"name":"tcp_connections_opened_total","tags_to_remove":["remove"]},` + 840 `{"dimensions":{"add":"bar"},"name":"tcp_received_bytes_total","tags_to_remove":["remove"]},` + 841 `{"dimensions":{"add":"bar"},"name":"tcp_sent_bytes_total","tags_to_remove":["remove"]}` + 842 `]}`, 843 }, 844 }, 845 { 846 "prometheus overrides all metrics secondary", 847 []config.Config{newTelemetry("istio-system", &tpb.Telemetry{ 848 Metrics: []*tpb.Metrics{ 849 { 850 Providers: []*tpb.ProviderRef{{Name: "prometheus"}}, 851 Overrides: []*tpb.MetricsOverrides{ 852 { 853 Match: &tpb.MetricSelector{ 854 MetricMatch: &tpb.MetricSelector_Metric{ 855 Metric: tpb.MetricSelector_REQUEST_COUNT, 856 }, 857 }, 858 TagOverrides: map[string]*tpb.MetricsOverrides_TagOverride{ 859 "add": { 860 Value: "add-override", 861 }, 862 }, 863 }, 864 { 865 TagOverrides: map[string]*tpb.MetricsOverrides_TagOverride{ 866 "remove": { 867 Operation: tpb.MetricsOverrides_TagOverride_REMOVE, 868 }, 869 "add": { 870 Operation: tpb.MetricsOverrides_TagOverride_UPSERT, 871 Value: "bar", 872 }, 873 }, 874 }, 875 }, 876 }, 877 }, 878 })}, 879 sidecar, 880 networking.ListenerClassSidecarOutbound, 881 networking.ListenerProtocolHTTP, 882 nil, 883 map[string]string{ 884 "istio.stats": `{"metrics":[` + 885 `{"dimensions":{"add":"bar"},"name":"request_messages_total","tags_to_remove":["remove"]},` + 886 `{"dimensions":{"add":"bar"},"name":"response_messages_total","tags_to_remove":["remove"]},` + 887 `{"dimensions":{"add":"bar"},"name":"requests_total","tags_to_remove":["remove"]},` + 888 `{"dimensions":{"add":"bar"},"name":"request_duration_milliseconds","tags_to_remove":["remove"]},` + 889 `{"dimensions":{"add":"bar"},"name":"request_bytes","tags_to_remove":["remove"]},` + 890 `{"dimensions":{"add":"bar"},"name":"response_bytes","tags_to_remove":["remove"]},` + 891 `{"dimensions":{"add":"bar"},"name":"tcp_connections_closed_total","tags_to_remove":["remove"]},` + 892 `{"dimensions":{"add":"bar"},"name":"tcp_connections_opened_total","tags_to_remove":["remove"]},` + 893 `{"dimensions":{"add":"bar"},"name":"tcp_received_bytes_total","tags_to_remove":["remove"]},` + 894 `{"dimensions":{"add":"bar"},"name":"tcp_sent_bytes_total","tags_to_remove":["remove"]}` + 895 `]}`, 896 }, 897 }, 898 { 899 "prometheus overrides TCP", 900 []config.Config{newTelemetry("istio-system", overridesPrometheus)}, 901 sidecar, 902 networking.ListenerClassSidecarOutbound, 903 networking.ListenerProtocolTCP, 904 nil, 905 map[string]string{ 906 "istio.stats": cfg, 907 }, 908 }, 909 { 910 "reporting-interval", 911 []config.Config{newTelemetry("istio-system", reportingInterval)}, 912 sidecar, 913 networking.ListenerClassSidecarOutbound, 914 networking.ListenerProtocolHTTP, 915 nil, 916 map[string]string{ 917 "istio.stats": `{"tcp_reporting_duration":"15s"}`, 918 }, 919 }, 920 { 921 "override-interval", 922 []config.Config{ 923 newTelemetry("istio-system", reportingInterval), 924 newTelemetry("default", overridesInterval), 925 }, 926 sidecar, 927 networking.ListenerClassSidecarOutbound, 928 networking.ListenerProtocolHTTP, 929 nil, 930 map[string]string{ 931 "istio.stats": `{"tcp_reporting_duration":"10s"}`, 932 }, 933 }, 934 { 935 "namespace overrides merge without provider", 936 []config.Config{ 937 newTelemetry("istio-system", emptyPrometheus), 938 newTelemetry("default", overridesEmptyProvider), 939 }, 940 sidecar, 941 networking.ListenerClassSidecarOutbound, 942 networking.ListenerProtocolHTTP, 943 nil, 944 map[string]string{ 945 "istio.stats": cfg, 946 }, 947 }, 948 { 949 "namespace overrides merge with default provider", 950 []config.Config{ 951 newTelemetry("default", overridesEmptyProvider), 952 }, 953 sidecar, 954 networking.ListenerClassSidecarOutbound, 955 networking.ListenerProtocolHTTP, 956 &meshconfig.MeshConfig_DefaultProviders{Metrics: []string{"prometheus"}}, 957 map[string]string{ 958 "istio.stats": cfg, 959 }, 960 }, 961 } 962 for _, tt := range tests { 963 t.Run(tt.name, func(t *testing.T) { 964 telemetry, _ := createTestTelemetries(tt.cfgs, t) 965 telemetry.meshConfig.DefaultProviders = tt.defaultProviders 966 got := telemetry.telemetryFilters(tt.proxy, tt.class, tt.protocol, nil) 967 res := map[string]string{} 968 http, ok := got.([]*hcm.HttpFilter) 969 if ok { 970 for _, f := range http { 971 if strings.HasSuffix(f.GetTypedConfig().GetTypeUrl(), "/stats.PluginConfig") { 972 w := &stats.PluginConfig{} 973 if err := f.GetTypedConfig().UnmarshalTo(w); err != nil { 974 t.Fatal(err) 975 } 976 cfgJSON, _ := protomarshal.MarshalProtoNames(w) 977 res[f.GetName()] = string(cfgJSON) 978 } else { 979 w := &httpwasm.Wasm{} 980 981 if err := f.GetTypedConfig().UnmarshalTo(w); err != nil { 982 t.Fatal(err) 983 } 984 cfg := &wrappers.StringValue{} 985 if err := w.GetConfig().GetConfiguration().UnmarshalTo(cfg); err != nil { 986 t.Fatal(err) 987 } 988 if _, dupe := res[f.GetName()]; dupe { 989 t.Fatalf("duplicate filter found: %v", f.GetName()) 990 } 991 res[f.GetName()] = cfg.GetValue() 992 } 993 } 994 } 995 tcp, ok := got.([]*listener.Filter) 996 if ok { 997 for _, f := range tcp { 998 if strings.HasSuffix(f.GetTypedConfig().GetTypeUrl(), "/stats.PluginConfig") { 999 w := &stats.PluginConfig{} 1000 if err := f.GetTypedConfig().UnmarshalTo(w); err != nil { 1001 t.Fatal(err) 1002 } 1003 cfgJSON, _ := protomarshal.MarshalProtoNames(w) 1004 res[f.GetName()] = string(cfgJSON) 1005 } else { 1006 w := &wasmfilter.Wasm{} 1007 1008 if err := f.GetTypedConfig().UnmarshalTo(w); err != nil { 1009 t.Fatal(err) 1010 } 1011 cfg := &wrappers.StringValue{} 1012 if err := w.GetConfig().GetConfiguration().UnmarshalTo(cfg); err != nil { 1013 t.Fatal(err) 1014 } 1015 if _, dupe := res[f.GetName()]; dupe { 1016 t.Fatalf("duplicate filter found: %v", f.GetName()) 1017 } 1018 res[f.GetName()] = cfg.GetValue() 1019 } 1020 } 1021 } 1022 if diff := cmp.Diff(res, tt.want); diff != "" { 1023 t.Errorf("got diff: %v", diff) 1024 } 1025 }) 1026 } 1027 } 1028 1029 func TestGetInterval(t *testing.T) { 1030 cases := []struct { 1031 name string 1032 input, defaultVal time.Duration 1033 expected *durationpb.Duration 1034 }{ 1035 { 1036 name: "return nil", 1037 input: 0, 1038 defaultVal: 0, 1039 expected: nil, 1040 }, 1041 { 1042 name: "return input", 1043 input: 1 * time.Second, 1044 defaultVal: 0, 1045 expected: durationpb.New(1 * time.Second), 1046 }, 1047 } 1048 1049 for _, tc := range cases { 1050 t.Run(tc.name, func(t *testing.T) { 1051 actual := getInterval(tc.input, tc.defaultVal) 1052 assert.Equal(t, tc.expected, actual) 1053 }) 1054 } 1055 } 1056 1057 func Test_appendApplicableTelemetries(t *testing.T) { 1058 namespacedName := types.NamespacedName{ 1059 Name: "my-telemetry", 1060 Namespace: "my-namespace", 1061 } 1062 emptyStackDriverTracing := &tpb.Tracing{ 1063 Match: &tpb.Tracing_TracingSelector{ 1064 Mode: tpb.WorkloadMode_CLIENT, 1065 }, 1066 Providers: []*tpb.ProviderRef{ 1067 { 1068 Name: "stackdriver", 1069 }, 1070 }, 1071 } 1072 prometheusMetrics := &tpb.Metrics{ 1073 Providers: []*tpb.ProviderRef{{Name: "prometheus"}}, 1074 ReportingInterval: durationpb.New(15 * time.Second), 1075 } 1076 emptyEnvoyLogging := &tpb.AccessLogging{ 1077 Providers: []*tpb.ProviderRef{ 1078 { 1079 Name: "envoy", 1080 }, 1081 }, 1082 } 1083 testComputeAccessLogging := &computedAccessLogging{ 1084 telemetryKey: telemetryKey{ 1085 Workload: namespacedName, 1086 }, 1087 Logging: []*tpb.AccessLogging{ 1088 emptyEnvoyLogging, 1089 }, 1090 } 1091 validTelemetryConfigurationWithTargetRef := &tpb.Telemetry{ 1092 TargetRef: &v1beta1.PolicyTargetReference{ 1093 Group: gvk.KubernetesGateway.Group, 1094 Kind: gvk.KubernetesGateway.Kind, 1095 Name: "my-gateway", 1096 }, 1097 Tracing: []*tpb.Tracing{ 1098 emptyStackDriverTracing, 1099 }, 1100 Metrics: []*tpb.Metrics{ 1101 prometheusMetrics, 1102 }, 1103 AccessLogging: []*tpb.AccessLogging{ 1104 emptyEnvoyLogging, 1105 }, 1106 } 1107 validTelemetryConfiguration := &tpb.Telemetry{ 1108 Tracing: []*tpb.Tracing{ 1109 emptyStackDriverTracing, 1110 }, 1111 Metrics: []*tpb.Metrics{ 1112 prometheusMetrics, 1113 }, 1114 AccessLogging: []*tpb.AccessLogging{ 1115 emptyEnvoyLogging, 1116 }, 1117 } 1118 type args struct { 1119 ct *computedTelemetries 1120 tel Telemetry 1121 spec *tpb.Telemetry 1122 } 1123 1124 tests := []struct { 1125 name string 1126 args args 1127 want *computedTelemetries 1128 }{ 1129 { 1130 name: "empty telemetry configuration", 1131 args: args{ 1132 ct: &computedTelemetries{}, 1133 tel: Telemetry{}, 1134 spec: &tpb.Telemetry{}, 1135 }, 1136 want: &computedTelemetries{}, 1137 }, 1138 { 1139 name: "targetRef is defined, telemetry configurations are added to empty computed telemetries", 1140 args: args{ 1141 ct: &computedTelemetries{}, 1142 tel: Telemetry{ 1143 Name: "my-telemetry", 1144 Namespace: "my-namespace", 1145 Spec: validTelemetryConfigurationWithTargetRef, 1146 }, 1147 spec: validTelemetryConfigurationWithTargetRef, 1148 }, 1149 want: &computedTelemetries{ 1150 telemetryKey: telemetryKey{Workload: namespacedName}, 1151 Metrics: []*tpb.Metrics{prometheusMetrics}, 1152 Logging: []*computedAccessLogging{testComputeAccessLogging}, 1153 Tracing: []*tpb.Tracing{emptyStackDriverTracing}, 1154 }, 1155 }, 1156 { 1157 name: "targetRef is not defined, telemetry configurations are added to empty computed telemetries", 1158 args: args{ 1159 ct: &computedTelemetries{}, 1160 tel: Telemetry{ 1161 Name: "my-telemetry", 1162 Namespace: "my-namespace", 1163 Spec: validTelemetryConfiguration, 1164 }, 1165 spec: validTelemetryConfiguration, 1166 }, 1167 want: &computedTelemetries{ 1168 telemetryKey: telemetryKey{ 1169 Workload: namespacedName, 1170 }, 1171 Metrics: []*tpb.Metrics{prometheusMetrics}, 1172 Logging: []*computedAccessLogging{testComputeAccessLogging}, 1173 Tracing: []*tpb.Tracing{emptyStackDriverTracing}, 1174 }, 1175 }, 1176 } 1177 for _, tt := range tests { 1178 t.Run(tt.name, func(t *testing.T) { 1179 if got := appendApplicableTelemetries(tt.args.ct, tt.args.tel, tt.args.spec); !cmp.Equal(got, tt.want) { 1180 t.Errorf("appendApplicableTelemetries() = want %v", cmp.Diff(got, tt.want)) 1181 } 1182 }) 1183 } 1184 } 1185 1186 func Test_computedTelemetries_Equal(t *testing.T) { 1187 type args struct { 1188 other *computedTelemetries 1189 } 1190 1191 tests := []struct { 1192 name string 1193 computedTelemetries *computedTelemetries 1194 args args 1195 want bool 1196 }{ 1197 { 1198 name: "nil", 1199 computedTelemetries: nil, 1200 args: args{ 1201 other: nil, 1202 }, 1203 want: true, 1204 }, 1205 { 1206 name: "empty", 1207 computedTelemetries: &computedTelemetries{}, 1208 args: args{ 1209 other: &computedTelemetries{}, 1210 }, 1211 want: true, 1212 }, 1213 { 1214 name: "computedTelemetries is nil and other computedTelemetries is not", 1215 computedTelemetries: nil, 1216 args: args{ 1217 other: &computedTelemetries{ 1218 Metrics: []*tpb.Metrics{ 1219 { 1220 Providers: []*tpb.ProviderRef{{Name: "prometheus"}}, 1221 }, 1222 }, 1223 }, 1224 }, 1225 want: false, 1226 }, 1227 { 1228 name: "other computedTelemetries is nil and computedTelemetries is not", 1229 computedTelemetries: &computedTelemetries{ 1230 Metrics: []*tpb.Metrics{ 1231 { 1232 Providers: []*tpb.ProviderRef{{Name: "prometheus"}}, 1233 }, 1234 }, 1235 }, 1236 args: args{ 1237 other: nil, 1238 }, 1239 want: false, 1240 }, 1241 { 1242 name: "different length in metrics slice comparison", 1243 computedTelemetries: &computedTelemetries{ 1244 Metrics: []*tpb.Metrics{ 1245 { 1246 Providers: []*tpb.ProviderRef{{Name: "prometheus"}}, 1247 }, 1248 }, 1249 }, 1250 args: args{ 1251 other: &computedTelemetries{ 1252 Metrics: []*tpb.Metrics{ 1253 { 1254 Providers: []*tpb.ProviderRef{{Name: "prometheus"}}, 1255 }, 1256 { 1257 Providers: []*tpb.ProviderRef{{Name: "stackdriver"}}, 1258 }, 1259 }, 1260 }, 1261 }, 1262 want: false, 1263 }, 1264 { 1265 name: "different length in tracing slice comparison", 1266 computedTelemetries: &computedTelemetries{ 1267 Tracing: []*tpb.Tracing{ 1268 { 1269 Providers: []*tpb.ProviderRef{{Name: "stackdriver"}}, 1270 }, 1271 }, 1272 }, 1273 args: args{ 1274 other: &computedTelemetries{ 1275 Tracing: []*tpb.Tracing{ 1276 { 1277 Providers: []*tpb.ProviderRef{{Name: "stackdriver"}}, 1278 }, 1279 { 1280 Providers: []*tpb.ProviderRef{{Name: "prometheus"}}, 1281 }, 1282 }, 1283 }, 1284 }, 1285 want: false, 1286 }, 1287 { 1288 name: "different length in logging slice comparison", 1289 computedTelemetries: &computedTelemetries{ 1290 Logging: []*computedAccessLogging{ 1291 { 1292 Logging: []*tpb.AccessLogging{ 1293 { 1294 Providers: []*tpb.ProviderRef{{Name: "stackdriver"}}, 1295 }, 1296 }, 1297 }, 1298 }, 1299 }, 1300 args: args{ 1301 other: &computedTelemetries{ 1302 Logging: []*computedAccessLogging{ 1303 { 1304 Logging: []*tpb.AccessLogging{ 1305 { 1306 Providers: []*tpb.ProviderRef{{Name: "stackdriver"}}, 1307 }, 1308 }, 1309 }, 1310 { 1311 Logging: []*tpb.AccessLogging{ 1312 { 1313 Providers: []*tpb.ProviderRef{{Name: "prometheus"}}, 1314 }, 1315 }, 1316 }, 1317 }, 1318 }, 1319 }, 1320 want: false, 1321 }, 1322 { 1323 name: "different metrics", 1324 computedTelemetries: &computedTelemetries{ 1325 Metrics: []*tpb.Metrics{ 1326 { 1327 Providers: []*tpb.ProviderRef{{Name: "prometheus"}}, 1328 }, 1329 }, 1330 }, 1331 args: args{ 1332 other: &computedTelemetries{ 1333 Metrics: []*tpb.Metrics{ 1334 { 1335 Providers: []*tpb.ProviderRef{{Name: "stackdriver"}}, 1336 }, 1337 }, 1338 }, 1339 }, 1340 want: false, 1341 }, 1342 { 1343 name: "different metrics reporting interval", 1344 computedTelemetries: &computedTelemetries{ 1345 Metrics: []*tpb.Metrics{ 1346 { 1347 Providers: []*tpb.ProviderRef{{Name: "prometheus"}}, 1348 ReportingInterval: &durationpb.Duration{ 1349 Seconds: 10, 1350 }, 1351 }, 1352 }, 1353 }, 1354 args: args{ 1355 other: &computedTelemetries{ 1356 Metrics: []*tpb.Metrics{ 1357 { 1358 Providers: []*tpb.ProviderRef{{Name: "prometheus"}}, 1359 ReportingInterval: &durationpb.Duration{ 1360 Seconds: 15, 1361 }, 1362 }, 1363 }, 1364 }, 1365 }, 1366 want: false, 1367 }, 1368 { 1369 name: "different tracing providers", 1370 computedTelemetries: &computedTelemetries{ 1371 Tracing: []*tpb.Tracing{ 1372 { 1373 Providers: []*tpb.ProviderRef{{Name: "stackdriver"}}, 1374 }, 1375 }, 1376 }, 1377 args: args{ 1378 other: &computedTelemetries{ 1379 Tracing: []*tpb.Tracing{ 1380 { 1381 Providers: []*tpb.ProviderRef{{Name: "prometheus"}}, 1382 }, 1383 }, 1384 }, 1385 }, 1386 want: false, 1387 }, 1388 { 1389 name: "different tracing match", 1390 computedTelemetries: &computedTelemetries{ 1391 Tracing: []*tpb.Tracing{ 1392 { 1393 Providers: []*tpb.ProviderRef{{Name: "stackdriver"}}, 1394 Match: &tpb.Tracing_TracingSelector{ 1395 Mode: tpb.WorkloadMode_CLIENT, 1396 }, 1397 }, 1398 }, 1399 }, 1400 args: args{ 1401 other: &computedTelemetries{ 1402 Tracing: []*tpb.Tracing{ 1403 { 1404 Providers: []*tpb.ProviderRef{{Name: "stackdriver"}}, 1405 Match: &tpb.Tracing_TracingSelector{ 1406 Mode: tpb.WorkloadMode_SERVER, 1407 }, 1408 }, 1409 }, 1410 }, 1411 }, 1412 want: false, 1413 }, 1414 { 1415 name: "different logging providers", 1416 computedTelemetries: &computedTelemetries{ 1417 Logging: []*computedAccessLogging{ 1418 { 1419 Logging: []*tpb.AccessLogging{ 1420 { 1421 Providers: []*tpb.ProviderRef{{Name: "stackdriver"}}, 1422 }, 1423 }, 1424 }, 1425 }, 1426 }, 1427 args: args{ 1428 other: &computedTelemetries{ 1429 Logging: []*computedAccessLogging{ 1430 { 1431 Logging: []*tpb.AccessLogging{ 1432 { 1433 Providers: []*tpb.ProviderRef{{Name: "prometheus"}}, 1434 }, 1435 }, 1436 }, 1437 }, 1438 }, 1439 }, 1440 want: false, 1441 }, 1442 { 1443 name: "different logging telemetryKey", 1444 computedTelemetries: &computedTelemetries{ 1445 Logging: []*computedAccessLogging{ 1446 { 1447 telemetryKey: telemetryKey{ 1448 Workload: types.NamespacedName{ 1449 Name: "my-telemetry", 1450 Namespace: "my-namespace", 1451 }, 1452 }, 1453 }, 1454 }, 1455 }, 1456 args: args{ 1457 other: &computedTelemetries{ 1458 Logging: []*computedAccessLogging{ 1459 { 1460 telemetryKey: telemetryKey{ 1461 Workload: types.NamespacedName{ 1462 Name: "my-telemetry", 1463 Namespace: "my-namespace-2", 1464 }, 1465 }, 1466 }, 1467 }, 1468 }, 1469 }, 1470 want: false, 1471 }, 1472 } 1473 for _, tt := range tests { 1474 t.Run(tt.name, func(t *testing.T) { 1475 if got := tt.computedTelemetries.Equal(tt.args.other); got != tt.want { 1476 t.Errorf("computedTelemetries.Equal() = %v, want %v", got, tt.want) 1477 } 1478 }) 1479 } 1480 }