Change:
*dto.Histogram } <del> // GetHistogramFromGatherer collects a metric from a gatherer implementing k8s.io/component-base/metrics.Gatherer interface. </del> <ins> // HistogramVec wraps a slice of Histogram. // Note that each Histogram must have the same number of buckets. type HistogramVec []*Histogram // GetAggregatedSampleCount aggregates the sample count of each inner Histogram. func (vec HistogramVec) GetAggregatedSampleCount() uint64 { var count uint64 for _, hist := range vec { count += hist.GetSampleCount() } return count } // GetAggregatedSampleSum aggregates the sample sum of each inner Histogram. func (vec HistogramVec) GetAggregatedSampleSum() float64 { var sum float64 for _, hist := range vec { sum += hist.GetSampleSum() } return sum } // Quantile first aggregates inner buckets of each Histogram, and then // computes q-th quantile of a cumulative histogram. func (vec HistogramVec) Quantile(q float64) float64 { var buckets []bucket for i, hist := range vec { for j, bckt := range hist.Bucket { if i == 0 { buckets = append(buckets, bucket{ count:      float64(bckt.GetCumulativeCount()), upperBound: bckt.GetUpperBound(), }) } else { buckets[j].count += float64(bckt.GetCumulativeCount()) } } } if len(buckets) == 0 || buckets[len(buckets)-1].upperBound != math.Inf(+1) { // The list of buckets in dto.Histogram doesn't include the final +Inf bucket, so we // add it here for the rest of the samples. buckets = append(buckets, bucket{ count:      float64(vec.GetAggregatedSampleCount()), upperBound: math.Inf(+1), }) } return bucketQuantile(q, buckets) } // Average computes wrapped histograms' average value. func (vec HistogramVec) Average() float64 { return vec.GetAggregatedSampleSum() / float64(vec.GetAggregatedSampleCount()) } // Validate makes sure the wrapped histograms have all necessary fields set and with valid values. func (vec HistogramVec) Validate() error { bucketSize := 0 for i, hist := range vec { if err := hist.Validate(); err != nil { return err } if i == 0 { bucketSize = len(hist.GetBucket()) } else if bucketSize != len(hist.GetBucket()) { return fmt.Errorf("found different bucket size: expect %v, but got %v at index %v", bucketSize, len(hist.GetBucket()), i) } } return nil } // GetHistogramVecFromGatherer collects a metric, that matches the input labelValue map, // from a gatherer implementing k8s.io/component-base/metrics.Gatherer interface. </ins> // Used only for testing purposes where we need to gather metrics directly from a running binary (without metrics endpoint). <del> func GetHistogramFromGatherer(gatherer metrics.Gatherer, metricName string) (Histogram, error) { </del> <ins> func GetHistogramVecFromGatherer(gatherer metrics.Gatherer, metricName string, lvMap map[string]string) (HistogramVec, error) { </ins> var metricFamily *dto.MetricFamily m, err := gatherer.Gather() if err != nil { <del> return Histogram{}, err </del> <ins> return nil, err </ins> } for _, mFamily := range m { if mFamily.GetName() == metricName {

Discussion:
The new scheduler performance test was introduced back in 1.18, back then, the metric it supported are all . However, along with , some metrics are updated to be , and hence it's no longer appropriate to return the first Histogram: However, it's very common (for instance Preemption) that the metrics may hold multiple histograms: Additionally, metrics and have been removed, we should update them to : /sig scheduling
/triage accepted /assign
Issues go stale after 90d of inactivity. Mark the issue as fresh with . Stale issues rot after an additional 30d of inactivity and eventually close. If this issue is safe to close now please do so with . Send feedback to sig-contributor-experience at . /lifecycle stale
/remove-lifecycle stale