Changes to accommodate client-go changes and kube vendor update

to v1.18.0

Signed-off-by: Humble Chirammal <hchiramm@redhat.com>
This commit is contained in:
Humble Chirammal
2020-04-14 12:34:33 +05:30
committed by mergify[bot]
parent 4c96ad3c85
commit 34fc1d847e
1083 changed files with 50505 additions and 155846 deletions

View File

@ -19,11 +19,16 @@ package testutil
import (
"fmt"
"io"
"math"
"reflect"
"sort"
"strings"
dto "github.com/prometheus/client_model/go"
"github.com/prometheus/common/expfmt"
"github.com/prometheus/common/model"
"k8s.io/component-base/metrics"
)
var (
@ -147,3 +152,198 @@ func ComputeHistogramDelta(before, after model.Samples, label model.LabelName) {
func makeKey(a, b model.LabelValue) string {
return string(a) + "___" + string(b)
}
// GetMetricValuesForLabel returns value of metric for a given dimension
func GetMetricValuesForLabel(ms Metrics, metricName, label string) map[string]int64 {
samples, found := ms[metricName]
result := make(map[string]int64, len(samples))
if !found {
return result
}
for _, sample := range samples {
count := int64(sample.Value)
dimensionName := string(sample.Metric[model.LabelName(label)])
result[dimensionName] = count
}
return result
}
// ValidateMetrics verifies if every sample of metric has all expected labels
func ValidateMetrics(metrics Metrics, metricName string, expectedLabels ...string) error {
samples, ok := metrics[metricName]
if !ok {
return fmt.Errorf("metric %q was not found in metrics", metricName)
}
for _, sample := range samples {
for _, l := range expectedLabels {
if _, ok := sample.Metric[model.LabelName(l)]; !ok {
return fmt.Errorf("metric %q is missing label %q, sample: %q", metricName, l, sample.String())
}
}
}
return nil
}
// Histogram wraps prometheus histogram DTO (data transfer object)
type Histogram struct {
*dto.Histogram
}
// GetHistogramFromGatherer collects a metric from a gatherer implementing k8s.io/component-base/metrics.Gatherer interface.
// Used only for testing purposes where we need to gather metrics directly from a running binary (without metrics endpoint).
func GetHistogramFromGatherer(gatherer metrics.Gatherer, metricName string) (Histogram, error) {
var metricFamily *dto.MetricFamily
m, err := gatherer.Gather()
if err != nil {
return Histogram{}, err
}
for _, mFamily := range m {
if mFamily.Name != nil && *mFamily.Name == metricName {
metricFamily = mFamily
break
}
}
if metricFamily == nil {
return Histogram{}, fmt.Errorf("Metric %q not found", metricName)
}
if metricFamily.GetMetric() == nil {
return Histogram{}, fmt.Errorf("Metric %q is empty", metricName)
}
if len(metricFamily.GetMetric()) == 0 {
return Histogram{}, fmt.Errorf("Metric %q is empty", metricName)
}
return Histogram{
// Histograms are stored under the first index (based on observation).
// Given there's only one histogram registered per each metric name, accessing
// the first index is sufficient.
metricFamily.GetMetric()[0].GetHistogram(),
}, nil
}
func uint64Ptr(u uint64) *uint64 {
return &u
}
// Bucket of a histogram
type bucket struct {
upperBound float64
count float64
}
func bucketQuantile(q float64, buckets []bucket) float64 {
if q < 0 {
return math.Inf(-1)
}
if q > 1 {
return math.Inf(+1)
}
if len(buckets) < 2 {
return math.NaN()
}
rank := q * buckets[len(buckets)-1].count
b := sort.Search(len(buckets)-1, func(i int) bool { return buckets[i].count >= rank })
if b == 0 {
return buckets[0].upperBound * (rank / buckets[0].count)
}
// linear approximation of b-th bucket
brank := rank - buckets[b-1].count
bSize := buckets[b].upperBound - buckets[b-1].upperBound
bCount := buckets[b].count - buckets[b-1].count
return buckets[b-1].upperBound + bSize*(brank/bCount)
}
// Quantile computes q-th quantile of a cumulative histogram.
// It's expected the histogram is valid (by calling Validate)
func (hist *Histogram) Quantile(q float64) float64 {
buckets := []bucket{}
for _, bckt := range hist.Bucket {
buckets = append(buckets, bucket{
count: float64(*bckt.CumulativeCount),
upperBound: *bckt.UpperBound,
})
}
// bucketQuantile expects the upper bound of the last bucket to be +inf
// buckets[len(buckets)-1].upperBound = math.Inf(+1)
return bucketQuantile(q, buckets)
}
// Average computes histogram's average value
func (hist *Histogram) Average() float64 {
return *hist.SampleSum / float64(*hist.SampleCount)
}
// Clear clears all fields of the wrapped histogram
func (hist *Histogram) Clear() {
if hist.SampleCount != nil {
*hist.SampleCount = 0
}
if hist.SampleSum != nil {
*hist.SampleSum = 0
}
for _, b := range hist.Bucket {
if b.CumulativeCount != nil {
*b.CumulativeCount = 0
}
}
}
// Validate makes sure the wrapped histogram has all necessary fields set and with valid values.
func (hist *Histogram) Validate() error {
if hist.SampleCount == nil || *hist.SampleCount == 0 {
return fmt.Errorf("nil or empty histogram SampleCount")
}
if hist.SampleSum == nil || *hist.SampleSum == 0 {
return fmt.Errorf("nil or empty histogram SampleSum")
}
for _, bckt := range hist.Bucket {
if bckt == nil {
return fmt.Errorf("empty histogram bucket")
}
if bckt.UpperBound == nil || *bckt.UpperBound < 0 {
return fmt.Errorf("nil or negative histogram bucket UpperBound")
}
}
return nil
}
// GetGaugeMetricValue extract metric value from GaugeMetric
func GetGaugeMetricValue(m metrics.GaugeMetric) (float64, error) {
metricProto := &dto.Metric{}
if err := m.Write(metricProto); err != nil {
return 0, fmt.Errorf("Error writing m: %v", err)
}
return metricProto.Gauge.GetValue(), nil
}
// GetCounterMetricValue extract metric value from CounterMetric
func GetCounterMetricValue(m metrics.CounterMetric) (float64, error) {
metricProto := &dto.Metric{}
if err := m.(metrics.Metric).Write(metricProto); err != nil {
return 0, fmt.Errorf("Error writing m: %v", err)
}
return metricProto.Counter.GetValue(), nil
}
// GetHistogramMetricValue extract sum of all samples from ObserverMetric
func GetHistogramMetricValue(m metrics.ObserverMetric) (float64, error) {
metricProto := &dto.Metric{}
if err := m.(metrics.Metric).Write(metricProto); err != nil {
return 0, fmt.Errorf("Error writing m: %v", err)
}
return metricProto.Histogram.GetSampleSum(), nil
}

View File

@ -17,10 +17,12 @@ limitations under the License.
package testutil
import (
"fmt"
"io"
"github.com/prometheus/client_golang/prometheus/testutil"
apimachineryversion "k8s.io/apimachinery/pkg/version"
"k8s.io/component-base/metrics"
)
@ -48,3 +50,21 @@ func CustomCollectAndCompare(c metrics.StableCollector, expected io.Reader, metr
return GatherAndCompare(registry, expected, metricNames...)
}
// NewFakeKubeRegistry creates a fake `KubeRegistry` that takes the input version as `build in version`.
// It should only be used in testing scenario especially for the deprecated metrics.
// The input version format should be `major.minor.patch`, e.g. '1.18.0'.
func NewFakeKubeRegistry(ver string) metrics.KubeRegistry {
backup := metrics.BuildVersion
defer func() {
metrics.BuildVersion = backup
}()
metrics.BuildVersion = func() apimachineryversion.Info {
return apimachineryversion.Info{
GitVersion: fmt.Sprintf("v%s-alpha+1.12345", ver),
}
}
return metrics.NewKubeRegistry()
}