1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-05 15:37:19 +00:00

Fix: metrics exposure inconsistencies and unwanted side-effects (#10016)

* Change: metrics exposure improvement

Signed-off-by: Tamas Eger <tamas.eger@instructure.com>

* Fix: addressing linter errors

Signed-off-by: Tamas Eger <tamas.eger@instructure.com>

* Fix: unit test assert failure

Signed-off-by: Tamas Eger <tamas.eger@instructure.com>

---------

Signed-off-by: Tamas Eger <tamas.eger@instructure.com>
Co-authored-by: Tamas Eger <tamas.eger@instructure.com>
This commit is contained in:
NeuroticalT 2024-04-22 09:33:04 +02:00 committed by GitHub
parent aea0b9934d
commit 370abe257e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 80 additions and 25 deletions

View file

@ -1,6 +1,7 @@
package config
import (
"maps"
"slices"
"sync"
"time"
@ -77,30 +78,44 @@ func (mcd *metricsConfig) GetBucketBoundaries() []float64 {
func (mcd *metricsConfig) BuildMeterProviderViews() []sdkmetric.View {
mcd.mux.RLock()
defer mcd.mux.RUnlock()
var views []sdkmetric.View
for key, value := range mcd.metricsExposure {
if *value.Enabled {
views = append(views, sdkmetric.NewView(
sdkmetric.Instrument{Name: key},
sdkmetric.Stream{
AttributeFilter: func(kv attribute.KeyValue) bool {
return !slices.Contains(value.DisabledLabelDimensions, string(kv.Key))
},
Aggregation: sdkmetric.AggregationExplicitBucketHistogram{
Boundaries: value.BucketBoundaries,
NoMinMax: false,
},
},
))
} else if !*value.Enabled {
views = append(views, sdkmetric.NewView(
sdkmetric.Instrument{Name: key},
sdkmetric.Stream{
Aggregation: sdkmetric.AggregationDrop{},
},
))
}
views := []sdkmetric.View{}
if len(mcd.metricsExposure) > 0 {
metricsExposure := maps.Clone(mcd.metricsExposure)
views = append(views, func(i sdkmetric.Instrument) (sdkmetric.Stream, bool) {
s := sdkmetric.Stream{Name: i.Name, Description: i.Description, Unit: i.Unit}
config, exists := metricsExposure[i.Name]
if !exists {
return s, false
}
if config.Enabled != nil && !*config.Enabled {
s.Aggregation = sdkmetric.AggregationDrop{}
return s, true
}
if len(config.DisabledLabelDimensions) > 0 {
s.AttributeFilter = func(kv attribute.KeyValue) bool {
return !slices.Contains(config.DisabledLabelDimensions, string(kv.Key))
}
}
if len(config.BucketBoundaries) > 0 {
aggregation := sdkmetric.DefaultAggregationSelector(i.Kind)
switch a := aggregation.(type) {
case sdkmetric.AggregationExplicitBucketHistogram:
a.Boundaries = config.BucketBoundaries
a.NoMinMax = false
s.Aggregation = a
}
}
return s, true
})
}
return views
}

View file

@ -105,13 +105,39 @@ func Test_metricsConfig_BuildMeterProviderViews(t *testing.T) {
expectedSize: 0,
},
{
name: "Case 2: metrics enabled",
name: "Case 2: there is no matching entry on the exposure config",
metricsExposure: map[string]metricExposureConfig{
"metric1": {Enabled: boolPtr(true), DisabledLabelDimensions: []string{"dim1"}, BucketBoundaries: []float64{0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 15, 20, 25, 30}},
},
expectedSize: 1,
validateFunc: func(views []sdkmetric.View) bool {
stream, _ := views[0](sdkmetric.Instrument{Name: "metric2"})
assert := stream.AttributeFilter == nil
assert = assert && stream.Aggregation == nil
return assert
},
},
{
name: "Case 3: metrics enabled, no transformation configured",
metricsExposure: map[string]metricExposureConfig{
"metric1": {Enabled: boolPtr(true)},
},
expectedSize: 1,
validateFunc: func(views []sdkmetric.View) bool {
stream, _ := views[0](sdkmetric.Instrument{Name: "metric1"})
assert := stream.AttributeFilter == nil
assert = assert && stream.Aggregation == nil
return assert
},
},
{
name: "Case 4: metrics enabled, histogram metric",
metricsExposure: map[string]metricExposureConfig{
"metric1": {Enabled: boolPtr(true), DisabledLabelDimensions: []string{"dim1"}, BucketBoundaries: []float64{0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 15, 20, 25, 30}},
},
expectedSize: 1,
validateFunc: func(views []sdkmetric.View) bool {
stream, _ := views[0](sdkmetric.Instrument{Name: "metric1", Kind: sdkmetric.InstrumentKindHistogram})
assert := stream.AttributeFilter(attribute.String("policy_validation_mode", ""))
assert = assert && !stream.AttributeFilter(attribute.String("dim1", ""))
assert = assert && reflect.DeepEqual(stream.Aggregation, sdkmetric.AggregationExplicitBucketHistogram{
@ -122,7 +148,21 @@ func Test_metricsConfig_BuildMeterProviderViews(t *testing.T) {
},
},
{
name: "Case 3: metrics disabled",
name: "Case 5: metrics enabled, non histogram metric",
metricsExposure: map[string]metricExposureConfig{
"metric1": {Enabled: boolPtr(true), DisabledLabelDimensions: []string{"dim1"}, BucketBoundaries: []float64{0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 15, 20, 25, 30}},
},
expectedSize: 1,
validateFunc: func(views []sdkmetric.View) bool {
stream, _ := views[0](sdkmetric.Instrument{Name: "metric1", Kind: sdkmetric.InstrumentKindCounter})
assert := stream.AttributeFilter(attribute.String("policy_validation_mode", ""))
assert = assert && !stream.AttributeFilter(attribute.String("dim1", ""))
assert = assert && stream.Aggregation == nil
return assert
},
},
{
name: "Case 6: metrics disabled",
metricsExposure: map[string]metricExposureConfig{
"metric1": {Enabled: boolPtr(false)},
},