diff --git a/pkg/collector/max_collector.go b/pkg/collector/max_collector.go index adb84e8..cf7fcc5 100644 --- a/pkg/collector/max_collector.go +++ b/pkg/collector/max_collector.go @@ -2,8 +2,10 @@ package collector import ( "fmt" - "k8s.io/apimachinery/pkg/api/resource" + "strings" "time" + + "k8s.io/apimachinery/pkg/api/resource" ) // MaxWeightedCollector is a simple aggregator collector that returns the maximum value @@ -25,18 +27,29 @@ func NewMaxWeightedCollector(interval time.Duration, weight float64, collectors // GetMetrics gets metrics from all collectors and return the higest value. func (c *MaxWeightedCollector) GetMetrics() ([]CollectedMetric, error) { + errors := make([]error, 0) collectedMetrics := make([]CollectedMetric, 0) for _, collector := range c.collectors { values, err := collector.GetMetrics() if err != nil { - return nil, err + errors = append(errors, err) + continue } for _, v := range values { collectedMetrics = append(collectedMetrics, v) } } if len(collectedMetrics) == 0 { - return nil, fmt.Errorf("no metrics collected, cannot determine max") + if len(errors) == 0 { + return nil, fmt.Errorf("no metrics collected, cannot determine max") + } else { + errorStrings := make([]string, len(errors)) + for i, e := range errors { + errorStrings[i] = e.Error() + } + allErrors := strings.Join(errorStrings, ",") + return nil, fmt.Errorf("could not determine maximum due to errors: %s", allErrors) + } } max := collectedMetrics[0] for _, value := range collectedMetrics { diff --git a/pkg/collector/max_collector_test.go b/pkg/collector/max_collector_test.go new file mode 100644 index 0000000..776aa69 --- /dev/null +++ b/pkg/collector/max_collector_test.go @@ -0,0 +1,76 @@ +package collector + +import ( + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/require" + "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/metrics/pkg/apis/custom_metrics" +) + +type dummyCollector struct { + value int64 +} + +func (c dummyCollector) Interval() time.Duration { + return time.Second +} + +func (c dummyCollector) GetMetrics() ([]CollectedMetric, error) { + if c.value > 0 { + quantity := resource.NewQuantity(c.value, resource.DecimalSI) + return []CollectedMetric{ + { + Custom: custom_metrics.MetricValue{ + Value: *quantity, + }, + }, + }, nil + } else { + return nil, fmt.Errorf("test error") + } +} + +func TestMaxCollector(t *testing.T) { + for _, tc := range []struct { + name string + values []int64 + expected int + weight float64 + }{ + { + name: "basic", + values: []int64{100, 10, 9}, + expected: 100, + weight: 1, + }, + { + name: "weighted", + values: []int64{100, 10, 9}, + expected: 20, + weight: 0.2, + }, + { + name: "with error", + values: []int64{-1, 10, 9}, + expected: 5, + weight: 0.5, + }, + } { + t.Run(tc.name, func(t *testing.T) { + collectors := make([]Collector, len(tc.values)) + for i, v := range tc.values { + collectors[i] = dummyCollector{value: v} + } + wc := NewMaxWeightedCollector(time.Second, tc.weight, collectors...) + metrics, err := wc.GetMetrics() + require.NoError(t, err) + require.Len(t, metrics, 1) + require.EqualValues(t, tc.expected, metrics[0].Custom.Value.Value()) + + }) + + } +}