mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 10:33:35 +00:00
build: move e2e dependencies into e2e/go.mod
Several packages are only used while running the e2e suite. These packages are less important to update, as the they can not influence the final executable that is part of the Ceph-CSI container-image. By moving these dependencies out of the main Ceph-CSI go.mod, it is easier to identify if a reported CVE affects Ceph-CSI, or only the testing (like most of the Kubernetes CVEs). Signed-off-by: Niels de Vos <ndevos@ibm.com>
This commit is contained in:
committed by
mergify[bot]
parent
15da101b1b
commit
bec6090996
11
e2e/vendor/k8s.io/component-base/metrics/OWNERS
generated
vendored
Normal file
11
e2e/vendor/k8s.io/component-base/metrics/OWNERS
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
# See the OWNERS docs at https://go.k8s.io/owners
|
||||
|
||||
approvers:
|
||||
- sig-instrumentation-approvers
|
||||
- logicalhan
|
||||
- RainbowMango
|
||||
reviewers:
|
||||
- sig-instrumentation-reviewers
|
||||
- YoyinZyc
|
||||
labels:
|
||||
- sig/instrumentation
|
53
e2e/vendor/k8s.io/component-base/metrics/buckets.go
generated
vendored
Normal file
53
e2e/vendor/k8s.io/component-base/metrics/buckets.go
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright 2022 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
// DefBuckets is a wrapper for prometheus.DefBuckets
|
||||
var DefBuckets = prometheus.DefBuckets
|
||||
|
||||
// LinearBuckets is a wrapper for prometheus.LinearBuckets.
|
||||
func LinearBuckets(start, width float64, count int) []float64 {
|
||||
return prometheus.LinearBuckets(start, width, count)
|
||||
}
|
||||
|
||||
// ExponentialBuckets is a wrapper for prometheus.ExponentialBuckets.
|
||||
func ExponentialBuckets(start, factor float64, count int) []float64 {
|
||||
return prometheus.ExponentialBuckets(start, factor, count)
|
||||
}
|
||||
|
||||
// ExponentialBucketsRange creates 'count' buckets, where the lowest bucket is
|
||||
// 'min' and the highest bucket is 'max'. The final +Inf bucket is not counted
|
||||
// and not included in the returned slice. The returned slice is meant to be
|
||||
// used for the Buckets field of HistogramOpts.
|
||||
//
|
||||
// The function panics if 'count' is 0 or negative, if 'min' is 0 or negative.
|
||||
func ExponentialBucketsRange(min, max float64, count int) []float64 {
|
||||
return prometheus.ExponentialBucketsRange(min, max, count)
|
||||
}
|
||||
|
||||
// MergeBuckets merges buckets together
|
||||
func MergeBuckets(buckets ...[]float64) []float64 {
|
||||
result := make([]float64, 1)
|
||||
for _, s := range buckets {
|
||||
result = append(result, s...)
|
||||
}
|
||||
return result
|
||||
}
|
190
e2e/vendor/k8s.io/component-base/metrics/collector.go
generated
vendored
Normal file
190
e2e/vendor/k8s.io/component-base/metrics/collector.go
generated
vendored
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
// StableCollector extends the prometheus.Collector interface to allow customization of the
|
||||
// metric registration process, it's especially intend to be used in scenario of custom collector.
|
||||
type StableCollector interface {
|
||||
prometheus.Collector
|
||||
|
||||
// DescribeWithStability sends the super-set of all possible metrics.Desc collected
|
||||
// by this StableCollector to the provided channel.
|
||||
DescribeWithStability(chan<- *Desc)
|
||||
|
||||
// CollectWithStability sends each collected metrics.Metric via the provide channel.
|
||||
CollectWithStability(chan<- Metric)
|
||||
|
||||
// Create will initialize all Desc and it intends to be called by registry.
|
||||
Create(version *semver.Version, self StableCollector) bool
|
||||
|
||||
// ClearState will clear all the states marked by Create.
|
||||
ClearState()
|
||||
|
||||
// HiddenMetrics tells the list of hidden metrics with fqName.
|
||||
HiddenMetrics() []string
|
||||
}
|
||||
|
||||
// BaseStableCollector which implements almost all methods defined by StableCollector
|
||||
// is a convenient assistant for custom collectors.
|
||||
// It is recommended to inherit BaseStableCollector when implementing custom collectors.
|
||||
type BaseStableCollector struct {
|
||||
descriptors map[string]*Desc // stores all descriptors by pair<fqName, Desc>, these are collected from DescribeWithStability().
|
||||
registerable map[string]*Desc // stores registerable descriptors by pair<fqName, Desc>, is a subset of descriptors.
|
||||
hidden map[string]*Desc // stores hidden descriptors by pair<fqName, Desc>, is a subset of descriptors.
|
||||
self StableCollector
|
||||
}
|
||||
|
||||
// DescribeWithStability sends all descriptors to the provided channel.
|
||||
// Every custom collector should over-write this method.
|
||||
func (bsc *BaseStableCollector) DescribeWithStability(ch chan<- *Desc) {
|
||||
panic(fmt.Errorf("custom collector should over-write DescribeWithStability method"))
|
||||
}
|
||||
|
||||
// Describe sends all descriptors to the provided channel.
|
||||
// It intended to be called by prometheus registry.
|
||||
func (bsc *BaseStableCollector) Describe(ch chan<- *prometheus.Desc) {
|
||||
for _, d := range bsc.registerable {
|
||||
ch <- d.toPrometheusDesc()
|
||||
}
|
||||
}
|
||||
|
||||
// CollectWithStability sends all metrics to the provided channel.
|
||||
// Every custom collector should over-write this method.
|
||||
func (bsc *BaseStableCollector) CollectWithStability(ch chan<- Metric) {
|
||||
panic(fmt.Errorf("custom collector should over-write CollectWithStability method"))
|
||||
}
|
||||
|
||||
// Collect is called by the Prometheus registry when collecting metrics.
|
||||
func (bsc *BaseStableCollector) Collect(ch chan<- prometheus.Metric) {
|
||||
mch := make(chan Metric)
|
||||
|
||||
go func() {
|
||||
bsc.self.CollectWithStability(mch)
|
||||
close(mch)
|
||||
}()
|
||||
|
||||
for m := range mch {
|
||||
// nil Metric usually means hidden metrics
|
||||
if m == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
ch <- prometheus.Metric(m)
|
||||
}
|
||||
}
|
||||
|
||||
func (bsc *BaseStableCollector) add(d *Desc) {
|
||||
if len(d.fqName) == 0 {
|
||||
panic("nameless metrics will be not allowed")
|
||||
}
|
||||
|
||||
if bsc.descriptors == nil {
|
||||
bsc.descriptors = make(map[string]*Desc)
|
||||
}
|
||||
|
||||
if _, exist := bsc.descriptors[d.fqName]; exist {
|
||||
panic(fmt.Sprintf("duplicate metrics (%s) will be not allowed", d.fqName))
|
||||
}
|
||||
|
||||
bsc.descriptors[d.fqName] = d
|
||||
}
|
||||
|
||||
// Init intends to be called by registry.
|
||||
func (bsc *BaseStableCollector) init(self StableCollector) {
|
||||
bsc.self = self
|
||||
|
||||
dch := make(chan *Desc)
|
||||
|
||||
// collect all possible descriptions from custom side
|
||||
go func() {
|
||||
bsc.self.DescribeWithStability(dch)
|
||||
close(dch)
|
||||
}()
|
||||
|
||||
for d := range dch {
|
||||
bsc.add(d)
|
||||
}
|
||||
}
|
||||
|
||||
func (bsc *BaseStableCollector) trackRegistrableDescriptor(d *Desc) {
|
||||
if bsc.registerable == nil {
|
||||
bsc.registerable = make(map[string]*Desc)
|
||||
}
|
||||
|
||||
bsc.registerable[d.fqName] = d
|
||||
}
|
||||
|
||||
func (bsc *BaseStableCollector) trackHiddenDescriptor(d *Desc) {
|
||||
if bsc.hidden == nil {
|
||||
bsc.hidden = make(map[string]*Desc)
|
||||
}
|
||||
|
||||
bsc.hidden[d.fqName] = d
|
||||
}
|
||||
|
||||
// Create intends to be called by registry.
|
||||
// Create will return true as long as there is one or more metrics not be hidden.
|
||||
// Otherwise return false, that means the whole collector will be ignored by registry.
|
||||
func (bsc *BaseStableCollector) Create(version *semver.Version, self StableCollector) bool {
|
||||
bsc.init(self)
|
||||
|
||||
for _, d := range bsc.descriptors {
|
||||
d.create(version)
|
||||
if d.IsHidden() {
|
||||
bsc.trackHiddenDescriptor(d)
|
||||
} else {
|
||||
bsc.trackRegistrableDescriptor(d)
|
||||
}
|
||||
}
|
||||
|
||||
if len(bsc.registerable) > 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// ClearState will clear all the states marked by Create.
|
||||
// It intends to be used for re-register a hidden metric.
|
||||
func (bsc *BaseStableCollector) ClearState() {
|
||||
for _, d := range bsc.descriptors {
|
||||
d.ClearState()
|
||||
}
|
||||
|
||||
bsc.descriptors = nil
|
||||
bsc.registerable = nil
|
||||
bsc.hidden = nil
|
||||
bsc.self = nil
|
||||
}
|
||||
|
||||
// HiddenMetrics tells the list of hidden metrics with fqName.
|
||||
func (bsc *BaseStableCollector) HiddenMetrics() (fqNames []string) {
|
||||
for i := range bsc.hidden {
|
||||
fqNames = append(fqNames, bsc.hidden[i].fqName)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Check if our BaseStableCollector implements necessary interface
|
||||
var _ StableCollector = &BaseStableCollector{}
|
306
e2e/vendor/k8s.io/component-base/metrics/counter.go
generated
vendored
Normal file
306
e2e/vendor/k8s.io/component-base/metrics/counter.go
generated
vendored
Normal file
@ -0,0 +1,306 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
// Counter is our internal representation for our wrapping struct around prometheus
|
||||
// counters. Counter implements both kubeCollector and CounterMetric.
|
||||
type Counter struct {
|
||||
ctx context.Context
|
||||
CounterMetric
|
||||
*CounterOpts
|
||||
lazyMetric
|
||||
selfCollector
|
||||
}
|
||||
|
||||
// The implementation of the Metric interface is expected by testutil.GetCounterMetricValue.
|
||||
var _ Metric = &Counter{}
|
||||
|
||||
// All supported exemplar metric types implement the metricWithExemplar interface.
|
||||
var _ metricWithExemplar = &Counter{}
|
||||
|
||||
// exemplarCounterMetric holds a context to extract exemplar labels from, and a counter metric to attach them to. It implements the metricWithExemplar interface.
|
||||
type exemplarCounterMetric struct {
|
||||
*Counter
|
||||
}
|
||||
|
||||
// NewCounter returns an object which satisfies the kubeCollector and CounterMetric interfaces.
|
||||
// However, the object returned will not measure anything unless the collector is first
|
||||
// registered, since the metric is lazily instantiated.
|
||||
func NewCounter(opts *CounterOpts) *Counter {
|
||||
opts.StabilityLevel.setDefaults()
|
||||
|
||||
kc := &Counter{
|
||||
CounterOpts: opts,
|
||||
lazyMetric: lazyMetric{stabilityLevel: opts.StabilityLevel},
|
||||
}
|
||||
kc.setPrometheusCounter(noop)
|
||||
kc.lazyInit(kc, BuildFQName(opts.Namespace, opts.Subsystem, opts.Name))
|
||||
return kc
|
||||
}
|
||||
|
||||
func (c *Counter) Desc() *prometheus.Desc {
|
||||
return c.metric.Desc()
|
||||
}
|
||||
|
||||
func (c *Counter) Write(to *dto.Metric) error {
|
||||
return c.metric.Write(to)
|
||||
}
|
||||
|
||||
// Reset resets the underlying prometheus Counter to start counting from 0 again
|
||||
func (c *Counter) Reset() {
|
||||
if !c.IsCreated() {
|
||||
return
|
||||
}
|
||||
c.setPrometheusCounter(prometheus.NewCounter(c.CounterOpts.toPromCounterOpts()))
|
||||
}
|
||||
|
||||
// setPrometheusCounter sets the underlying CounterMetric object, i.e. the thing that does the measurement.
|
||||
func (c *Counter) setPrometheusCounter(counter prometheus.Counter) {
|
||||
c.CounterMetric = counter
|
||||
c.initSelfCollection(counter)
|
||||
}
|
||||
|
||||
// DeprecatedVersion returns a pointer to the Version or nil
|
||||
func (c *Counter) DeprecatedVersion() *semver.Version {
|
||||
return parseSemver(c.CounterOpts.DeprecatedVersion)
|
||||
}
|
||||
|
||||
// initializeMetric invocation creates the actual underlying Counter. Until this method is called
|
||||
// the underlying counter is a no-op.
|
||||
func (c *Counter) initializeMetric() {
|
||||
c.CounterOpts.annotateStabilityLevel()
|
||||
// this actually creates the underlying prometheus counter.
|
||||
c.setPrometheusCounter(prometheus.NewCounter(c.CounterOpts.toPromCounterOpts()))
|
||||
}
|
||||
|
||||
// initializeDeprecatedMetric invocation creates the actual (but deprecated) Counter. Until this method
|
||||
// is called the underlying counter is a no-op.
|
||||
func (c *Counter) initializeDeprecatedMetric() {
|
||||
c.CounterOpts.markDeprecated()
|
||||
c.initializeMetric()
|
||||
}
|
||||
|
||||
// WithContext allows the normal Counter metric to pass in context.
|
||||
func (c *Counter) WithContext(ctx context.Context) CounterMetric {
|
||||
c.ctx = ctx
|
||||
return c.CounterMetric
|
||||
}
|
||||
|
||||
// withExemplar initializes the exemplarMetric object and sets the exemplar value.
|
||||
func (c *Counter) withExemplar(v float64) {
|
||||
(&exemplarCounterMetric{c}).withExemplar(v)
|
||||
}
|
||||
|
||||
func (c *Counter) Add(v float64) {
|
||||
c.withExemplar(v)
|
||||
}
|
||||
|
||||
func (c *Counter) Inc() {
|
||||
c.withExemplar(1)
|
||||
}
|
||||
|
||||
// withExemplar attaches an exemplar to the metric.
|
||||
func (e *exemplarCounterMetric) withExemplar(v float64) {
|
||||
if m, ok := e.CounterMetric.(prometheus.ExemplarAdder); ok {
|
||||
maybeSpanCtx := trace.SpanContextFromContext(e.ctx)
|
||||
if maybeSpanCtx.IsValid() && maybeSpanCtx.IsSampled() {
|
||||
exemplarLabels := prometheus.Labels{
|
||||
"trace_id": maybeSpanCtx.TraceID().String(),
|
||||
"span_id": maybeSpanCtx.SpanID().String(),
|
||||
}
|
||||
m.AddWithExemplar(v, exemplarLabels)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
e.CounterMetric.Add(v)
|
||||
}
|
||||
|
||||
// CounterVec is the internal representation of our wrapping struct around prometheus
|
||||
// counterVecs. CounterVec implements both kubeCollector and CounterVecMetric.
|
||||
type CounterVec struct {
|
||||
*prometheus.CounterVec
|
||||
*CounterOpts
|
||||
lazyMetric
|
||||
originalLabels []string
|
||||
}
|
||||
|
||||
var _ kubeCollector = &CounterVec{}
|
||||
|
||||
// TODO: make this true: var _ CounterVecMetric = &CounterVec{}
|
||||
|
||||
// NewCounterVec returns an object which satisfies the kubeCollector and (almost) CounterVecMetric interfaces.
|
||||
// However, the object returned will not measure anything unless the collector is first
|
||||
// registered, since the metric is lazily instantiated, and only members extracted after
|
||||
// registration will actually measure anything.
|
||||
func NewCounterVec(opts *CounterOpts, labels []string) *CounterVec {
|
||||
opts.StabilityLevel.setDefaults()
|
||||
|
||||
fqName := BuildFQName(opts.Namespace, opts.Subsystem, opts.Name)
|
||||
|
||||
cv := &CounterVec{
|
||||
CounterVec: noopCounterVec,
|
||||
CounterOpts: opts,
|
||||
originalLabels: labels,
|
||||
lazyMetric: lazyMetric{stabilityLevel: opts.StabilityLevel},
|
||||
}
|
||||
cv.lazyInit(cv, fqName)
|
||||
return cv
|
||||
}
|
||||
|
||||
// DeprecatedVersion returns a pointer to the Version or nil
|
||||
func (v *CounterVec) DeprecatedVersion() *semver.Version {
|
||||
return parseSemver(v.CounterOpts.DeprecatedVersion)
|
||||
|
||||
}
|
||||
|
||||
// initializeMetric invocation creates the actual underlying CounterVec. Until this method is called
|
||||
// the underlying counterVec is a no-op.
|
||||
func (v *CounterVec) initializeMetric() {
|
||||
v.CounterOpts.annotateStabilityLevel()
|
||||
v.CounterVec = prometheus.NewCounterVec(v.CounterOpts.toPromCounterOpts(), v.originalLabels)
|
||||
}
|
||||
|
||||
// initializeDeprecatedMetric invocation creates the actual (but deprecated) CounterVec. Until this method is called
|
||||
// the underlying counterVec is a no-op.
|
||||
func (v *CounterVec) initializeDeprecatedMetric() {
|
||||
v.CounterOpts.markDeprecated()
|
||||
v.initializeMetric()
|
||||
}
|
||||
|
||||
// Default Prometheus Vec behavior is that member extraction results in creation of a new element
|
||||
// if one with the unique label values is not found in the underlying stored metricMap.
|
||||
// This means that if this function is called but the underlying metric is not registered
|
||||
// (which means it will never be exposed externally nor consumed), the metric will exist in memory
|
||||
// for perpetuity (i.e. throughout application lifecycle).
|
||||
//
|
||||
// For reference: https://github.com/prometheus/client_golang/blob/v0.9.2/prometheus/counter.go#L179-L197
|
||||
//
|
||||
// In contrast, the Vec behavior in this package is that member extraction before registration
|
||||
// returns a permanent noop object.
|
||||
|
||||
// WithLabelValues returns the Counter for the given slice of label
|
||||
// values (same order as the VariableLabels in Desc). If that combination of
|
||||
// label values is accessed for the first time, a new Counter is created IFF the counterVec
|
||||
// has been registered to a metrics registry.
|
||||
func (v *CounterVec) WithLabelValues(lvs ...string) CounterMetric {
|
||||
if !v.IsCreated() {
|
||||
return noop // return no-op counter
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
} else {
|
||||
v.initializeLabelAllowListsOnce.Do(func() {
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[v.FQName()]; ok {
|
||||
v.LabelValueAllowLists = allowList
|
||||
allowList.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
})
|
||||
}
|
||||
|
||||
return v.CounterVec.WithLabelValues(lvs...)
|
||||
}
|
||||
|
||||
// With returns the Counter for the given Labels map (the label names
|
||||
// must match those of the VariableLabels in Desc). If that label map is
|
||||
// accessed for the first time, a new Counter is created IFF the counterVec has
|
||||
// been registered to a metrics registry.
|
||||
func (v *CounterVec) With(labels map[string]string) CounterMetric {
|
||||
if !v.IsCreated() {
|
||||
return noop // return no-op counter
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainLabelMap(labels)
|
||||
} else {
|
||||
v.initializeLabelAllowListsOnce.Do(func() {
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[v.FQName()]; ok {
|
||||
v.LabelValueAllowLists = allowList
|
||||
allowList.ConstrainLabelMap(labels)
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
})
|
||||
}
|
||||
return v.CounterVec.With(labels)
|
||||
}
|
||||
|
||||
// Delete deletes the metric where the variable labels are the same as those
|
||||
// passed in as labels. It returns true if a metric was deleted.
|
||||
//
|
||||
// It is not an error if the number and names of the Labels are inconsistent
|
||||
// with those of the VariableLabels in Desc. However, such inconsistent Labels
|
||||
// can never match an actual metric, so the method will always return false in
|
||||
// that case.
|
||||
func (v *CounterVec) Delete(labels map[string]string) bool {
|
||||
if !v.IsCreated() {
|
||||
return false // since we haven't created the metric, we haven't deleted a metric with the passed in values
|
||||
}
|
||||
return v.CounterVec.Delete(labels)
|
||||
}
|
||||
|
||||
// Reset deletes all metrics in this vector.
|
||||
func (v *CounterVec) Reset() {
|
||||
if !v.IsCreated() {
|
||||
return
|
||||
}
|
||||
|
||||
v.CounterVec.Reset()
|
||||
}
|
||||
|
||||
// ResetLabelAllowLists resets the label allow list for the CounterVec.
|
||||
// NOTE: This should only be used in test.
|
||||
func (v *CounterVec) ResetLabelAllowLists() {
|
||||
v.initializeLabelAllowListsOnce = sync.Once{}
|
||||
v.LabelValueAllowLists = nil
|
||||
}
|
||||
|
||||
// WithContext returns wrapped CounterVec with context
|
||||
func (v *CounterVec) WithContext(ctx context.Context) *CounterVecWithContext {
|
||||
return &CounterVecWithContext{
|
||||
ctx: ctx,
|
||||
CounterVec: v,
|
||||
}
|
||||
}
|
||||
|
||||
// CounterVecWithContext is the wrapper of CounterVec with context.
|
||||
type CounterVecWithContext struct {
|
||||
*CounterVec
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
// WithLabelValues is the wrapper of CounterVec.WithLabelValues.
|
||||
func (vc *CounterVecWithContext) WithLabelValues(lvs ...string) CounterMetric {
|
||||
return vc.CounterVec.WithLabelValues(lvs...)
|
||||
}
|
||||
|
||||
// With is the wrapper of CounterVec.With.
|
||||
func (vc *CounterVecWithContext) With(labels map[string]string) CounterMetric {
|
||||
return vc.CounterVec.With(labels)
|
||||
}
|
225
e2e/vendor/k8s.io/component-base/metrics/desc.go
generated
vendored
Normal file
225
e2e/vendor/k8s.io/component-base/metrics/desc.go
generated
vendored
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// Desc is a prometheus.Desc extension.
|
||||
//
|
||||
// Use NewDesc to create new Desc instances.
|
||||
type Desc struct {
|
||||
// fqName has been built from Namespace, Subsystem, and Name.
|
||||
fqName string
|
||||
// help provides some helpful information about this metric.
|
||||
help string
|
||||
// constLabels is the label names. Their label values are variable.
|
||||
constLabels Labels
|
||||
// variableLabels contains names of labels for which the metric
|
||||
// maintains variable values.
|
||||
variableLabels []string
|
||||
|
||||
// promDesc is the descriptor used by every Prometheus Metric.
|
||||
promDesc *prometheus.Desc
|
||||
annotatedHelp string
|
||||
|
||||
// stabilityLevel represents the API guarantees for a given defined metric.
|
||||
stabilityLevel StabilityLevel
|
||||
// deprecatedVersion represents in which version this metric be deprecated.
|
||||
deprecatedVersion string
|
||||
|
||||
isDeprecated bool
|
||||
isHidden bool
|
||||
isCreated bool
|
||||
createLock sync.RWMutex
|
||||
markDeprecationOnce sync.Once
|
||||
createOnce sync.Once
|
||||
deprecateOnce sync.Once
|
||||
hideOnce sync.Once
|
||||
annotateOnce sync.Once
|
||||
}
|
||||
|
||||
// NewDesc extends prometheus.NewDesc with stability support.
|
||||
//
|
||||
// The stabilityLevel should be valid stability label, such as "metrics.ALPHA"
|
||||
// and "metrics.STABLE"(Maybe "metrics.BETA" in future). Default value "metrics.ALPHA"
|
||||
// will be used in case of empty or invalid stability label.
|
||||
//
|
||||
// The deprecatedVersion represents in which version this Metric be deprecated.
|
||||
// The deprecation policy outlined by the control plane metrics stability KEP.
|
||||
func NewDesc(fqName string, help string, variableLabels []string, constLabels Labels,
|
||||
stabilityLevel StabilityLevel, deprecatedVersion string) *Desc {
|
||||
d := &Desc{
|
||||
fqName: fqName,
|
||||
help: help,
|
||||
annotatedHelp: help,
|
||||
variableLabels: variableLabels,
|
||||
constLabels: constLabels,
|
||||
stabilityLevel: stabilityLevel,
|
||||
deprecatedVersion: deprecatedVersion,
|
||||
}
|
||||
d.stabilityLevel.setDefaults()
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
// String formats the Desc as a string.
|
||||
// The stability metadata maybe annotated in 'HELP' section if called after registry,
|
||||
// otherwise not.
|
||||
// e.g. "Desc{fqName: "normal_stable_descriptor", help: "[STABLE] this is a stable descriptor", constLabels: {}, variableLabels: []}"
|
||||
func (d *Desc) String() string {
|
||||
if d.isCreated {
|
||||
return d.promDesc.String()
|
||||
}
|
||||
|
||||
return prometheus.NewDesc(d.fqName, d.help, d.variableLabels, prometheus.Labels(d.constLabels)).String()
|
||||
}
|
||||
|
||||
// toPrometheusDesc transform self to prometheus.Desc
|
||||
func (d *Desc) toPrometheusDesc() *prometheus.Desc {
|
||||
return d.promDesc
|
||||
}
|
||||
|
||||
// DeprecatedVersion returns a pointer to the Version or nil
|
||||
func (d *Desc) DeprecatedVersion() *semver.Version {
|
||||
return parseSemver(d.deprecatedVersion)
|
||||
|
||||
}
|
||||
|
||||
func (d *Desc) determineDeprecationStatus(version semver.Version) {
|
||||
selfVersion := d.DeprecatedVersion()
|
||||
if selfVersion == nil {
|
||||
return
|
||||
}
|
||||
d.markDeprecationOnce.Do(func() {
|
||||
if selfVersion.LTE(version) {
|
||||
d.isDeprecated = true
|
||||
}
|
||||
if ShouldShowHidden() {
|
||||
klog.Warningf("Hidden metrics(%s) have been manually overridden, showing this very deprecated metric.", d.fqName)
|
||||
return
|
||||
}
|
||||
if shouldHide(&version, selfVersion) {
|
||||
// TODO(RainbowMango): Remove this log temporarily. https://github.com/kubernetes/kubernetes/issues/85369
|
||||
// klog.Warningf("This metric(%s) has been deprecated for more than one release, hiding.", d.fqName)
|
||||
d.isHidden = true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// IsHidden returns if metric will be hidden
|
||||
func (d *Desc) IsHidden() bool {
|
||||
return d.isHidden
|
||||
}
|
||||
|
||||
// IsDeprecated returns if metric has been deprecated
|
||||
func (d *Desc) IsDeprecated() bool {
|
||||
return d.isDeprecated
|
||||
}
|
||||
|
||||
// IsCreated returns if metric has been created.
|
||||
func (d *Desc) IsCreated() bool {
|
||||
d.createLock.RLock()
|
||||
defer d.createLock.RUnlock()
|
||||
|
||||
return d.isCreated
|
||||
}
|
||||
|
||||
// create forces the initialization of Desc which has been deferred until
|
||||
// the point at which this method is invoked. This method will determine whether
|
||||
// the Desc is deprecated or hidden, no-opting if the Desc should be considered
|
||||
// hidden. Furthermore, this function no-opts and returns true if Desc is already
|
||||
// created.
|
||||
func (d *Desc) create(version *semver.Version) bool {
|
||||
if version != nil {
|
||||
d.determineDeprecationStatus(*version)
|
||||
}
|
||||
|
||||
// let's not create if this metric is slated to be hidden
|
||||
if d.IsHidden() {
|
||||
return false
|
||||
}
|
||||
d.createOnce.Do(func() {
|
||||
d.createLock.Lock()
|
||||
defer d.createLock.Unlock()
|
||||
|
||||
d.isCreated = true
|
||||
if d.IsDeprecated() {
|
||||
d.initializeDeprecatedDesc()
|
||||
} else {
|
||||
d.initialize()
|
||||
}
|
||||
})
|
||||
return d.IsCreated()
|
||||
}
|
||||
|
||||
// ClearState will clear all the states marked by Create.
|
||||
// It intends to be used for re-register a hidden metric.
|
||||
func (d *Desc) ClearState() {
|
||||
d.isDeprecated = false
|
||||
d.isHidden = false
|
||||
d.isCreated = false
|
||||
|
||||
d.markDeprecationOnce = *new(sync.Once)
|
||||
d.createOnce = *new(sync.Once)
|
||||
d.deprecateOnce = *new(sync.Once)
|
||||
d.hideOnce = *new(sync.Once)
|
||||
d.annotateOnce = *new(sync.Once)
|
||||
|
||||
d.annotatedHelp = d.help
|
||||
d.promDesc = nil
|
||||
}
|
||||
|
||||
func (d *Desc) markDeprecated() {
|
||||
d.deprecateOnce.Do(func() {
|
||||
d.annotatedHelp = fmt.Sprintf("(Deprecated since %s) %s", d.deprecatedVersion, d.annotatedHelp)
|
||||
})
|
||||
}
|
||||
|
||||
func (d *Desc) annotateStabilityLevel() {
|
||||
d.annotateOnce.Do(func() {
|
||||
d.annotatedHelp = fmt.Sprintf("[%v] %v", d.stabilityLevel, d.annotatedHelp)
|
||||
})
|
||||
}
|
||||
|
||||
func (d *Desc) initialize() {
|
||||
d.annotateStabilityLevel()
|
||||
|
||||
// this actually creates the underlying prometheus desc.
|
||||
d.promDesc = prometheus.NewDesc(d.fqName, d.annotatedHelp, d.variableLabels, prometheus.Labels(d.constLabels))
|
||||
}
|
||||
|
||||
func (d *Desc) initializeDeprecatedDesc() {
|
||||
d.markDeprecated()
|
||||
d.initialize()
|
||||
}
|
||||
|
||||
// GetRawDesc will returns a new *Desc with original parameters provided to NewDesc().
|
||||
//
|
||||
// It will be useful in testing scenario that the same Desc be registered to different registry.
|
||||
// 1. Desc `D` is registered to registry 'A' in TestA (Note: `D` maybe created)
|
||||
// 2. Desc `D` is registered to registry 'B' in TestB (Note: since 'D' has been created once, thus will be ignored by registry 'B')
|
||||
func (d *Desc) GetRawDesc() *Desc {
|
||||
return NewDesc(d.fqName, d.help, d.variableLabels, d.constLabels, d.stabilityLevel, d.deprecatedVersion)
|
||||
}
|
45
e2e/vendor/k8s.io/component-base/metrics/features/kube_features.go
generated
vendored
Normal file
45
e2e/vendor/k8s.io/component-base/metrics/features/kube_features.go
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright 2022 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package features
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
"k8s.io/component-base/featuregate"
|
||||
)
|
||||
|
||||
const (
|
||||
// owner: @logicalhan
|
||||
// kep: https://kep.k8s.io/3466
|
||||
ComponentSLIs featuregate.Feature = "ComponentSLIs"
|
||||
)
|
||||
|
||||
func featureGates() map[featuregate.Feature]featuregate.VersionedSpecs {
|
||||
return map[featuregate.Feature]featuregate.VersionedSpecs{
|
||||
ComponentSLIs: {
|
||||
{Version: version.MustParse("1.26"), Default: false, PreRelease: featuregate.Alpha},
|
||||
{Version: version.MustParse("1.27"), Default: true, PreRelease: featuregate.Beta},
|
||||
// ComponentSLIs officially graduated to GA in v1.29 but the gate was not updated until v1.32.
|
||||
// To support emulated versions, keep the gate until v1.35.
|
||||
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.GA, LockToDefault: true},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// AddFeatureGates adds all feature gates used by this package.
|
||||
func AddFeatureGates(mutableFeatureGate featuregate.MutableVersionedFeatureGate) error {
|
||||
return mutableFeatureGate.AddVersioned(featureGates())
|
||||
}
|
298
e2e/vendor/k8s.io/component-base/metrics/gauge.go
generated
vendored
Normal file
298
e2e/vendor/k8s.io/component-base/metrics/gauge.go
generated
vendored
Normal file
@ -0,0 +1,298 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
"k8s.io/component-base/version"
|
||||
)
|
||||
|
||||
// Gauge is our internal representation for our wrapping struct around prometheus
|
||||
// gauges. kubeGauge implements both kubeCollector and KubeGauge.
|
||||
type Gauge struct {
|
||||
GaugeMetric
|
||||
*GaugeOpts
|
||||
lazyMetric
|
||||
selfCollector
|
||||
}
|
||||
|
||||
var _ GaugeMetric = &Gauge{}
|
||||
var _ Registerable = &Gauge{}
|
||||
var _ kubeCollector = &Gauge{}
|
||||
|
||||
// NewGauge returns an object which satisfies the kubeCollector, Registerable, and Gauge interfaces.
|
||||
// However, the object returned will not measure anything unless the collector is first
|
||||
// registered, since the metric is lazily instantiated.
|
||||
func NewGauge(opts *GaugeOpts) *Gauge {
|
||||
opts.StabilityLevel.setDefaults()
|
||||
|
||||
kc := &Gauge{
|
||||
GaugeOpts: opts,
|
||||
lazyMetric: lazyMetric{stabilityLevel: opts.StabilityLevel},
|
||||
}
|
||||
kc.setPrometheusGauge(noop)
|
||||
kc.lazyInit(kc, BuildFQName(opts.Namespace, opts.Subsystem, opts.Name))
|
||||
return kc
|
||||
}
|
||||
|
||||
// setPrometheusGauge sets the underlying KubeGauge object, i.e. the thing that does the measurement.
|
||||
func (g *Gauge) setPrometheusGauge(gauge prometheus.Gauge) {
|
||||
g.GaugeMetric = gauge
|
||||
g.initSelfCollection(gauge)
|
||||
}
|
||||
|
||||
// DeprecatedVersion returns a pointer to the Version or nil
|
||||
func (g *Gauge) DeprecatedVersion() *semver.Version {
|
||||
return parseSemver(g.GaugeOpts.DeprecatedVersion)
|
||||
}
|
||||
|
||||
// initializeMetric invocation creates the actual underlying Gauge. Until this method is called
|
||||
// the underlying gauge is a no-op.
|
||||
func (g *Gauge) initializeMetric() {
|
||||
g.GaugeOpts.annotateStabilityLevel()
|
||||
// this actually creates the underlying prometheus gauge.
|
||||
g.setPrometheusGauge(prometheus.NewGauge(g.GaugeOpts.toPromGaugeOpts()))
|
||||
}
|
||||
|
||||
// initializeDeprecatedMetric invocation creates the actual (but deprecated) Gauge. Until this method
|
||||
// is called the underlying gauge is a no-op.
|
||||
func (g *Gauge) initializeDeprecatedMetric() {
|
||||
g.GaugeOpts.markDeprecated()
|
||||
g.initializeMetric()
|
||||
}
|
||||
|
||||
// WithContext allows the normal Gauge metric to pass in context. The context is no-op now.
|
||||
func (g *Gauge) WithContext(ctx context.Context) GaugeMetric {
|
||||
return g.GaugeMetric
|
||||
}
|
||||
|
||||
// GaugeVec is the internal representation of our wrapping struct around prometheus
|
||||
// gaugeVecs. kubeGaugeVec implements both kubeCollector and KubeGaugeVec.
|
||||
type GaugeVec struct {
|
||||
*prometheus.GaugeVec
|
||||
*GaugeOpts
|
||||
lazyMetric
|
||||
originalLabels []string
|
||||
}
|
||||
|
||||
var _ GaugeVecMetric = &GaugeVec{}
|
||||
var _ Registerable = &GaugeVec{}
|
||||
var _ kubeCollector = &GaugeVec{}
|
||||
|
||||
// NewGaugeVec returns an object which satisfies the kubeCollector, Registerable, and GaugeVecMetric interfaces.
|
||||
// However, the object returned will not measure anything unless the collector is first
|
||||
// registered, since the metric is lazily instantiated, and only members extracted after
|
||||
// registration will actually measure anything.
|
||||
func NewGaugeVec(opts *GaugeOpts, labels []string) *GaugeVec {
|
||||
opts.StabilityLevel.setDefaults()
|
||||
|
||||
fqName := BuildFQName(opts.Namespace, opts.Subsystem, opts.Name)
|
||||
|
||||
cv := &GaugeVec{
|
||||
GaugeVec: noopGaugeVec,
|
||||
GaugeOpts: opts,
|
||||
originalLabels: labels,
|
||||
lazyMetric: lazyMetric{stabilityLevel: opts.StabilityLevel},
|
||||
}
|
||||
cv.lazyInit(cv, fqName)
|
||||
return cv
|
||||
}
|
||||
|
||||
// DeprecatedVersion returns a pointer to the Version or nil
|
||||
func (v *GaugeVec) DeprecatedVersion() *semver.Version {
|
||||
return parseSemver(v.GaugeOpts.DeprecatedVersion)
|
||||
}
|
||||
|
||||
// initializeMetric invocation creates the actual underlying GaugeVec. Until this method is called
|
||||
// the underlying gaugeVec is a no-op.
|
||||
func (v *GaugeVec) initializeMetric() {
|
||||
v.GaugeOpts.annotateStabilityLevel()
|
||||
v.GaugeVec = prometheus.NewGaugeVec(v.GaugeOpts.toPromGaugeOpts(), v.originalLabels)
|
||||
}
|
||||
|
||||
// initializeDeprecatedMetric invocation creates the actual (but deprecated) GaugeVec. Until this method is called
|
||||
// the underlying gaugeVec is a no-op.
|
||||
func (v *GaugeVec) initializeDeprecatedMetric() {
|
||||
v.GaugeOpts.markDeprecated()
|
||||
v.initializeMetric()
|
||||
}
|
||||
|
||||
func (v *GaugeVec) WithLabelValuesChecked(lvs ...string) (GaugeMetric, error) {
|
||||
if !v.IsCreated() {
|
||||
if v.IsHidden() {
|
||||
return noop, nil
|
||||
}
|
||||
return noop, errNotRegistered // return no-op gauge
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
} else {
|
||||
v.initializeLabelAllowListsOnce.Do(func() {
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[v.FQName()]; ok {
|
||||
v.LabelValueAllowLists = allowList
|
||||
allowList.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
})
|
||||
}
|
||||
elt, err := v.GaugeVec.GetMetricWithLabelValues(lvs...)
|
||||
return elt, err
|
||||
}
|
||||
|
||||
// Default Prometheus Vec behavior is that member extraction results in creation of a new element
|
||||
// if one with the unique label values is not found in the underlying stored metricMap.
|
||||
// This means that if this function is called but the underlying metric is not registered
|
||||
// (which means it will never be exposed externally nor consumed), the metric will exist in memory
|
||||
// for perpetuity (i.e. throughout application lifecycle).
|
||||
//
|
||||
// For reference: https://github.com/prometheus/client_golang/blob/v0.9.2/prometheus/gauge.go#L190-L208
|
||||
//
|
||||
// In contrast, the Vec behavior in this package is that member extraction before registration
|
||||
// returns a permanent noop object.
|
||||
|
||||
// WithLabelValues returns the GaugeMetric for the given slice of label
|
||||
// values (same order as the VariableLabels in Desc). If that combination of
|
||||
// label values is accessed for the first time, a new GaugeMetric is created IFF the gaugeVec
|
||||
// has been registered to a metrics registry.
|
||||
func (v *GaugeVec) WithLabelValues(lvs ...string) GaugeMetric {
|
||||
ans, err := v.WithLabelValuesChecked(lvs...)
|
||||
if err == nil || ErrIsNotRegistered(err) {
|
||||
return ans
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
func (v *GaugeVec) WithChecked(labels map[string]string) (GaugeMetric, error) {
|
||||
if !v.IsCreated() {
|
||||
if v.IsHidden() {
|
||||
return noop, nil
|
||||
}
|
||||
return noop, errNotRegistered // return no-op gauge
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainLabelMap(labels)
|
||||
} else {
|
||||
v.initializeLabelAllowListsOnce.Do(func() {
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[v.FQName()]; ok {
|
||||
v.LabelValueAllowLists = allowList
|
||||
allowList.ConstrainLabelMap(labels)
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
})
|
||||
}
|
||||
elt, err := v.GaugeVec.GetMetricWith(labels)
|
||||
return elt, err
|
||||
}
|
||||
|
||||
// With returns the GaugeMetric for the given Labels map (the label names
|
||||
// must match those of the VariableLabels in Desc). If that label map is
|
||||
// accessed for the first time, a new GaugeMetric is created IFF the gaugeVec has
|
||||
// been registered to a metrics registry.
|
||||
func (v *GaugeVec) With(labels map[string]string) GaugeMetric {
|
||||
ans, err := v.WithChecked(labels)
|
||||
if err == nil || ErrIsNotRegistered(err) {
|
||||
return ans
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Delete deletes the metric where the variable labels are the same as those
|
||||
// passed in as labels. It returns true if a metric was deleted.
|
||||
//
|
||||
// It is not an error if the number and names of the Labels are inconsistent
|
||||
// with those of the VariableLabels in Desc. However, such inconsistent Labels
|
||||
// can never match an actual metric, so the method will always return false in
|
||||
// that case.
|
||||
func (v *GaugeVec) Delete(labels map[string]string) bool {
|
||||
if !v.IsCreated() {
|
||||
return false // since we haven't created the metric, we haven't deleted a metric with the passed in values
|
||||
}
|
||||
return v.GaugeVec.Delete(labels)
|
||||
}
|
||||
|
||||
// Reset deletes all metrics in this vector.
|
||||
func (v *GaugeVec) Reset() {
|
||||
if !v.IsCreated() {
|
||||
return
|
||||
}
|
||||
|
||||
v.GaugeVec.Reset()
|
||||
}
|
||||
|
||||
// ResetLabelAllowLists resets the label allow list for the GaugeVec.
|
||||
// NOTE: This should only be used in test.
|
||||
func (v *GaugeVec) ResetLabelAllowLists() {
|
||||
v.initializeLabelAllowListsOnce = sync.Once{}
|
||||
v.LabelValueAllowLists = nil
|
||||
}
|
||||
|
||||
func newGaugeFunc(opts *GaugeOpts, function func() float64, v semver.Version) GaugeFunc {
|
||||
g := NewGauge(opts)
|
||||
|
||||
if !g.Create(&v) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return prometheus.NewGaugeFunc(g.GaugeOpts.toPromGaugeOpts(), function)
|
||||
}
|
||||
|
||||
// NewGaugeFunc creates a new GaugeFunc based on the provided GaugeOpts. The
|
||||
// value reported is determined by calling the given function from within the
|
||||
// Write method. Take into account that metric collection may happen
|
||||
// concurrently. If that results in concurrent calls to Write, like in the case
|
||||
// where a GaugeFunc is directly registered with Prometheus, the provided
|
||||
// function must be concurrency-safe.
|
||||
func NewGaugeFunc(opts *GaugeOpts, function func() float64) GaugeFunc {
|
||||
v := parseVersion(version.Get())
|
||||
|
||||
return newGaugeFunc(opts, function, v)
|
||||
}
|
||||
|
||||
// WithContext returns wrapped GaugeVec with context
|
||||
func (v *GaugeVec) WithContext(ctx context.Context) *GaugeVecWithContext {
|
||||
return &GaugeVecWithContext{
|
||||
ctx: ctx,
|
||||
GaugeVec: v,
|
||||
}
|
||||
}
|
||||
|
||||
func (v *GaugeVec) InterfaceWithContext(ctx context.Context) GaugeVecMetric {
|
||||
return v.WithContext(ctx)
|
||||
}
|
||||
|
||||
// GaugeVecWithContext is the wrapper of GaugeVec with context.
|
||||
type GaugeVecWithContext struct {
|
||||
*GaugeVec
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
// WithLabelValues is the wrapper of GaugeVec.WithLabelValues.
|
||||
func (vc *GaugeVecWithContext) WithLabelValues(lvs ...string) GaugeMetric {
|
||||
return vc.GaugeVec.WithLabelValues(lvs...)
|
||||
}
|
||||
|
||||
// With is the wrapper of GaugeVec.With.
|
||||
func (vc *GaugeVecWithContext) With(labels map[string]string) GaugeMetric {
|
||||
return vc.GaugeVec.With(labels)
|
||||
}
|
299
e2e/vendor/k8s.io/component-base/metrics/histogram.go
generated
vendored
Normal file
299
e2e/vendor/k8s.io/component-base/metrics/histogram.go
generated
vendored
Normal file
@ -0,0 +1,299 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// Histogram is our internal representation for our wrapping struct around prometheus
|
||||
// histograms. Summary implements both kubeCollector and ObserverMetric
|
||||
type Histogram struct {
|
||||
ctx context.Context
|
||||
ObserverMetric
|
||||
*HistogramOpts
|
||||
lazyMetric
|
||||
selfCollector
|
||||
}
|
||||
|
||||
// exemplarHistogramMetric holds a context to extract exemplar labels from, and a historgram metric to attach them to. It implements the metricWithExemplar interface.
|
||||
type exemplarHistogramMetric struct {
|
||||
*Histogram
|
||||
}
|
||||
|
||||
type exemplarHistogramVec struct {
|
||||
*HistogramVecWithContext
|
||||
observer prometheus.Observer
|
||||
}
|
||||
|
||||
func (h *Histogram) Observe(v float64) {
|
||||
h.withExemplar(v)
|
||||
}
|
||||
|
||||
// withExemplar initializes the exemplarMetric object and sets the exemplar value.
|
||||
func (h *Histogram) withExemplar(v float64) {
|
||||
(&exemplarHistogramMetric{h}).withExemplar(v)
|
||||
}
|
||||
|
||||
// withExemplar attaches an exemplar to the metric.
|
||||
func (e *exemplarHistogramMetric) withExemplar(v float64) {
|
||||
if m, ok := e.Histogram.ObserverMetric.(prometheus.ExemplarObserver); ok {
|
||||
maybeSpanCtx := trace.SpanContextFromContext(e.ctx)
|
||||
if maybeSpanCtx.IsValid() && maybeSpanCtx.IsSampled() {
|
||||
exemplarLabels := prometheus.Labels{
|
||||
"trace_id": maybeSpanCtx.TraceID().String(),
|
||||
"span_id": maybeSpanCtx.SpanID().String(),
|
||||
}
|
||||
m.ObserveWithExemplar(v, exemplarLabels)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
e.ObserverMetric.Observe(v)
|
||||
}
|
||||
|
||||
// NewHistogram returns an object which is Histogram-like. However, nothing
|
||||
// will be measured until the histogram is registered somewhere.
|
||||
func NewHistogram(opts *HistogramOpts) *Histogram {
|
||||
opts.StabilityLevel.setDefaults()
|
||||
|
||||
h := &Histogram{
|
||||
HistogramOpts: opts,
|
||||
lazyMetric: lazyMetric{stabilityLevel: opts.StabilityLevel},
|
||||
}
|
||||
h.setPrometheusHistogram(noopMetric{})
|
||||
h.lazyInit(h, BuildFQName(opts.Namespace, opts.Subsystem, opts.Name))
|
||||
return h
|
||||
}
|
||||
|
||||
// setPrometheusHistogram sets the underlying KubeGauge object, i.e. the thing that does the measurement.
|
||||
func (h *Histogram) setPrometheusHistogram(histogram prometheus.Histogram) {
|
||||
h.ObserverMetric = histogram
|
||||
h.initSelfCollection(histogram)
|
||||
}
|
||||
|
||||
// DeprecatedVersion returns a pointer to the Version or nil
|
||||
func (h *Histogram) DeprecatedVersion() *semver.Version {
|
||||
return parseSemver(h.HistogramOpts.DeprecatedVersion)
|
||||
}
|
||||
|
||||
// initializeMetric invokes the actual prometheus.Histogram object instantiation
|
||||
// and stores a reference to it
|
||||
func (h *Histogram) initializeMetric() {
|
||||
h.HistogramOpts.annotateStabilityLevel()
|
||||
// this actually creates the underlying prometheus gauge.
|
||||
h.setPrometheusHistogram(prometheus.NewHistogram(h.HistogramOpts.toPromHistogramOpts()))
|
||||
}
|
||||
|
||||
// initializeDeprecatedMetric invokes the actual prometheus.Histogram object instantiation
|
||||
// but modifies the Help description prior to object instantiation.
|
||||
func (h *Histogram) initializeDeprecatedMetric() {
|
||||
h.HistogramOpts.markDeprecated()
|
||||
h.initializeMetric()
|
||||
}
|
||||
|
||||
// WithContext allows the normal Histogram metric to pass in context. The context is no-op now.
|
||||
func (h *Histogram) WithContext(ctx context.Context) ObserverMetric {
|
||||
h.ctx = ctx
|
||||
return h.ObserverMetric
|
||||
}
|
||||
|
||||
// HistogramVec is the internal representation of our wrapping struct around prometheus
|
||||
// histogramVecs.
|
||||
type HistogramVec struct {
|
||||
*prometheus.HistogramVec
|
||||
*HistogramOpts
|
||||
lazyMetric
|
||||
originalLabels []string
|
||||
}
|
||||
|
||||
// NewHistogramVec returns an object which satisfies kubeCollector and wraps the
|
||||
// prometheus.HistogramVec object. However, the object returned will not measure
|
||||
// anything unless the collector is first registered, since the metric is lazily instantiated,
|
||||
// and only members extracted after
|
||||
// registration will actually measure anything.
|
||||
|
||||
func NewHistogramVec(opts *HistogramOpts, labels []string) *HistogramVec {
|
||||
opts.StabilityLevel.setDefaults()
|
||||
|
||||
fqName := BuildFQName(opts.Namespace, opts.Subsystem, opts.Name)
|
||||
|
||||
v := &HistogramVec{
|
||||
HistogramVec: noopHistogramVec,
|
||||
HistogramOpts: opts,
|
||||
originalLabels: labels,
|
||||
lazyMetric: lazyMetric{stabilityLevel: opts.StabilityLevel},
|
||||
}
|
||||
v.lazyInit(v, fqName)
|
||||
return v
|
||||
}
|
||||
|
||||
// DeprecatedVersion returns a pointer to the Version or nil
|
||||
func (v *HistogramVec) DeprecatedVersion() *semver.Version {
|
||||
return parseSemver(v.HistogramOpts.DeprecatedVersion)
|
||||
}
|
||||
|
||||
func (v *HistogramVec) initializeMetric() {
|
||||
v.HistogramOpts.annotateStabilityLevel()
|
||||
v.HistogramVec = prometheus.NewHistogramVec(v.HistogramOpts.toPromHistogramOpts(), v.originalLabels)
|
||||
}
|
||||
|
||||
func (v *HistogramVec) initializeDeprecatedMetric() {
|
||||
v.HistogramOpts.markDeprecated()
|
||||
v.initializeMetric()
|
||||
}
|
||||
|
||||
// Default Prometheus Vec behavior is that member extraction results in creation of a new element
|
||||
// if one with the unique label values is not found in the underlying stored metricMap.
|
||||
// This means that if this function is called but the underlying metric is not registered
|
||||
// (which means it will never be exposed externally nor consumed), the metric will exist in memory
|
||||
// for perpetuity (i.e. throughout application lifecycle).
|
||||
//
|
||||
// For reference: https://github.com/prometheus/client_golang/blob/v0.9.2/prometheus/histogram.go#L460-L470
|
||||
//
|
||||
// In contrast, the Vec behavior in this package is that member extraction before registration
|
||||
// returns a permanent noop object.
|
||||
|
||||
// WithLabelValues returns the ObserverMetric for the given slice of label
|
||||
// values (same order as the VariableLabels in Desc). If that combination of
|
||||
// label values is accessed for the first time, a new ObserverMetric is created IFF the HistogramVec
|
||||
// has been registered to a metrics registry.
|
||||
func (v *HistogramVec) WithLabelValues(lvs ...string) ObserverMetric {
|
||||
if !v.IsCreated() {
|
||||
return noop
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
} else {
|
||||
v.initializeLabelAllowListsOnce.Do(func() {
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[v.FQName()]; ok {
|
||||
v.LabelValueAllowLists = allowList
|
||||
allowList.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
})
|
||||
}
|
||||
return v.HistogramVec.WithLabelValues(lvs...)
|
||||
}
|
||||
|
||||
// With returns the ObserverMetric for the given Labels map (the label names
|
||||
// must match those of the VariableLabels in Desc). If that label map is
|
||||
// accessed for the first time, a new ObserverMetric is created IFF the HistogramVec has
|
||||
// been registered to a metrics registry.
|
||||
func (v *HistogramVec) With(labels map[string]string) ObserverMetric {
|
||||
if !v.IsCreated() {
|
||||
return noop
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainLabelMap(labels)
|
||||
} else {
|
||||
v.initializeLabelAllowListsOnce.Do(func() {
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[v.FQName()]; ok {
|
||||
v.LabelValueAllowLists = allowList
|
||||
allowList.ConstrainLabelMap(labels)
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
})
|
||||
}
|
||||
return v.HistogramVec.With(labels)
|
||||
}
|
||||
|
||||
// Delete deletes the metric where the variable labels are the same as those
|
||||
// passed in as labels. It returns true if a metric was deleted.
|
||||
//
|
||||
// It is not an error if the number and names of the Labels are inconsistent
|
||||
// with those of the VariableLabels in Desc. However, such inconsistent Labels
|
||||
// can never match an actual metric, so the method will always return false in
|
||||
// that case.
|
||||
func (v *HistogramVec) Delete(labels map[string]string) bool {
|
||||
if !v.IsCreated() {
|
||||
return false // since we haven't created the metric, we haven't deleted a metric with the passed in values
|
||||
}
|
||||
return v.HistogramVec.Delete(labels)
|
||||
}
|
||||
|
||||
// Reset deletes all metrics in this vector.
|
||||
func (v *HistogramVec) Reset() {
|
||||
if !v.IsCreated() {
|
||||
return
|
||||
}
|
||||
|
||||
v.HistogramVec.Reset()
|
||||
}
|
||||
|
||||
// ResetLabelAllowLists resets the label allow list for the HistogramVec.
|
||||
// NOTE: This should only be used in test.
|
||||
func (v *HistogramVec) ResetLabelAllowLists() {
|
||||
v.initializeLabelAllowListsOnce = sync.Once{}
|
||||
v.LabelValueAllowLists = nil
|
||||
}
|
||||
|
||||
// WithContext returns wrapped HistogramVec with context
|
||||
func (v *HistogramVec) WithContext(ctx context.Context) *HistogramVecWithContext {
|
||||
return &HistogramVecWithContext{
|
||||
ctx: ctx,
|
||||
HistogramVec: v,
|
||||
}
|
||||
}
|
||||
|
||||
// HistogramVecWithContext is the wrapper of HistogramVec with context.
|
||||
type HistogramVecWithContext struct {
|
||||
*HistogramVec
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func (h *exemplarHistogramVec) Observe(v float64) {
|
||||
h.withExemplar(v)
|
||||
}
|
||||
|
||||
func (h *exemplarHistogramVec) withExemplar(v float64) {
|
||||
if m, ok := h.observer.(prometheus.ExemplarObserver); ok {
|
||||
maybeSpanCtx := trace.SpanContextFromContext(h.HistogramVecWithContext.ctx)
|
||||
if maybeSpanCtx.IsValid() && maybeSpanCtx.IsSampled() {
|
||||
m.ObserveWithExemplar(v, prometheus.Labels{
|
||||
"trace_id": maybeSpanCtx.TraceID().String(),
|
||||
"span_id": maybeSpanCtx.SpanID().String(),
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
h.observer.Observe(v)
|
||||
}
|
||||
|
||||
// WithLabelValues is the wrapper of HistogramVec.WithLabelValues.
|
||||
func (vc *HistogramVecWithContext) WithLabelValues(lvs ...string) *exemplarHistogramVec {
|
||||
return &exemplarHistogramVec{
|
||||
HistogramVecWithContext: vc,
|
||||
observer: vc.HistogramVec.WithLabelValues(lvs...),
|
||||
}
|
||||
}
|
||||
|
||||
// With is the wrapper of HistogramVec.With.
|
||||
func (vc *HistogramVecWithContext) With(labels map[string]string) *exemplarHistogramVec {
|
||||
return &exemplarHistogramVec{
|
||||
HistogramVecWithContext: vc,
|
||||
observer: vc.HistogramVec.With(labels),
|
||||
}
|
||||
}
|
87
e2e/vendor/k8s.io/component-base/metrics/http.go
generated
vendored
Normal file
87
e2e/vendor/k8s.io/component-base/metrics/http.go
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
var (
|
||||
processStartedAt time.Time
|
||||
)
|
||||
|
||||
func init() {
|
||||
processStartedAt = time.Now()
|
||||
}
|
||||
|
||||
// These constants cause handlers serving metrics to behave as described if
|
||||
// errors are encountered.
|
||||
const (
|
||||
// HTTPErrorOnError serve an HTTP status code 500 upon the first error
|
||||
// encountered. Report the error message in the body.
|
||||
HTTPErrorOnError promhttp.HandlerErrorHandling = iota
|
||||
|
||||
// ContinueOnError ignore errors and try to serve as many metrics as possible.
|
||||
// However, if no metrics can be served, serve an HTTP status code 500 and the
|
||||
// last error message in the body. Only use this in deliberate "best
|
||||
// effort" metrics collection scenarios. In this case, it is highly
|
||||
// recommended to provide other means of detecting errors: By setting an
|
||||
// ErrorLog in HandlerOpts, the errors are logged. By providing a
|
||||
// Registry in HandlerOpts, the exposed metrics include an error counter
|
||||
// "promhttp_metric_handler_errors_total", which can be used for
|
||||
// alerts.
|
||||
ContinueOnError
|
||||
|
||||
// PanicOnError panics upon the first error encountered (useful for "crash only" apps).
|
||||
PanicOnError
|
||||
)
|
||||
|
||||
// HandlerOpts specifies options how to serve metrics via an http.Handler. The
|
||||
// zero value of HandlerOpts is a reasonable default.
|
||||
type HandlerOpts promhttp.HandlerOpts
|
||||
|
||||
func (ho *HandlerOpts) toPromhttpHandlerOpts() promhttp.HandlerOpts {
|
||||
ho.ProcessStartTime = processStartedAt
|
||||
return promhttp.HandlerOpts(*ho)
|
||||
}
|
||||
|
||||
// HandlerFor returns an uninstrumented http.Handler for the provided
|
||||
// Gatherer. The behavior of the Handler is defined by the provided
|
||||
// HandlerOpts. Thus, HandlerFor is useful to create http.Handlers for custom
|
||||
// Gatherers, with non-default HandlerOpts, and/or with custom (or no)
|
||||
// instrumentation. Use the InstrumentMetricHandler function to apply the same
|
||||
// kind of instrumentation as it is used by the Handler function.
|
||||
func HandlerFor(reg Gatherer, opts HandlerOpts) http.Handler {
|
||||
return promhttp.HandlerFor(reg, opts.toPromhttpHandlerOpts())
|
||||
}
|
||||
|
||||
// HandlerWithReset return an http.Handler with Reset
|
||||
func HandlerWithReset(reg KubeRegistry, opts HandlerOpts) http.Handler {
|
||||
defaultHandler := promhttp.HandlerFor(reg, opts.toPromhttpHandlerOpts())
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodDelete {
|
||||
reg.Reset()
|
||||
io.WriteString(w, "metrics reset\n")
|
||||
return
|
||||
}
|
||||
defaultHandler.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
22
e2e/vendor/k8s.io/component-base/metrics/labels.go
generated
vendored
Normal file
22
e2e/vendor/k8s.io/component-base/metrics/labels.go
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import "github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
// Labels represents a collection of label name -> value mappings.
|
||||
type Labels prometheus.Labels
|
92
e2e/vendor/k8s.io/component-base/metrics/legacyregistry/registry.go
generated
vendored
Normal file
92
e2e/vendor/k8s.io/component-base/metrics/legacyregistry/registry.go
generated
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package legacyregistry
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/collectors"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
|
||||
"k8s.io/component-base/metrics"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultRegistry = metrics.NewKubeRegistry()
|
||||
// DefaultGatherer exposes the global registry gatherer
|
||||
DefaultGatherer metrics.Gatherer = defaultRegistry
|
||||
// Reset calls reset on the global registry
|
||||
Reset = defaultRegistry.Reset
|
||||
// MustRegister registers registerable metrics but uses the global registry.
|
||||
MustRegister = defaultRegistry.MustRegister
|
||||
// RawMustRegister registers prometheus collectors but uses the global registry, this
|
||||
// bypasses the metric stability framework
|
||||
//
|
||||
// Deprecated
|
||||
RawMustRegister = defaultRegistry.RawMustRegister
|
||||
|
||||
// Register registers a collectable metric but uses the global registry
|
||||
Register = defaultRegistry.Register
|
||||
|
||||
// Registerer exposes the global registerer
|
||||
Registerer = defaultRegistry.Registerer
|
||||
|
||||
processStart time.Time
|
||||
)
|
||||
|
||||
func init() {
|
||||
RawMustRegister(collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}))
|
||||
RawMustRegister(collectors.NewGoCollector(collectors.WithGoCollectorRuntimeMetrics(collectors.MetricsAll)))
|
||||
defaultRegistry.RegisterMetaMetrics()
|
||||
processStart = time.Now()
|
||||
}
|
||||
|
||||
// Handler returns an HTTP handler for the DefaultGatherer. It is
|
||||
// already instrumented with InstrumentHandler (using "prometheus" as handler
|
||||
// name).
|
||||
func Handler() http.Handler {
|
||||
return promhttp.InstrumentMetricHandler(prometheus.DefaultRegisterer, promhttp.HandlerFor(defaultRegistry, promhttp.HandlerOpts{ProcessStartTime: processStart}))
|
||||
}
|
||||
|
||||
// HandlerWithReset returns an HTTP handler for the DefaultGatherer but invokes
|
||||
// registry reset if the http method is DELETE.
|
||||
func HandlerWithReset() http.Handler {
|
||||
return promhttp.InstrumentMetricHandler(
|
||||
prometheus.DefaultRegisterer,
|
||||
metrics.HandlerWithReset(defaultRegistry, metrics.HandlerOpts{ProcessStartTime: processStart}))
|
||||
}
|
||||
|
||||
// CustomRegister registers a custom collector but uses the global registry.
|
||||
func CustomRegister(c metrics.StableCollector) error {
|
||||
err := defaultRegistry.CustomRegister(c)
|
||||
|
||||
//TODO(RainbowMango): Maybe we can wrap this error by error wrapping.(Golang 1.13)
|
||||
_ = prometheus.Register(c)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// CustomMustRegister registers custom collectors but uses the global registry.
|
||||
func CustomMustRegister(cs ...metrics.StableCollector) {
|
||||
defaultRegistry.CustomMustRegister(cs...)
|
||||
|
||||
for _, c := range cs {
|
||||
prometheus.MustRegister(c)
|
||||
}
|
||||
}
|
240
e2e/vendor/k8s.io/component-base/metrics/metric.go
generated
vendored
Normal file
240
e2e/vendor/k8s.io/component-base/metrics/metric.go
generated
vendored
Normal file
@ -0,0 +1,240 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
|
||||
promext "k8s.io/component-base/metrics/prometheusextension"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
/*
|
||||
kubeCollector extends the prometheus.Collector interface to allow customization of the metric
|
||||
registration process. Defer metric initialization until Create() is called, which then
|
||||
delegates to the underlying metric's initializeMetric or initializeDeprecatedMetric
|
||||
method call depending on whether the metric is deprecated or not.
|
||||
*/
|
||||
type kubeCollector interface {
|
||||
Collector
|
||||
lazyKubeMetric
|
||||
DeprecatedVersion() *semver.Version
|
||||
// Each collector metric should provide an initialization function
|
||||
// for both deprecated and non-deprecated variants of a metric. This
|
||||
// is necessary since metric instantiation will be deferred
|
||||
// until the metric is actually registered somewhere.
|
||||
initializeMetric()
|
||||
initializeDeprecatedMetric()
|
||||
}
|
||||
|
||||
/*
|
||||
lazyKubeMetric defines our metric registration interface. lazyKubeMetric objects are expected
|
||||
to lazily instantiate metrics (i.e defer metric instantiation until when
|
||||
the Create() function is explicitly called).
|
||||
*/
|
||||
type lazyKubeMetric interface {
|
||||
Create(*semver.Version) bool
|
||||
IsCreated() bool
|
||||
IsHidden() bool
|
||||
IsDeprecated() bool
|
||||
}
|
||||
|
||||
/*
|
||||
lazyMetric implements lazyKubeMetric. A lazy metric is lazy because it waits until metric
|
||||
registration time before instantiation. Add it as an anonymous field to a struct that
|
||||
implements kubeCollector to get deferred registration behavior. You must call lazyInit
|
||||
with the kubeCollector itself as an argument.
|
||||
*/
|
||||
type lazyMetric struct {
|
||||
fqName string
|
||||
isDeprecated bool
|
||||
isHidden bool
|
||||
isCreated bool
|
||||
createLock sync.RWMutex
|
||||
markDeprecationOnce sync.Once
|
||||
createOnce sync.Once
|
||||
self kubeCollector
|
||||
stabilityLevel StabilityLevel
|
||||
}
|
||||
|
||||
func (r *lazyMetric) IsCreated() bool {
|
||||
r.createLock.RLock()
|
||||
defer r.createLock.RUnlock()
|
||||
return r.isCreated
|
||||
}
|
||||
|
||||
// lazyInit provides the lazyMetric with a reference to the kubeCollector it is supposed
|
||||
// to allow lazy initialization for. It should be invoked in the factory function which creates new
|
||||
// kubeCollector type objects.
|
||||
func (r *lazyMetric) lazyInit(self kubeCollector, fqName string) {
|
||||
r.fqName = fqName
|
||||
r.self = self
|
||||
}
|
||||
|
||||
// preprocessMetric figures out whether the lazy metric should be hidden or not.
|
||||
// This method takes a Version argument which should be the version of the binary in which
|
||||
// this code is currently being executed. A metric can be hidden under two conditions:
|
||||
// 1. if the metric is deprecated and is outside the grace period (i.e. has been
|
||||
// deprecated for more than one release
|
||||
// 2. if the metric is manually disabled via a CLI flag.
|
||||
//
|
||||
// Disclaimer: disabling a metric via a CLI flag has higher precedence than
|
||||
// deprecation and will override show-hidden-metrics for the explicitly
|
||||
// disabled metric.
|
||||
func (r *lazyMetric) preprocessMetric(version semver.Version) {
|
||||
disabledMetricsLock.RLock()
|
||||
defer disabledMetricsLock.RUnlock()
|
||||
// disabling metrics is higher in precedence than showing hidden metrics
|
||||
if _, ok := disabledMetrics[r.fqName]; ok {
|
||||
r.isHidden = true
|
||||
return
|
||||
}
|
||||
selfVersion := r.self.DeprecatedVersion()
|
||||
if selfVersion == nil {
|
||||
return
|
||||
}
|
||||
r.markDeprecationOnce.Do(func() {
|
||||
if selfVersion.LTE(version) {
|
||||
r.isDeprecated = true
|
||||
}
|
||||
|
||||
if ShouldShowHidden() {
|
||||
klog.Warningf("Hidden metrics (%s) have been manually overridden, showing this very deprecated metric.", r.fqName)
|
||||
return
|
||||
}
|
||||
if shouldHide(&version, selfVersion) {
|
||||
// TODO(RainbowMango): Remove this log temporarily. https://github.com/kubernetes/kubernetes/issues/85369
|
||||
// klog.Warningf("This metric has been deprecated for more than one release, hiding.")
|
||||
r.isHidden = true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (r *lazyMetric) IsHidden() bool {
|
||||
return r.isHidden
|
||||
}
|
||||
|
||||
func (r *lazyMetric) IsDeprecated() bool {
|
||||
return r.isDeprecated
|
||||
}
|
||||
|
||||
// Create forces the initialization of metric which has been deferred until
|
||||
// the point at which this method is invoked. This method will determine whether
|
||||
// the metric is deprecated or hidden, no-opting if the metric should be considered
|
||||
// hidden. Furthermore, this function no-opts and returns true if metric is already
|
||||
// created.
|
||||
func (r *lazyMetric) Create(version *semver.Version) bool {
|
||||
if version != nil {
|
||||
r.preprocessMetric(*version)
|
||||
}
|
||||
// let's not create if this metric is slated to be hidden
|
||||
if r.IsHidden() {
|
||||
return false
|
||||
}
|
||||
|
||||
r.createOnce.Do(func() {
|
||||
r.createLock.Lock()
|
||||
defer r.createLock.Unlock()
|
||||
r.isCreated = true
|
||||
if r.IsDeprecated() {
|
||||
r.self.initializeDeprecatedMetric()
|
||||
} else {
|
||||
r.self.initializeMetric()
|
||||
}
|
||||
})
|
||||
sl := r.stabilityLevel
|
||||
deprecatedV := r.self.DeprecatedVersion()
|
||||
dv := ""
|
||||
if deprecatedV != nil {
|
||||
dv = deprecatedV.String()
|
||||
}
|
||||
registeredMetricsTotal.WithLabelValues(string(sl), dv).Inc()
|
||||
return r.IsCreated()
|
||||
}
|
||||
|
||||
// ClearState will clear all the states marked by Create.
|
||||
// It intends to be used for re-register a hidden metric.
|
||||
func (r *lazyMetric) ClearState() {
|
||||
r.createLock.Lock()
|
||||
defer r.createLock.Unlock()
|
||||
|
||||
r.isDeprecated = false
|
||||
r.isHidden = false
|
||||
r.isCreated = false
|
||||
r.markDeprecationOnce = sync.Once{}
|
||||
r.createOnce = sync.Once{}
|
||||
}
|
||||
|
||||
// FQName returns the fully-qualified metric name of the collector.
|
||||
func (r *lazyMetric) FQName() string {
|
||||
return r.fqName
|
||||
}
|
||||
|
||||
/*
|
||||
This code is directly lifted from the prometheus codebase. It's a convenience struct which
|
||||
allows you satisfy the Collector interface automatically if you already satisfy the Metric interface.
|
||||
|
||||
For reference: https://github.com/prometheus/client_golang/blob/v0.9.2/prometheus/collector.go#L98-L120
|
||||
*/
|
||||
type selfCollector struct {
|
||||
metric prometheus.Metric
|
||||
}
|
||||
|
||||
func (c *selfCollector) initSelfCollection(m prometheus.Metric) {
|
||||
c.metric = m
|
||||
}
|
||||
|
||||
func (c *selfCollector) Describe(ch chan<- *prometheus.Desc) {
|
||||
ch <- c.metric.Desc()
|
||||
}
|
||||
|
||||
func (c *selfCollector) Collect(ch chan<- prometheus.Metric) {
|
||||
ch <- c.metric
|
||||
}
|
||||
|
||||
// metricWithExemplar is an interface that knows how to attach an exemplar to certain supported metric types.
|
||||
type metricWithExemplar interface {
|
||||
withExemplar(v float64)
|
||||
}
|
||||
|
||||
// no-op vecs for convenience
|
||||
var noopCounterVec = &prometheus.CounterVec{}
|
||||
var noopHistogramVec = &prometheus.HistogramVec{}
|
||||
var noopTimingHistogramVec = &promext.TimingHistogramVec{}
|
||||
var noopGaugeVec = &prometheus.GaugeVec{}
|
||||
|
||||
// just use a convenience struct for all the no-ops
|
||||
var noop = &noopMetric{}
|
||||
|
||||
type noopMetric struct{}
|
||||
|
||||
func (noopMetric) Inc() {}
|
||||
func (noopMetric) Add(float64) {}
|
||||
func (noopMetric) Dec() {}
|
||||
func (noopMetric) Set(float64) {}
|
||||
func (noopMetric) Sub(float64) {}
|
||||
func (noopMetric) Observe(float64) {}
|
||||
func (noopMetric) ObserveWithWeight(float64, uint64) {}
|
||||
func (noopMetric) SetToCurrentTime() {}
|
||||
func (noopMetric) Desc() *prometheus.Desc { return nil }
|
||||
func (noopMetric) Write(*dto.Metric) error { return nil }
|
||||
func (noopMetric) Describe(chan<- *prometheus.Desc) {}
|
||||
func (noopMetric) Collect(chan<- prometheus.Metric) {}
|
136
e2e/vendor/k8s.io/component-base/metrics/options.go
generated
vendored
Normal file
136
e2e/vendor/k8s.io/component-base/metrics/options.go
generated
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"k8s.io/component-base/version"
|
||||
)
|
||||
|
||||
// Options has all parameters needed for exposing metrics from components
|
||||
type Options struct {
|
||||
ShowHiddenMetricsForVersion string
|
||||
DisabledMetrics []string
|
||||
AllowListMapping map[string]string
|
||||
AllowListMappingManifest string
|
||||
}
|
||||
|
||||
// NewOptions returns default metrics options
|
||||
func NewOptions() *Options {
|
||||
return &Options{}
|
||||
}
|
||||
|
||||
// Validate validates metrics flags options.
|
||||
func (o *Options) Validate() []error {
|
||||
if o == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var errs []error
|
||||
err := validateShowHiddenMetricsVersion(parseVersion(version.Get()), o.ShowHiddenMetricsForVersion)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
||||
if err := validateAllowMetricLabel(o.AllowListMapping); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
||||
if len(errs) == 0 {
|
||||
return nil
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
// AddFlags adds flags for exposing component metrics.
|
||||
func (o *Options) AddFlags(fs *pflag.FlagSet) {
|
||||
if o == nil {
|
||||
return
|
||||
}
|
||||
fs.StringVar(&o.ShowHiddenMetricsForVersion, "show-hidden-metrics-for-version", o.ShowHiddenMetricsForVersion,
|
||||
"The previous version for which you want to show hidden metrics. "+
|
||||
"Only the previous minor version is meaningful, other values will not be allowed. "+
|
||||
"The format is <major>.<minor>, e.g.: '1.16'. "+
|
||||
"The purpose of this format is make sure you have the opportunity to notice if the next release hides additional metrics, "+
|
||||
"rather than being surprised when they are permanently removed in the release after that.")
|
||||
fs.StringSliceVar(&o.DisabledMetrics,
|
||||
"disabled-metrics",
|
||||
o.DisabledMetrics,
|
||||
"This flag provides an escape hatch for misbehaving metrics. "+
|
||||
"You must provide the fully qualified metric name in order to disable it. "+
|
||||
"Disclaimer: disabling metrics is higher in precedence than showing hidden metrics.")
|
||||
fs.StringToStringVar(&o.AllowListMapping, "allow-metric-labels", o.AllowListMapping,
|
||||
"The map from metric-label to value allow-list of this label. The key's format is <MetricName>,<LabelName>. "+
|
||||
"The value's format is <allowed_value>,<allowed_value>..."+
|
||||
"e.g. metric1,label1='v1,v2,v3', metric1,label2='v1,v2,v3' metric2,label1='v1,v2,v3'.")
|
||||
fs.StringVar(&o.AllowListMappingManifest, "allow-metric-labels-manifest", o.AllowListMappingManifest,
|
||||
"The path to the manifest file that contains the allow-list mapping. "+
|
||||
"The format of the file is the same as the flag --allow-metric-labels. "+
|
||||
"Note that the flag --allow-metric-labels will override the manifest file.")
|
||||
}
|
||||
|
||||
// Apply applies parameters into global configuration of metrics.
|
||||
func (o *Options) Apply() {
|
||||
if o == nil {
|
||||
return
|
||||
}
|
||||
if len(o.ShowHiddenMetricsForVersion) > 0 {
|
||||
SetShowHidden()
|
||||
}
|
||||
// set disabled metrics
|
||||
for _, metricName := range o.DisabledMetrics {
|
||||
SetDisabledMetric(metricName)
|
||||
}
|
||||
if o.AllowListMapping != nil {
|
||||
SetLabelAllowListFromCLI(o.AllowListMapping)
|
||||
} else if len(o.AllowListMappingManifest) > 0 {
|
||||
SetLabelAllowListFromManifest(o.AllowListMappingManifest)
|
||||
}
|
||||
}
|
||||
|
||||
func validateShowHiddenMetricsVersion(currentVersion semver.Version, targetVersionStr string) error {
|
||||
if targetVersionStr == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
validVersionStr := fmt.Sprintf("%d.%d", currentVersion.Major, currentVersion.Minor-1)
|
||||
if targetVersionStr != validVersionStr {
|
||||
return fmt.Errorf("--show-hidden-metrics-for-version must be omitted or have the value '%v'. Only the previous minor version is allowed", validVersionStr)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateAllowMetricLabel(allowListMapping map[string]string) error {
|
||||
if allowListMapping == nil {
|
||||
return nil
|
||||
}
|
||||
metricNameRegex := `[a-zA-Z_:][a-zA-Z0-9_:]*`
|
||||
labelRegex := `[a-zA-Z_][a-zA-Z0-9_]*`
|
||||
for k := range allowListMapping {
|
||||
reg := regexp.MustCompile(metricNameRegex + `,` + labelRegex)
|
||||
if reg.FindString(k) != k {
|
||||
return fmt.Errorf("--allow-metric-labels must have a list of kv pair with format `metricName,labelName=labelValue, labelValue,...`")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
390
e2e/vendor/k8s.io/component-base/metrics/opts.go
generated
vendored
Normal file
390
e2e/vendor/k8s.io/component-base/metrics/opts.go
generated
vendored
Normal file
@ -0,0 +1,390 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
promext "k8s.io/component-base/metrics/prometheusextension"
|
||||
"k8s.io/klog/v2"
|
||||
yaml "sigs.k8s.io/yaml/goyaml.v2"
|
||||
)
|
||||
|
||||
var (
|
||||
labelValueAllowLists = map[string]*MetricLabelAllowList{}
|
||||
allowListLock sync.RWMutex
|
||||
)
|
||||
|
||||
// ResetLabelValueAllowLists resets the allow lists for label values.
|
||||
// NOTE: This should only be used in test.
|
||||
func ResetLabelValueAllowLists() {
|
||||
allowListLock.Lock()
|
||||
defer allowListLock.Unlock()
|
||||
labelValueAllowLists = map[string]*MetricLabelAllowList{}
|
||||
}
|
||||
|
||||
// KubeOpts is superset struct for prometheus.Opts. The prometheus Opts structure
|
||||
// is purposefully not embedded here because that would change struct initialization
|
||||
// in the manner which people are currently accustomed.
|
||||
//
|
||||
// Name must be set to a non-empty string. DeprecatedVersion is defined only
|
||||
// if the metric for which this options applies is, in fact, deprecated.
|
||||
type KubeOpts struct {
|
||||
Namespace string
|
||||
Subsystem string
|
||||
Name string
|
||||
Help string
|
||||
ConstLabels map[string]string
|
||||
DeprecatedVersion string
|
||||
deprecateOnce sync.Once
|
||||
annotateOnce sync.Once
|
||||
StabilityLevel StabilityLevel
|
||||
initializeLabelAllowListsOnce sync.Once
|
||||
LabelValueAllowLists *MetricLabelAllowList
|
||||
}
|
||||
|
||||
// BuildFQName joins the given three name components by "_". Empty name
|
||||
// components are ignored. If the name parameter itself is empty, an empty
|
||||
// string is returned, no matter what. Metric implementations included in this
|
||||
// library use this function internally to generate the fully-qualified metric
|
||||
// name from the name component in their Opts. Users of the library will only
|
||||
// need this function if they implement their own Metric or instantiate a Desc
|
||||
// (with NewDesc) directly.
|
||||
func BuildFQName(namespace, subsystem, name string) string {
|
||||
return prometheus.BuildFQName(namespace, subsystem, name)
|
||||
}
|
||||
|
||||
// StabilityLevel represents the API guarantees for a given defined metric.
|
||||
type StabilityLevel string
|
||||
|
||||
const (
|
||||
// INTERNAL metrics have no stability guarantees, as such, labels may
|
||||
// be arbitrarily added/removed and the metric may be deleted at any time.
|
||||
INTERNAL StabilityLevel = "INTERNAL"
|
||||
// ALPHA metrics have no stability guarantees, as such, labels may
|
||||
// be arbitrarily added/removed and the metric may be deleted at any time.
|
||||
ALPHA StabilityLevel = "ALPHA"
|
||||
// BETA metrics are governed by the deprecation policy outlined in by
|
||||
// the control plane metrics stability KEP.
|
||||
BETA StabilityLevel = "BETA"
|
||||
// STABLE metrics are guaranteed not be mutated and removal is governed by
|
||||
// the deprecation policy outlined in by the control plane metrics stability KEP.
|
||||
STABLE StabilityLevel = "STABLE"
|
||||
)
|
||||
|
||||
// setDefaults takes 'ALPHA' in case of empty.
|
||||
func (sl *StabilityLevel) setDefaults() {
|
||||
switch *sl {
|
||||
case "":
|
||||
*sl = ALPHA
|
||||
default:
|
||||
// no-op, since we have a StabilityLevel already
|
||||
}
|
||||
}
|
||||
|
||||
// CounterOpts is an alias for Opts. See there for doc comments.
|
||||
type CounterOpts KubeOpts
|
||||
|
||||
// Modify help description on the metric description.
|
||||
func (o *CounterOpts) markDeprecated() {
|
||||
o.deprecateOnce.Do(func() {
|
||||
o.Help = fmt.Sprintf("(Deprecated since %v) %v", o.DeprecatedVersion, o.Help)
|
||||
})
|
||||
}
|
||||
|
||||
// annotateStabilityLevel annotates help description on the metric description with the stability level
|
||||
// of the metric
|
||||
func (o *CounterOpts) annotateStabilityLevel() {
|
||||
o.annotateOnce.Do(func() {
|
||||
o.Help = fmt.Sprintf("[%v] %v", o.StabilityLevel, o.Help)
|
||||
})
|
||||
}
|
||||
|
||||
// convenience function to allow easy transformation to the prometheus
|
||||
// counterpart. This will do more once we have a proper label abstraction
|
||||
func (o *CounterOpts) toPromCounterOpts() prometheus.CounterOpts {
|
||||
return prometheus.CounterOpts{
|
||||
Namespace: o.Namespace,
|
||||
Subsystem: o.Subsystem,
|
||||
Name: o.Name,
|
||||
Help: o.Help,
|
||||
ConstLabels: o.ConstLabels,
|
||||
}
|
||||
}
|
||||
|
||||
// GaugeOpts is an alias for Opts. See there for doc comments.
|
||||
type GaugeOpts KubeOpts
|
||||
|
||||
// Modify help description on the metric description.
|
||||
func (o *GaugeOpts) markDeprecated() {
|
||||
o.deprecateOnce.Do(func() {
|
||||
o.Help = fmt.Sprintf("(Deprecated since %v) %v", o.DeprecatedVersion, o.Help)
|
||||
})
|
||||
}
|
||||
|
||||
// annotateStabilityLevel annotates help description on the metric description with the stability level
|
||||
// of the metric
|
||||
func (o *GaugeOpts) annotateStabilityLevel() {
|
||||
o.annotateOnce.Do(func() {
|
||||
o.Help = fmt.Sprintf("[%v] %v", o.StabilityLevel, o.Help)
|
||||
})
|
||||
}
|
||||
|
||||
// convenience function to allow easy transformation to the prometheus
|
||||
// counterpart. This will do more once we have a proper label abstraction
|
||||
func (o *GaugeOpts) toPromGaugeOpts() prometheus.GaugeOpts {
|
||||
return prometheus.GaugeOpts{
|
||||
Namespace: o.Namespace,
|
||||
Subsystem: o.Subsystem,
|
||||
Name: o.Name,
|
||||
Help: o.Help,
|
||||
ConstLabels: o.ConstLabels,
|
||||
}
|
||||
}
|
||||
|
||||
// HistogramOpts bundles the options for creating a Histogram metric. It is
|
||||
// mandatory to set Name to a non-empty string. All other fields are optional
|
||||
// and can safely be left at their zero value, although it is strongly
|
||||
// encouraged to set a Help string.
|
||||
type HistogramOpts struct {
|
||||
Namespace string
|
||||
Subsystem string
|
||||
Name string
|
||||
Help string
|
||||
ConstLabels map[string]string
|
||||
Buckets []float64
|
||||
DeprecatedVersion string
|
||||
deprecateOnce sync.Once
|
||||
annotateOnce sync.Once
|
||||
StabilityLevel StabilityLevel
|
||||
initializeLabelAllowListsOnce sync.Once
|
||||
LabelValueAllowLists *MetricLabelAllowList
|
||||
}
|
||||
|
||||
// Modify help description on the metric description.
|
||||
func (o *HistogramOpts) markDeprecated() {
|
||||
o.deprecateOnce.Do(func() {
|
||||
o.Help = fmt.Sprintf("(Deprecated since %v) %v", o.DeprecatedVersion, o.Help)
|
||||
})
|
||||
}
|
||||
|
||||
// annotateStabilityLevel annotates help description on the metric description with the stability level
|
||||
// of the metric
|
||||
func (o *HistogramOpts) annotateStabilityLevel() {
|
||||
o.annotateOnce.Do(func() {
|
||||
o.Help = fmt.Sprintf("[%v] %v", o.StabilityLevel, o.Help)
|
||||
})
|
||||
}
|
||||
|
||||
// convenience function to allow easy transformation to the prometheus
|
||||
// counterpart. This will do more once we have a proper label abstraction
|
||||
func (o *HistogramOpts) toPromHistogramOpts() prometheus.HistogramOpts {
|
||||
return prometheus.HistogramOpts{
|
||||
Namespace: o.Namespace,
|
||||
Subsystem: o.Subsystem,
|
||||
Name: o.Name,
|
||||
Help: o.Help,
|
||||
ConstLabels: o.ConstLabels,
|
||||
Buckets: o.Buckets,
|
||||
}
|
||||
}
|
||||
|
||||
// TimingHistogramOpts bundles the options for creating a TimingHistogram metric. It is
|
||||
// mandatory to set Name to a non-empty string. All other fields are optional
|
||||
// and can safely be left at their zero value, although it is strongly
|
||||
// encouraged to set a Help string.
|
||||
type TimingHistogramOpts struct {
|
||||
Namespace string
|
||||
Subsystem string
|
||||
Name string
|
||||
Help string
|
||||
ConstLabels map[string]string
|
||||
Buckets []float64
|
||||
InitialValue float64
|
||||
DeprecatedVersion string
|
||||
deprecateOnce sync.Once
|
||||
annotateOnce sync.Once
|
||||
StabilityLevel StabilityLevel
|
||||
initializeLabelAllowListsOnce sync.Once
|
||||
LabelValueAllowLists *MetricLabelAllowList
|
||||
}
|
||||
|
||||
// Modify help description on the metric description.
|
||||
func (o *TimingHistogramOpts) markDeprecated() {
|
||||
o.deprecateOnce.Do(func() {
|
||||
o.Help = fmt.Sprintf("(Deprecated since %v) %v", o.DeprecatedVersion, o.Help)
|
||||
})
|
||||
}
|
||||
|
||||
// annotateStabilityLevel annotates help description on the metric description with the stability level
|
||||
// of the metric
|
||||
func (o *TimingHistogramOpts) annotateStabilityLevel() {
|
||||
o.annotateOnce.Do(func() {
|
||||
o.Help = fmt.Sprintf("[%v] %v", o.StabilityLevel, o.Help)
|
||||
})
|
||||
}
|
||||
|
||||
// convenience function to allow easy transformation to the prometheus
|
||||
// counterpart. This will do more once we have a proper label abstraction
|
||||
func (o *TimingHistogramOpts) toPromHistogramOpts() promext.TimingHistogramOpts {
|
||||
return promext.TimingHistogramOpts{
|
||||
Namespace: o.Namespace,
|
||||
Subsystem: o.Subsystem,
|
||||
Name: o.Name,
|
||||
Help: o.Help,
|
||||
ConstLabels: o.ConstLabels,
|
||||
Buckets: o.Buckets,
|
||||
InitialValue: o.InitialValue,
|
||||
}
|
||||
}
|
||||
|
||||
// SummaryOpts bundles the options for creating a Summary metric. It is
|
||||
// mandatory to set Name to a non-empty string. While all other fields are
|
||||
// optional and can safely be left at their zero value, it is recommended to set
|
||||
// a help string and to explicitly set the Objectives field to the desired value
|
||||
// as the default value will change in the upcoming v0.10 of the library.
|
||||
type SummaryOpts struct {
|
||||
Namespace string
|
||||
Subsystem string
|
||||
Name string
|
||||
Help string
|
||||
ConstLabels map[string]string
|
||||
Objectives map[float64]float64
|
||||
MaxAge time.Duration
|
||||
AgeBuckets uint32
|
||||
BufCap uint32
|
||||
DeprecatedVersion string
|
||||
deprecateOnce sync.Once
|
||||
annotateOnce sync.Once
|
||||
StabilityLevel StabilityLevel
|
||||
initializeLabelAllowListsOnce sync.Once
|
||||
LabelValueAllowLists *MetricLabelAllowList
|
||||
}
|
||||
|
||||
// Modify help description on the metric description.
|
||||
func (o *SummaryOpts) markDeprecated() {
|
||||
o.deprecateOnce.Do(func() {
|
||||
o.Help = fmt.Sprintf("(Deprecated since %v) %v", o.DeprecatedVersion, o.Help)
|
||||
})
|
||||
}
|
||||
|
||||
// annotateStabilityLevel annotates help description on the metric description with the stability level
|
||||
// of the metric
|
||||
func (o *SummaryOpts) annotateStabilityLevel() {
|
||||
o.annotateOnce.Do(func() {
|
||||
o.Help = fmt.Sprintf("[%v] %v", o.StabilityLevel, o.Help)
|
||||
})
|
||||
}
|
||||
|
||||
// Deprecated: DefObjectives will not be used as the default objectives in
|
||||
// v1.0.0 of the library. The default Summary will have no quantiles then.
|
||||
var (
|
||||
defObjectives = map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}
|
||||
)
|
||||
|
||||
// convenience function to allow easy transformation to the prometheus
|
||||
// counterpart. This will do more once we have a proper label abstraction
|
||||
func (o *SummaryOpts) toPromSummaryOpts() prometheus.SummaryOpts {
|
||||
// we need to retain existing quantile behavior for backwards compatibility,
|
||||
// so let's do what prometheus used to do prior to v1.
|
||||
objectives := o.Objectives
|
||||
if objectives == nil {
|
||||
objectives = defObjectives
|
||||
}
|
||||
return prometheus.SummaryOpts{
|
||||
Namespace: o.Namespace,
|
||||
Subsystem: o.Subsystem,
|
||||
Name: o.Name,
|
||||
Help: o.Help,
|
||||
ConstLabels: o.ConstLabels,
|
||||
Objectives: objectives,
|
||||
MaxAge: o.MaxAge,
|
||||
AgeBuckets: o.AgeBuckets,
|
||||
BufCap: o.BufCap,
|
||||
}
|
||||
}
|
||||
|
||||
type MetricLabelAllowList struct {
|
||||
labelToAllowList map[string]sets.Set[string]
|
||||
}
|
||||
|
||||
func (allowList *MetricLabelAllowList) ConstrainToAllowedList(labelNameList, labelValueList []string) {
|
||||
for index, value := range labelValueList {
|
||||
name := labelNameList[index]
|
||||
if allowValues, ok := allowList.labelToAllowList[name]; ok {
|
||||
if !allowValues.Has(value) {
|
||||
labelValueList[index] = "unexpected"
|
||||
cardinalityEnforcementUnexpectedCategorizationsTotal.Inc()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (allowList *MetricLabelAllowList) ConstrainLabelMap(labels map[string]string) {
|
||||
for name, value := range labels {
|
||||
if allowValues, ok := allowList.labelToAllowList[name]; ok {
|
||||
if !allowValues.Has(value) {
|
||||
labels[name] = "unexpected"
|
||||
cardinalityEnforcementUnexpectedCategorizationsTotal.Inc()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func SetLabelAllowListFromCLI(allowListMapping map[string]string) {
|
||||
allowListLock.Lock()
|
||||
defer allowListLock.Unlock()
|
||||
for metricLabelName, labelValues := range allowListMapping {
|
||||
metricName := strings.Split(metricLabelName, ",")[0]
|
||||
labelName := strings.Split(metricLabelName, ",")[1]
|
||||
valueSet := sets.New[string](strings.Split(labelValues, ",")...)
|
||||
|
||||
allowList, ok := labelValueAllowLists[metricName]
|
||||
if ok {
|
||||
allowList.labelToAllowList[labelName] = valueSet
|
||||
} else {
|
||||
labelToAllowList := make(map[string]sets.Set[string])
|
||||
labelToAllowList[labelName] = valueSet
|
||||
labelValueAllowLists[metricName] = &MetricLabelAllowList{
|
||||
labelToAllowList,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func SetLabelAllowListFromManifest(manifest string) {
|
||||
allowListMapping := make(map[string]string)
|
||||
data, err := os.ReadFile(filepath.Clean(manifest))
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to read allow list manifest: %v", err)
|
||||
return
|
||||
}
|
||||
err = yaml.Unmarshal(data, &allowListMapping)
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to parse allow list manifest: %v", err)
|
||||
return
|
||||
}
|
||||
SetLabelAllowListFromCLI(allowListMapping)
|
||||
}
|
51
e2e/vendor/k8s.io/component-base/metrics/processstarttime.go
generated
vendored
Normal file
51
e2e/vendor/k8s.io/component-base/metrics/processstarttime.go
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
var processStartTime = NewGaugeVec(
|
||||
&GaugeOpts{
|
||||
Name: "process_start_time_seconds",
|
||||
Help: "Start time of the process since unix epoch in seconds.",
|
||||
StabilityLevel: ALPHA,
|
||||
},
|
||||
[]string{},
|
||||
)
|
||||
|
||||
// RegisterProcessStartTime registers the process_start_time_seconds to
|
||||
// a prometheus registry. This metric needs to be included to ensure counter
|
||||
// data fidelity.
|
||||
func RegisterProcessStartTime(registrationFunc func(Registerable) error) error {
|
||||
start, err := GetProcessStart()
|
||||
if err != nil {
|
||||
klog.Errorf("Could not get process start time, %v", err)
|
||||
start = float64(time.Now().Unix())
|
||||
}
|
||||
// processStartTime is a lazy metric which only get initialized after registered.
|
||||
// so we need to register the metric first and then set the value for it
|
||||
if err = registrationFunc(processStartTime); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
processStartTime.WithLabelValues().Set(start)
|
||||
return nil
|
||||
}
|
39
e2e/vendor/k8s.io/component-base/metrics/processstarttime_others.go
generated
vendored
Normal file
39
e2e/vendor/k8s.io/component-base/metrics/processstarttime_others.go
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/prometheus/procfs"
|
||||
)
|
||||
|
||||
func GetProcessStart() (float64, error) {
|
||||
pid := os.Getpid()
|
||||
p, err := procfs.NewProc(pid)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if stat, err := p.Stat(); err == nil {
|
||||
return stat.StartTime()
|
||||
}
|
||||
return 0, err
|
||||
}
|
34
e2e/vendor/k8s.io/component-base/metrics/processstarttime_windows.go
generated
vendored
Normal file
34
e2e/vendor/k8s.io/component-base/metrics/processstarttime_windows.go
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func GetProcessStart() (float64, error) {
|
||||
processHandle := windows.CurrentProcess()
|
||||
|
||||
var creationTime, exitTime, kernelTime, userTime windows.Filetime
|
||||
if err := windows.GetProcessTimes(processHandle, &creationTime, &exitTime, &kernelTime, &userTime); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return float64(creationTime.Nanoseconds() / 1e9), nil
|
||||
}
|
53
e2e/vendor/k8s.io/component-base/metrics/prometheus/feature/metrics.go
generated
vendored
Normal file
53
e2e/vendor/k8s.io/component-base/metrics/prometheus/feature/metrics.go
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright 2022 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package feature
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
k8smetrics "k8s.io/component-base/metrics"
|
||||
"k8s.io/component-base/metrics/legacyregistry"
|
||||
)
|
||||
|
||||
var (
|
||||
// featureInfo is a Prometheus Gauge metrics used for recording the enablement of a k8s feature.
|
||||
featureInfo = k8smetrics.NewGaugeVec(
|
||||
&k8smetrics.GaugeOpts{
|
||||
Namespace: "kubernetes",
|
||||
Name: "feature_enabled",
|
||||
Help: "This metric records the data about the stage and enablement of a k8s feature.",
|
||||
StabilityLevel: k8smetrics.BETA,
|
||||
},
|
||||
[]string{"name", "stage"},
|
||||
)
|
||||
)
|
||||
|
||||
func init() {
|
||||
legacyregistry.MustRegister(featureInfo)
|
||||
}
|
||||
|
||||
func ResetFeatureInfoMetric() {
|
||||
featureInfo.Reset()
|
||||
}
|
||||
|
||||
func RecordFeatureInfo(ctx context.Context, name string, stage string, enabled bool) {
|
||||
value := 0.0
|
||||
if enabled {
|
||||
value = 1.0
|
||||
}
|
||||
featureInfo.WithContext(ctx).WithLabelValues(name, stage).Set(value)
|
||||
}
|
75
e2e/vendor/k8s.io/component-base/metrics/prometheus/slis/metrics.go
generated
vendored
Normal file
75
e2e/vendor/k8s.io/component-base/metrics/prometheus/slis/metrics.go
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
Copyright 2022 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package slis
|
||||
|
||||
import (
|
||||
"context"
|
||||
k8smetrics "k8s.io/component-base/metrics"
|
||||
)
|
||||
|
||||
type HealthcheckStatus string
|
||||
|
||||
const (
|
||||
Success HealthcheckStatus = "success"
|
||||
Error HealthcheckStatus = "error"
|
||||
)
|
||||
|
||||
var (
|
||||
// healthcheck is a Prometheus Gauge metrics used for recording the results of a k8s healthcheck.
|
||||
healthcheck = k8smetrics.NewGaugeVec(
|
||||
&k8smetrics.GaugeOpts{
|
||||
Namespace: "kubernetes",
|
||||
Name: "healthcheck",
|
||||
Help: "This metric records the result of a single healthcheck.",
|
||||
StabilityLevel: k8smetrics.STABLE,
|
||||
},
|
||||
[]string{"name", "type"},
|
||||
)
|
||||
|
||||
// healthchecksTotal is a Prometheus Counter metrics used for counting the results of a k8s healthcheck.
|
||||
healthchecksTotal = k8smetrics.NewCounterVec(
|
||||
&k8smetrics.CounterOpts{
|
||||
Namespace: "kubernetes",
|
||||
Name: "healthchecks_total",
|
||||
Help: "This metric records the results of all healthcheck.",
|
||||
StabilityLevel: k8smetrics.STABLE,
|
||||
},
|
||||
[]string{"name", "type", "status"},
|
||||
)
|
||||
)
|
||||
|
||||
func Register(registry k8smetrics.KubeRegistry) {
|
||||
registry.Register(healthcheck)
|
||||
registry.Register(healthchecksTotal)
|
||||
_ = k8smetrics.RegisterProcessStartTime(registry.Register)
|
||||
}
|
||||
|
||||
func ResetHealthMetrics() {
|
||||
healthcheck.Reset()
|
||||
healthchecksTotal.Reset()
|
||||
}
|
||||
|
||||
func ObserveHealthcheck(ctx context.Context, name string, healthcheckType string, status HealthcheckStatus) error {
|
||||
if status == Success {
|
||||
healthcheck.WithContext(ctx).WithLabelValues(name, healthcheckType).Set(1)
|
||||
} else {
|
||||
healthcheck.WithContext(ctx).WithLabelValues(name, healthcheckType).Set(0)
|
||||
}
|
||||
|
||||
healthchecksTotal.WithContext(ctx).WithLabelValues(name, healthcheckType, string(status)).Inc()
|
||||
return nil
|
||||
}
|
27
e2e/vendor/k8s.io/component-base/metrics/prometheus/slis/registry.go
generated
vendored
Normal file
27
e2e/vendor/k8s.io/component-base/metrics/prometheus/slis/registry.go
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright 2020 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package slis
|
||||
|
||||
import (
|
||||
"k8s.io/component-base/metrics"
|
||||
)
|
||||
|
||||
var (
|
||||
// Registry exposes the SLI registry so that additional SLIs can be
|
||||
// added on a per-component basis.
|
||||
Registry = metrics.NewKubeRegistry()
|
||||
)
|
53
e2e/vendor/k8s.io/component-base/metrics/prometheus/slis/routes.go
generated
vendored
Normal file
53
e2e/vendor/k8s.io/component-base/metrics/prometheus/slis/routes.go
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright 2020 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package slis
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"k8s.io/component-base/metrics"
|
||||
)
|
||||
|
||||
var (
|
||||
installOnce = sync.Once{}
|
||||
installWithResetOnce = sync.Once{}
|
||||
)
|
||||
|
||||
type mux interface {
|
||||
Handle(path string, handler http.Handler)
|
||||
}
|
||||
|
||||
type SLIMetrics struct{}
|
||||
|
||||
// Install adds the DefaultMetrics handler
|
||||
func (s SLIMetrics) Install(m mux) {
|
||||
installOnce.Do(func() {
|
||||
Register(Registry)
|
||||
})
|
||||
m.Handle("/metrics/slis", metrics.HandlerFor(Registry, metrics.HandlerOpts{}))
|
||||
}
|
||||
|
||||
type SLIMetricsWithReset struct{}
|
||||
|
||||
// Install adds the DefaultMetrics handler
|
||||
func (s SLIMetricsWithReset) Install(m mux) {
|
||||
installWithResetOnce.Do(func() {
|
||||
Register(Registry)
|
||||
})
|
||||
m.Handle("/metrics/slis", metrics.HandlerWithReset(Registry, metrics.HandlerOpts{}))
|
||||
}
|
137
e2e/vendor/k8s.io/component-base/metrics/prometheus/workqueue/metrics.go
generated
vendored
Normal file
137
e2e/vendor/k8s.io/component-base/metrics/prometheus/workqueue/metrics.go
generated
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package workqueue
|
||||
|
||||
import (
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
k8smetrics "k8s.io/component-base/metrics"
|
||||
"k8s.io/component-base/metrics/legacyregistry"
|
||||
)
|
||||
|
||||
// Package prometheus sets the workqueue DefaultMetricsFactory to produce
|
||||
// prometheus metrics. To use this package, you just have to import it.
|
||||
|
||||
// Metrics subsystem and keys used by the workqueue.
|
||||
const (
|
||||
WorkQueueSubsystem = "workqueue"
|
||||
DepthKey = "depth"
|
||||
AddsKey = "adds_total"
|
||||
QueueLatencyKey = "queue_duration_seconds"
|
||||
WorkDurationKey = "work_duration_seconds"
|
||||
UnfinishedWorkKey = "unfinished_work_seconds"
|
||||
LongestRunningProcessorKey = "longest_running_processor_seconds"
|
||||
RetriesKey = "retries_total"
|
||||
)
|
||||
|
||||
var (
|
||||
depth = k8smetrics.NewGaugeVec(&k8smetrics.GaugeOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: DepthKey,
|
||||
StabilityLevel: k8smetrics.ALPHA,
|
||||
Help: "Current depth of workqueue",
|
||||
}, []string{"name"})
|
||||
|
||||
adds = k8smetrics.NewCounterVec(&k8smetrics.CounterOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: AddsKey,
|
||||
StabilityLevel: k8smetrics.ALPHA,
|
||||
Help: "Total number of adds handled by workqueue",
|
||||
}, []string{"name"})
|
||||
|
||||
latency = k8smetrics.NewHistogramVec(&k8smetrics.HistogramOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: QueueLatencyKey,
|
||||
StabilityLevel: k8smetrics.ALPHA,
|
||||
Help: "How long in seconds an item stays in workqueue before being requested.",
|
||||
Buckets: k8smetrics.ExponentialBuckets(10e-9, 10, 10),
|
||||
}, []string{"name"})
|
||||
|
||||
workDuration = k8smetrics.NewHistogramVec(&k8smetrics.HistogramOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: WorkDurationKey,
|
||||
StabilityLevel: k8smetrics.ALPHA,
|
||||
Help: "How long in seconds processing an item from workqueue takes.",
|
||||
Buckets: k8smetrics.ExponentialBuckets(10e-9, 10, 10),
|
||||
}, []string{"name"})
|
||||
|
||||
unfinished = k8smetrics.NewGaugeVec(&k8smetrics.GaugeOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: UnfinishedWorkKey,
|
||||
StabilityLevel: k8smetrics.ALPHA,
|
||||
Help: "How many seconds of work has done that " +
|
||||
"is in progress and hasn't been observed by work_duration. Large " +
|
||||
"values indicate stuck threads. One can deduce the number of stuck " +
|
||||
"threads by observing the rate at which this increases.",
|
||||
}, []string{"name"})
|
||||
|
||||
longestRunningProcessor = k8smetrics.NewGaugeVec(&k8smetrics.GaugeOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: LongestRunningProcessorKey,
|
||||
StabilityLevel: k8smetrics.ALPHA,
|
||||
Help: "How many seconds has the longest running " +
|
||||
"processor for workqueue been running.",
|
||||
}, []string{"name"})
|
||||
|
||||
retries = k8smetrics.NewCounterVec(&k8smetrics.CounterOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: RetriesKey,
|
||||
StabilityLevel: k8smetrics.ALPHA,
|
||||
Help: "Total number of retries handled by workqueue",
|
||||
}, []string{"name"})
|
||||
|
||||
metrics = []k8smetrics.Registerable{
|
||||
depth, adds, latency, workDuration, unfinished, longestRunningProcessor, retries,
|
||||
}
|
||||
)
|
||||
|
||||
type prometheusMetricsProvider struct {
|
||||
}
|
||||
|
||||
func init() {
|
||||
for _, m := range metrics {
|
||||
legacyregistry.MustRegister(m)
|
||||
}
|
||||
workqueue.SetProvider(prometheusMetricsProvider{})
|
||||
}
|
||||
|
||||
func (prometheusMetricsProvider) NewDepthMetric(name string) workqueue.GaugeMetric {
|
||||
return depth.WithLabelValues(name)
|
||||
}
|
||||
|
||||
func (prometheusMetricsProvider) NewAddsMetric(name string) workqueue.CounterMetric {
|
||||
return adds.WithLabelValues(name)
|
||||
}
|
||||
|
||||
func (prometheusMetricsProvider) NewLatencyMetric(name string) workqueue.HistogramMetric {
|
||||
return latency.WithLabelValues(name)
|
||||
}
|
||||
|
||||
func (prometheusMetricsProvider) NewWorkDurationMetric(name string) workqueue.HistogramMetric {
|
||||
return workDuration.WithLabelValues(name)
|
||||
}
|
||||
|
||||
func (prometheusMetricsProvider) NewUnfinishedWorkSecondsMetric(name string) workqueue.SettableGaugeMetric {
|
||||
return unfinished.WithLabelValues(name)
|
||||
}
|
||||
|
||||
func (prometheusMetricsProvider) NewLongestRunningProcessorSecondsMetric(name string) workqueue.SettableGaugeMetric {
|
||||
return longestRunningProcessor.WithLabelValues(name)
|
||||
}
|
||||
|
||||
func (prometheusMetricsProvider) NewRetriesMetric(name string) workqueue.CounterMetric {
|
||||
return retries.WithLabelValues(name)
|
||||
}
|
189
e2e/vendor/k8s.io/component-base/metrics/prometheusextension/timing_histogram.go
generated
vendored
Normal file
189
e2e/vendor/k8s.io/component-base/metrics/prometheusextension/timing_histogram.go
generated
vendored
Normal file
@ -0,0 +1,189 @@
|
||||
/*
|
||||
Copyright 2022 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package prometheusextension
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
// GaugeOps is the part of `prometheus.Gauge` that is relevant to
|
||||
// instrumented code.
|
||||
// This factoring should be in prometheus, analogous to the way
|
||||
// it already factors out the Observer interface for histograms and summaries.
|
||||
type GaugeOps interface {
|
||||
// Set is the same as Gauge.Set
|
||||
Set(float64)
|
||||
// Inc is the same as Gauge.inc
|
||||
Inc()
|
||||
// Dec is the same as Gauge.Dec
|
||||
Dec()
|
||||
// Add is the same as Gauge.Add
|
||||
Add(float64)
|
||||
// Sub is the same as Gauge.Sub
|
||||
Sub(float64)
|
||||
|
||||
// SetToCurrentTime the same as Gauge.SetToCurrentTime
|
||||
SetToCurrentTime()
|
||||
}
|
||||
|
||||
// A TimingHistogram tracks how long a `float64` variable spends in
|
||||
// ranges defined by buckets. Time is counted in nanoseconds. The
|
||||
// histogram's sum is the integral over time (in nanoseconds, from
|
||||
// creation of the histogram) of the variable's value.
|
||||
type TimingHistogram interface {
|
||||
prometheus.Metric
|
||||
prometheus.Collector
|
||||
GaugeOps
|
||||
}
|
||||
|
||||
// TimingHistogramOpts is the parameters of the TimingHistogram constructor
|
||||
type TimingHistogramOpts struct {
|
||||
Namespace string
|
||||
Subsystem string
|
||||
Name string
|
||||
Help string
|
||||
ConstLabels prometheus.Labels
|
||||
|
||||
// Buckets defines the buckets into which observations are
|
||||
// accumulated. Each element in the slice is the upper
|
||||
// inclusive bound of a bucket. The values must be sorted in
|
||||
// strictly increasing order. There is no need to add a
|
||||
// highest bucket with +Inf bound. The default value is
|
||||
// prometheus.DefBuckets.
|
||||
Buckets []float64
|
||||
|
||||
// The initial value of the variable.
|
||||
InitialValue float64
|
||||
}
|
||||
|
||||
// NewTimingHistogram creates a new TimingHistogram
|
||||
func NewTimingHistogram(opts TimingHistogramOpts) (TimingHistogram, error) {
|
||||
return NewTestableTimingHistogram(time.Now, opts)
|
||||
}
|
||||
|
||||
// NewTestableTimingHistogram creates a TimingHistogram that uses a mockable clock
|
||||
func NewTestableTimingHistogram(nowFunc func() time.Time, opts TimingHistogramOpts) (TimingHistogram, error) {
|
||||
desc := prometheus.NewDesc(
|
||||
prometheus.BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
|
||||
wrapTimingHelp(opts.Help),
|
||||
nil,
|
||||
opts.ConstLabels,
|
||||
)
|
||||
return newTimingHistogram(nowFunc, desc, opts)
|
||||
}
|
||||
|
||||
func wrapTimingHelp(given string) string {
|
||||
return "EXPERIMENTAL: " + given
|
||||
}
|
||||
|
||||
func newTimingHistogram(nowFunc func() time.Time, desc *prometheus.Desc, opts TimingHistogramOpts, variableLabelValues ...string) (TimingHistogram, error) {
|
||||
allLabelsM := prometheus.Labels{}
|
||||
allLabelsS := prometheus.MakeLabelPairs(desc, variableLabelValues)
|
||||
for _, pair := range allLabelsS {
|
||||
if pair == nil || pair.Name == nil || pair.Value == nil {
|
||||
return nil, errors.New("prometheus.MakeLabelPairs returned a nil")
|
||||
}
|
||||
allLabelsM[*pair.Name] = *pair.Value
|
||||
}
|
||||
weighted, err := newWeightedHistogram(desc, WeightedHistogramOpts{
|
||||
Namespace: opts.Namespace,
|
||||
Subsystem: opts.Subsystem,
|
||||
Name: opts.Name,
|
||||
Help: opts.Help,
|
||||
ConstLabels: allLabelsM,
|
||||
Buckets: opts.Buckets,
|
||||
}, variableLabelValues...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &timingHistogram{
|
||||
nowFunc: nowFunc,
|
||||
weighted: weighted,
|
||||
lastSetTime: nowFunc(),
|
||||
value: opts.InitialValue,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type timingHistogram struct {
|
||||
nowFunc func() time.Time
|
||||
weighted *weightedHistogram
|
||||
|
||||
// The following fields must only be accessed with weighted's lock held
|
||||
|
||||
lastSetTime time.Time // identifies when value was last set
|
||||
value float64
|
||||
}
|
||||
|
||||
var _ TimingHistogram = &timingHistogram{}
|
||||
|
||||
func (th *timingHistogram) Set(newValue float64) {
|
||||
th.update(func(float64) float64 { return newValue })
|
||||
}
|
||||
|
||||
func (th *timingHistogram) Inc() {
|
||||
th.update(func(oldValue float64) float64 { return oldValue + 1 })
|
||||
}
|
||||
|
||||
func (th *timingHistogram) Dec() {
|
||||
th.update(func(oldValue float64) float64 { return oldValue - 1 })
|
||||
}
|
||||
|
||||
func (th *timingHistogram) Add(delta float64) {
|
||||
th.update(func(oldValue float64) float64 { return oldValue + delta })
|
||||
}
|
||||
|
||||
func (th *timingHistogram) Sub(delta float64) {
|
||||
th.update(func(oldValue float64) float64 { return oldValue - delta })
|
||||
}
|
||||
|
||||
func (th *timingHistogram) SetToCurrentTime() {
|
||||
th.update(func(oldValue float64) float64 { return th.nowFunc().Sub(time.Unix(0, 0)).Seconds() })
|
||||
}
|
||||
|
||||
func (th *timingHistogram) update(updateFn func(float64) float64) {
|
||||
th.weighted.lock.Lock()
|
||||
defer th.weighted.lock.Unlock()
|
||||
now := th.nowFunc()
|
||||
delta := now.Sub(th.lastSetTime)
|
||||
value := th.value
|
||||
if delta > 0 {
|
||||
th.weighted.observeWithWeightLocked(value, uint64(delta))
|
||||
th.lastSetTime = now
|
||||
}
|
||||
th.value = updateFn(value)
|
||||
}
|
||||
|
||||
func (th *timingHistogram) Desc() *prometheus.Desc {
|
||||
return th.weighted.Desc()
|
||||
}
|
||||
|
||||
func (th *timingHistogram) Write(dest *dto.Metric) error {
|
||||
th.Add(0) // account for time since last update
|
||||
return th.weighted.Write(dest)
|
||||
}
|
||||
|
||||
func (th *timingHistogram) Describe(ch chan<- *prometheus.Desc) {
|
||||
ch <- th.weighted.Desc()
|
||||
}
|
||||
|
||||
func (th *timingHistogram) Collect(ch chan<- prometheus.Metric) {
|
||||
ch <- th
|
||||
}
|
111
e2e/vendor/k8s.io/component-base/metrics/prometheusextension/timing_histogram_vec.go
generated
vendored
Normal file
111
e2e/vendor/k8s.io/component-base/metrics/prometheusextension/timing_histogram_vec.go
generated
vendored
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
Copyright 2022 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package prometheusextension
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
// GaugeVecOps is a bunch of Gauge that have the same
|
||||
// Desc and are distinguished by the values for their variable labels.
|
||||
type GaugeVecOps interface {
|
||||
GetMetricWith(prometheus.Labels) (GaugeOps, error)
|
||||
GetMetricWithLabelValues(lvs ...string) (GaugeOps, error)
|
||||
With(prometheus.Labels) GaugeOps
|
||||
WithLabelValues(...string) GaugeOps
|
||||
CurryWith(prometheus.Labels) (GaugeVecOps, error)
|
||||
MustCurryWith(prometheus.Labels) GaugeVecOps
|
||||
}
|
||||
|
||||
type TimingHistogramVec struct {
|
||||
*prometheus.MetricVec
|
||||
}
|
||||
|
||||
var _ GaugeVecOps = &TimingHistogramVec{}
|
||||
var _ prometheus.Collector = &TimingHistogramVec{}
|
||||
|
||||
func NewTimingHistogramVec(opts TimingHistogramOpts, labelNames ...string) *TimingHistogramVec {
|
||||
return NewTestableTimingHistogramVec(time.Now, opts, labelNames...)
|
||||
}
|
||||
|
||||
func NewTestableTimingHistogramVec(nowFunc func() time.Time, opts TimingHistogramOpts, labelNames ...string) *TimingHistogramVec {
|
||||
desc := prometheus.NewDesc(
|
||||
prometheus.BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
|
||||
wrapTimingHelp(opts.Help),
|
||||
labelNames,
|
||||
opts.ConstLabels,
|
||||
)
|
||||
return &TimingHistogramVec{
|
||||
MetricVec: prometheus.NewMetricVec(desc, func(lvs ...string) prometheus.Metric {
|
||||
metric, err := newTimingHistogram(nowFunc, desc, opts, lvs...)
|
||||
if err != nil {
|
||||
panic(err) // like in prometheus.newHistogram
|
||||
}
|
||||
return metric
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
func (hv *TimingHistogramVec) GetMetricWith(labels prometheus.Labels) (GaugeOps, error) {
|
||||
metric, err := hv.MetricVec.GetMetricWith(labels)
|
||||
if metric != nil {
|
||||
return metric.(GaugeOps), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (hv *TimingHistogramVec) GetMetricWithLabelValues(lvs ...string) (GaugeOps, error) {
|
||||
metric, err := hv.MetricVec.GetMetricWithLabelValues(lvs...)
|
||||
if metric != nil {
|
||||
return metric.(GaugeOps), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (hv *TimingHistogramVec) With(labels prometheus.Labels) GaugeOps {
|
||||
h, err := hv.GetMetricWith(labels)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
func (hv *TimingHistogramVec) WithLabelValues(lvs ...string) GaugeOps {
|
||||
h, err := hv.GetMetricWithLabelValues(lvs...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
func (hv *TimingHistogramVec) CurryWith(labels prometheus.Labels) (GaugeVecOps, error) {
|
||||
vec, err := hv.MetricVec.CurryWith(labels)
|
||||
if vec != nil {
|
||||
return &TimingHistogramVec{MetricVec: vec}, err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (hv *TimingHistogramVec) MustCurryWith(labels prometheus.Labels) GaugeVecOps {
|
||||
vec, err := hv.CurryWith(labels)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return vec
|
||||
}
|
203
e2e/vendor/k8s.io/component-base/metrics/prometheusextension/weighted_histogram.go
generated
vendored
Normal file
203
e2e/vendor/k8s.io/component-base/metrics/prometheusextension/weighted_histogram.go
generated
vendored
Normal file
@ -0,0 +1,203 @@
|
||||
/*
|
||||
Copyright 2022 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package prometheusextension
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
// WeightedHistogram generalizes Histogram: each observation has
|
||||
// an associated _weight_. For a given `x` and `N`,
|
||||
// `1` call on `ObserveWithWeight(x, N)` has the same meaning as
|
||||
// `N` calls on `ObserveWithWeight(x, 1)`.
|
||||
// The weighted sum might differ slightly due to the use of
|
||||
// floating point, although the implementation takes some steps
|
||||
// to mitigate that.
|
||||
// If every weight were 1,
|
||||
// this would be the same as the existing Histogram abstraction.
|
||||
type WeightedHistogram interface {
|
||||
prometheus.Metric
|
||||
prometheus.Collector
|
||||
WeightedObserver
|
||||
}
|
||||
|
||||
// WeightedObserver generalizes the Observer interface.
|
||||
type WeightedObserver interface {
|
||||
// Set the variable to the given value with the given weight.
|
||||
ObserveWithWeight(value float64, weight uint64)
|
||||
}
|
||||
|
||||
// WeightedHistogramOpts is the same as for an ordinary Histogram
|
||||
type WeightedHistogramOpts = prometheus.HistogramOpts
|
||||
|
||||
// NewWeightedHistogram creates a new WeightedHistogram
|
||||
func NewWeightedHistogram(opts WeightedHistogramOpts) (WeightedHistogram, error) {
|
||||
desc := prometheus.NewDesc(
|
||||
prometheus.BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
|
||||
wrapWeightedHelp(opts.Help),
|
||||
nil,
|
||||
opts.ConstLabels,
|
||||
)
|
||||
return newWeightedHistogram(desc, opts)
|
||||
}
|
||||
|
||||
func wrapWeightedHelp(given string) string {
|
||||
return "EXPERIMENTAL: " + given
|
||||
}
|
||||
|
||||
func newWeightedHistogram(desc *prometheus.Desc, opts WeightedHistogramOpts, variableLabelValues ...string) (*weightedHistogram, error) {
|
||||
if len(opts.Buckets) == 0 {
|
||||
opts.Buckets = prometheus.DefBuckets
|
||||
}
|
||||
|
||||
for i, upperBound := range opts.Buckets {
|
||||
if i < len(opts.Buckets)-1 {
|
||||
if upperBound >= opts.Buckets[i+1] {
|
||||
return nil, fmt.Errorf(
|
||||
"histogram buckets must be in increasing order: %f >= %f",
|
||||
upperBound, opts.Buckets[i+1],
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if math.IsInf(upperBound, +1) {
|
||||
// The +Inf bucket is implicit. Remove it here.
|
||||
opts.Buckets = opts.Buckets[:i]
|
||||
}
|
||||
}
|
||||
}
|
||||
upperBounds := make([]float64, len(opts.Buckets))
|
||||
copy(upperBounds, opts.Buckets)
|
||||
|
||||
return &weightedHistogram{
|
||||
desc: desc,
|
||||
variableLabelValues: variableLabelValues,
|
||||
upperBounds: upperBounds,
|
||||
buckets: make([]uint64, len(upperBounds)+1),
|
||||
hotCount: initialHotCount,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type weightedHistogram struct {
|
||||
desc *prometheus.Desc
|
||||
variableLabelValues []string
|
||||
upperBounds []float64 // exclusive of +Inf
|
||||
|
||||
lock sync.Mutex // applies to all the following
|
||||
|
||||
// buckets is longer by one than upperBounds.
|
||||
// For 0 <= idx < len(upperBounds), buckets[idx] holds the
|
||||
// accumulated time.Duration that value has been <=
|
||||
// upperBounds[idx] but not <= upperBounds[idx-1].
|
||||
// buckets[len(upperBounds)] holds the accumulated
|
||||
// time.Duration when value fit in no other bucket.
|
||||
buckets []uint64
|
||||
|
||||
// sumHot + sumCold is the weighted sum of value.
|
||||
// Rather than risk loss of precision in one
|
||||
// float64, we do this sum hierarchically. Many successive
|
||||
// increments are added into sumHot; once in a while
|
||||
// the magnitude of sumHot is compared to the magnitude
|
||||
// of sumCold and, if the ratio is high enough,
|
||||
// sumHot is transferred into sumCold.
|
||||
sumHot float64
|
||||
sumCold float64
|
||||
|
||||
transferThreshold float64 // = math.Abs(sumCold) / 2^26 (that's about half of the bits of precision in a float64)
|
||||
|
||||
// hotCount is used to decide when to consider dumping sumHot into sumCold.
|
||||
// hotCount counts upward from initialHotCount to zero.
|
||||
hotCount int
|
||||
}
|
||||
|
||||
// initialHotCount is the negative of the number of terms
|
||||
// that are summed into sumHot before considering whether
|
||||
// to transfer to sumCold. This only has to be big enough
|
||||
// to make the extra floating point operations occur in a
|
||||
// distinct minority of cases.
|
||||
const initialHotCount = -15
|
||||
|
||||
var _ WeightedHistogram = &weightedHistogram{}
|
||||
var _ prometheus.Metric = &weightedHistogram{}
|
||||
var _ prometheus.Collector = &weightedHistogram{}
|
||||
|
||||
func (sh *weightedHistogram) ObserveWithWeight(value float64, weight uint64) {
|
||||
idx := sort.SearchFloat64s(sh.upperBounds, value)
|
||||
sh.lock.Lock()
|
||||
defer sh.lock.Unlock()
|
||||
sh.updateLocked(idx, value, weight)
|
||||
}
|
||||
|
||||
func (sh *weightedHistogram) observeWithWeightLocked(value float64, weight uint64) {
|
||||
idx := sort.SearchFloat64s(sh.upperBounds, value)
|
||||
sh.updateLocked(idx, value, weight)
|
||||
}
|
||||
|
||||
func (sh *weightedHistogram) updateLocked(idx int, value float64, weight uint64) {
|
||||
sh.buckets[idx] += weight
|
||||
newSumHot := sh.sumHot + float64(weight)*value
|
||||
sh.hotCount++
|
||||
if sh.hotCount >= 0 {
|
||||
sh.hotCount = initialHotCount
|
||||
if math.Abs(newSumHot) > sh.transferThreshold {
|
||||
newSumCold := sh.sumCold + newSumHot
|
||||
sh.sumCold = newSumCold
|
||||
sh.transferThreshold = math.Abs(newSumCold / 67108864)
|
||||
sh.sumHot = 0
|
||||
return
|
||||
}
|
||||
}
|
||||
sh.sumHot = newSumHot
|
||||
}
|
||||
|
||||
func (sh *weightedHistogram) Desc() *prometheus.Desc {
|
||||
return sh.desc
|
||||
}
|
||||
|
||||
func (sh *weightedHistogram) Write(dest *dto.Metric) error {
|
||||
count, sum, buckets := func() (uint64, float64, map[float64]uint64) {
|
||||
sh.lock.Lock()
|
||||
defer sh.lock.Unlock()
|
||||
nBounds := len(sh.upperBounds)
|
||||
buckets := make(map[float64]uint64, nBounds)
|
||||
var count uint64
|
||||
for idx, upperBound := range sh.upperBounds {
|
||||
count += sh.buckets[idx]
|
||||
buckets[upperBound] = count
|
||||
}
|
||||
count += sh.buckets[nBounds]
|
||||
return count, sh.sumHot + sh.sumCold, buckets
|
||||
}()
|
||||
metric, err := prometheus.NewConstHistogram(sh.desc, count, sum, buckets, sh.variableLabelValues...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return metric.Write(dest)
|
||||
}
|
||||
|
||||
func (sh *weightedHistogram) Describe(ch chan<- *prometheus.Desc) {
|
||||
ch <- sh.desc
|
||||
}
|
||||
|
||||
func (sh *weightedHistogram) Collect(ch chan<- prometheus.Metric) {
|
||||
ch <- sh
|
||||
}
|
106
e2e/vendor/k8s.io/component-base/metrics/prometheusextension/weighted_histogram_vec.go
generated
vendored
Normal file
106
e2e/vendor/k8s.io/component-base/metrics/prometheusextension/weighted_histogram_vec.go
generated
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright 2022 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package prometheusextension
|
||||
|
||||
import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
// WeightedObserverVec is a bunch of WeightedObservers that have the same
|
||||
// Desc and are distinguished by the values for their variable labels.
|
||||
type WeightedObserverVec interface {
|
||||
GetMetricWith(prometheus.Labels) (WeightedObserver, error)
|
||||
GetMetricWithLabelValues(lvs ...string) (WeightedObserver, error)
|
||||
With(prometheus.Labels) WeightedObserver
|
||||
WithLabelValues(...string) WeightedObserver
|
||||
CurryWith(prometheus.Labels) (WeightedObserverVec, error)
|
||||
MustCurryWith(prometheus.Labels) WeightedObserverVec
|
||||
}
|
||||
|
||||
// WeightedHistogramVec implements WeightedObserverVec
|
||||
type WeightedHistogramVec struct {
|
||||
*prometheus.MetricVec
|
||||
}
|
||||
|
||||
var _ WeightedObserverVec = &WeightedHistogramVec{}
|
||||
var _ prometheus.Collector = &WeightedHistogramVec{}
|
||||
|
||||
func NewWeightedHistogramVec(opts WeightedHistogramOpts, labelNames ...string) *WeightedHistogramVec {
|
||||
desc := prometheus.NewDesc(
|
||||
prometheus.BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
|
||||
wrapWeightedHelp(opts.Help),
|
||||
labelNames,
|
||||
opts.ConstLabels,
|
||||
)
|
||||
return &WeightedHistogramVec{
|
||||
MetricVec: prometheus.NewMetricVec(desc, func(lvs ...string) prometheus.Metric {
|
||||
metric, err := newWeightedHistogram(desc, opts, lvs...)
|
||||
if err != nil {
|
||||
panic(err) // like in prometheus.newHistogram
|
||||
}
|
||||
return metric
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
func (hv *WeightedHistogramVec) GetMetricWith(labels prometheus.Labels) (WeightedObserver, error) {
|
||||
metric, err := hv.MetricVec.GetMetricWith(labels)
|
||||
if metric != nil {
|
||||
return metric.(WeightedObserver), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (hv *WeightedHistogramVec) GetMetricWithLabelValues(lvs ...string) (WeightedObserver, error) {
|
||||
metric, err := hv.MetricVec.GetMetricWithLabelValues(lvs...)
|
||||
if metric != nil {
|
||||
return metric.(WeightedObserver), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (hv *WeightedHistogramVec) With(labels prometheus.Labels) WeightedObserver {
|
||||
h, err := hv.GetMetricWith(labels)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
func (hv *WeightedHistogramVec) WithLabelValues(lvs ...string) WeightedObserver {
|
||||
h, err := hv.GetMetricWithLabelValues(lvs...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
func (hv *WeightedHistogramVec) CurryWith(labels prometheus.Labels) (WeightedObserverVec, error) {
|
||||
vec, err := hv.MetricVec.CurryWith(labels)
|
||||
if vec != nil {
|
||||
return &WeightedHistogramVec{MetricVec: vec}, err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (hv *WeightedHistogramVec) MustCurryWith(labels prometheus.Labels) WeightedObserverVec {
|
||||
vec, err := hv.CurryWith(labels)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return vec
|
||||
}
|
394
e2e/vendor/k8s.io/component-base/metrics/registry.go
generated
vendored
Normal file
394
e2e/vendor/k8s.io/component-base/metrics/registry.go
generated
vendored
Normal file
@ -0,0 +1,394 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
|
||||
apimachineryversion "k8s.io/apimachinery/pkg/version"
|
||||
"k8s.io/component-base/version"
|
||||
)
|
||||
|
||||
var (
|
||||
showHiddenOnce sync.Once
|
||||
disabledMetricsLock sync.RWMutex
|
||||
showHidden atomic.Bool
|
||||
registries []*kubeRegistry // stores all registries created by NewKubeRegistry()
|
||||
registriesLock sync.RWMutex
|
||||
disabledMetrics = map[string]struct{}{}
|
||||
|
||||
registeredMetricsTotal = NewCounterVec(
|
||||
&CounterOpts{
|
||||
Name: "registered_metrics_total",
|
||||
Help: "The count of registered metrics broken by stability level and deprecation version.",
|
||||
StabilityLevel: BETA,
|
||||
},
|
||||
[]string{"stability_level", "deprecated_version"},
|
||||
)
|
||||
|
||||
disabledMetricsTotal = NewCounter(
|
||||
&CounterOpts{
|
||||
Name: "disabled_metrics_total",
|
||||
Help: "The count of disabled metrics.",
|
||||
StabilityLevel: BETA,
|
||||
},
|
||||
)
|
||||
|
||||
hiddenMetricsTotal = NewCounter(
|
||||
&CounterOpts{
|
||||
Name: "hidden_metrics_total",
|
||||
Help: "The count of hidden metrics.",
|
||||
StabilityLevel: BETA,
|
||||
},
|
||||
)
|
||||
|
||||
cardinalityEnforcementUnexpectedCategorizationsTotal = NewCounter(
|
||||
&CounterOpts{
|
||||
Name: "cardinality_enforcement_unexpected_categorizations_total",
|
||||
Help: "The count of unexpected categorizations during cardinality enforcement.",
|
||||
StabilityLevel: ALPHA,
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
// shouldHide be used to check if a specific metric with deprecated version should be hidden
|
||||
// according to metrics deprecation lifecycle.
|
||||
func shouldHide(currentVersion *semver.Version, deprecatedVersion *semver.Version) bool {
|
||||
guardVersion, err := semver.Make(fmt.Sprintf("%d.%d.0", currentVersion.Major, currentVersion.Minor))
|
||||
if err != nil {
|
||||
panic("failed to make version from current version")
|
||||
}
|
||||
|
||||
if deprecatedVersion.LT(guardVersion) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// ValidateShowHiddenMetricsVersion checks invalid version for which show hidden metrics.
|
||||
func ValidateShowHiddenMetricsVersion(v string) []error {
|
||||
err := validateShowHiddenMetricsVersion(parseVersion(version.Get()), v)
|
||||
if err != nil {
|
||||
return []error{err}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetDisabledMetric(name string) {
|
||||
disabledMetricsLock.Lock()
|
||||
defer disabledMetricsLock.Unlock()
|
||||
disabledMetrics[name] = struct{}{}
|
||||
disabledMetricsTotal.Inc()
|
||||
}
|
||||
|
||||
// SetShowHidden will enable showing hidden metrics. This will no-opt
|
||||
// after the initial call
|
||||
func SetShowHidden() {
|
||||
showHiddenOnce.Do(func() {
|
||||
showHidden.Store(true)
|
||||
|
||||
// re-register collectors that has been hidden in phase of last registry.
|
||||
for _, r := range registries {
|
||||
r.enableHiddenCollectors()
|
||||
r.enableHiddenStableCollectors()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// ShouldShowHidden returns whether showing hidden deprecated metrics
|
||||
// is enabled. While the primary usecase for this is internal (to determine
|
||||
// registration behavior) this can also be used to introspect
|
||||
func ShouldShowHidden() bool {
|
||||
return showHidden.Load()
|
||||
}
|
||||
|
||||
// Registerable is an interface for a collector metric which we
|
||||
// will register with KubeRegistry.
|
||||
type Registerable interface {
|
||||
prometheus.Collector
|
||||
|
||||
// Create will mark deprecated state for the collector
|
||||
Create(version *semver.Version) bool
|
||||
|
||||
// ClearState will clear all the states marked by Create.
|
||||
ClearState()
|
||||
|
||||
// FQName returns the fully-qualified metric name of the collector.
|
||||
FQName() string
|
||||
}
|
||||
|
||||
type resettable interface {
|
||||
Reset()
|
||||
}
|
||||
|
||||
// KubeRegistry is an interface which implements a subset of prometheus.Registerer and
|
||||
// prometheus.Gatherer interfaces
|
||||
type KubeRegistry interface {
|
||||
// Deprecated
|
||||
RawMustRegister(...prometheus.Collector)
|
||||
// CustomRegister is our internal variant of Prometheus registry.Register
|
||||
CustomRegister(c StableCollector) error
|
||||
// CustomMustRegister is our internal variant of Prometheus registry.MustRegister
|
||||
CustomMustRegister(cs ...StableCollector)
|
||||
// Register conforms to Prometheus registry.Register
|
||||
Register(Registerable) error
|
||||
// MustRegister conforms to Prometheus registry.MustRegister
|
||||
MustRegister(...Registerable)
|
||||
// Unregister conforms to Prometheus registry.Unregister
|
||||
Unregister(collector Collector) bool
|
||||
// Gather conforms to Prometheus gatherer.Gather
|
||||
Gather() ([]*dto.MetricFamily, error)
|
||||
// Reset invokes the Reset() function on all items in the registry
|
||||
// which are added as resettables.
|
||||
Reset()
|
||||
// RegisterMetaMetrics registers metrics about the number of registered metrics.
|
||||
RegisterMetaMetrics()
|
||||
// Registerer exposes the underlying prometheus registerer
|
||||
Registerer() prometheus.Registerer
|
||||
// Gatherer exposes the underlying prometheus gatherer
|
||||
Gatherer() prometheus.Gatherer
|
||||
}
|
||||
|
||||
// kubeRegistry is a wrapper around a prometheus registry-type object. Upon initialization
|
||||
// the kubernetes binary version information is loaded into the registry object, so that
|
||||
// automatic behavior can be configured for metric versioning.
|
||||
type kubeRegistry struct {
|
||||
PromRegistry
|
||||
version semver.Version
|
||||
hiddenCollectors map[string]Registerable // stores all collectors that has been hidden
|
||||
stableCollectors []StableCollector // stores all stable collector
|
||||
hiddenCollectorsLock sync.RWMutex
|
||||
stableCollectorsLock sync.RWMutex
|
||||
resetLock sync.RWMutex
|
||||
resettables []resettable
|
||||
}
|
||||
|
||||
// Register registers a new Collector to be included in metrics
|
||||
// collection. It returns an error if the descriptors provided by the
|
||||
// Collector are invalid or if they — in combination with descriptors of
|
||||
// already registered Collectors — do not fulfill the consistency and
|
||||
// uniqueness criteria described in the documentation of metric.Desc.
|
||||
func (kr *kubeRegistry) Register(c Registerable) error {
|
||||
if c.Create(&kr.version) {
|
||||
defer kr.addResettable(c)
|
||||
return kr.PromRegistry.Register(c)
|
||||
}
|
||||
|
||||
kr.trackHiddenCollector(c)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Registerer exposes the underlying prometheus.Registerer
|
||||
func (kr *kubeRegistry) Registerer() prometheus.Registerer {
|
||||
return kr.PromRegistry
|
||||
}
|
||||
|
||||
// Gatherer exposes the underlying prometheus.Gatherer
|
||||
func (kr *kubeRegistry) Gatherer() prometheus.Gatherer {
|
||||
return kr.PromRegistry
|
||||
}
|
||||
|
||||
// MustRegister works like Register but registers any number of
|
||||
// Collectors and panics upon the first registration that causes an
|
||||
// error.
|
||||
func (kr *kubeRegistry) MustRegister(cs ...Registerable) {
|
||||
metrics := make([]prometheus.Collector, 0, len(cs))
|
||||
for _, c := range cs {
|
||||
if c.Create(&kr.version) {
|
||||
metrics = append(metrics, c)
|
||||
kr.addResettable(c)
|
||||
} else {
|
||||
kr.trackHiddenCollector(c)
|
||||
}
|
||||
}
|
||||
kr.PromRegistry.MustRegister(metrics...)
|
||||
}
|
||||
|
||||
// CustomRegister registers a new custom collector.
|
||||
func (kr *kubeRegistry) CustomRegister(c StableCollector) error {
|
||||
kr.trackStableCollectors(c)
|
||||
defer kr.addResettable(c)
|
||||
if c.Create(&kr.version, c) {
|
||||
return kr.PromRegistry.Register(c)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CustomMustRegister works like CustomRegister but registers any number of
|
||||
// StableCollectors and panics upon the first registration that causes an
|
||||
// error.
|
||||
func (kr *kubeRegistry) CustomMustRegister(cs ...StableCollector) {
|
||||
kr.trackStableCollectors(cs...)
|
||||
collectors := make([]prometheus.Collector, 0, len(cs))
|
||||
for _, c := range cs {
|
||||
if c.Create(&kr.version, c) {
|
||||
kr.addResettable(c)
|
||||
collectors = append(collectors, c)
|
||||
}
|
||||
}
|
||||
kr.PromRegistry.MustRegister(collectors...)
|
||||
}
|
||||
|
||||
// RawMustRegister takes a native prometheus.Collector and registers the collector
|
||||
// to the registry. This bypasses metrics safety checks, so should only be used
|
||||
// to register custom prometheus collectors.
|
||||
//
|
||||
// Deprecated
|
||||
func (kr *kubeRegistry) RawMustRegister(cs ...prometheus.Collector) {
|
||||
kr.PromRegistry.MustRegister(cs...)
|
||||
for _, c := range cs {
|
||||
kr.addResettable(c)
|
||||
}
|
||||
}
|
||||
|
||||
// addResettable will automatically add our metric to our reset
|
||||
// list if it satisfies the interface
|
||||
func (kr *kubeRegistry) addResettable(i interface{}) {
|
||||
kr.resetLock.Lock()
|
||||
defer kr.resetLock.Unlock()
|
||||
if resettable, ok := i.(resettable); ok {
|
||||
kr.resettables = append(kr.resettables, resettable)
|
||||
}
|
||||
}
|
||||
|
||||
// Unregister unregisters the Collector that equals the Collector passed
|
||||
// in as an argument. (Two Collectors are considered equal if their
|
||||
// Describe method yields the same set of descriptors.) The function
|
||||
// returns whether a Collector was unregistered. Note that an unchecked
|
||||
// Collector cannot be unregistered (as its Describe method does not
|
||||
// yield any descriptor).
|
||||
func (kr *kubeRegistry) Unregister(collector Collector) bool {
|
||||
return kr.PromRegistry.Unregister(collector)
|
||||
}
|
||||
|
||||
// Gather calls the Collect method of the registered Collectors and then
|
||||
// gathers the collected metrics into a lexicographically sorted slice
|
||||
// of uniquely named MetricFamily protobufs. Gather ensures that the
|
||||
// returned slice is valid and self-consistent so that it can be used
|
||||
// for valid exposition. As an exception to the strict consistency
|
||||
// requirements described for metric.Desc, Gather will tolerate
|
||||
// different sets of label names for metrics of the same metric family.
|
||||
func (kr *kubeRegistry) Gather() ([]*dto.MetricFamily, error) {
|
||||
return kr.PromRegistry.Gather()
|
||||
}
|
||||
|
||||
// trackHiddenCollector stores all hidden collectors.
|
||||
func (kr *kubeRegistry) trackHiddenCollector(c Registerable) {
|
||||
kr.hiddenCollectorsLock.Lock()
|
||||
defer kr.hiddenCollectorsLock.Unlock()
|
||||
|
||||
kr.hiddenCollectors[c.FQName()] = c
|
||||
hiddenMetricsTotal.Inc()
|
||||
}
|
||||
|
||||
// trackStableCollectors stores all custom collectors.
|
||||
func (kr *kubeRegistry) trackStableCollectors(cs ...StableCollector) {
|
||||
kr.stableCollectorsLock.Lock()
|
||||
defer kr.stableCollectorsLock.Unlock()
|
||||
|
||||
kr.stableCollectors = append(kr.stableCollectors, cs...)
|
||||
}
|
||||
|
||||
// enableHiddenCollectors will re-register all of the hidden collectors.
|
||||
func (kr *kubeRegistry) enableHiddenCollectors() {
|
||||
if len(kr.hiddenCollectors) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
kr.hiddenCollectorsLock.Lock()
|
||||
cs := make([]Registerable, 0, len(kr.hiddenCollectors))
|
||||
|
||||
for _, c := range kr.hiddenCollectors {
|
||||
c.ClearState()
|
||||
cs = append(cs, c)
|
||||
}
|
||||
|
||||
kr.hiddenCollectors = make(map[string]Registerable)
|
||||
kr.hiddenCollectorsLock.Unlock()
|
||||
kr.MustRegister(cs...)
|
||||
}
|
||||
|
||||
// enableHiddenStableCollectors will re-register the stable collectors if there is one or more hidden metrics in it.
|
||||
// Since we can not register a metrics twice, so we have to unregister first then register again.
|
||||
func (kr *kubeRegistry) enableHiddenStableCollectors() {
|
||||
if len(kr.stableCollectors) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
kr.stableCollectorsLock.Lock()
|
||||
|
||||
cs := make([]StableCollector, 0, len(kr.stableCollectors))
|
||||
for _, c := range kr.stableCollectors {
|
||||
if len(c.HiddenMetrics()) > 0 {
|
||||
kr.Unregister(c) // unregister must happens before clear state, otherwise no metrics would be unregister
|
||||
c.ClearState()
|
||||
cs = append(cs, c)
|
||||
}
|
||||
}
|
||||
|
||||
kr.stableCollectors = nil
|
||||
kr.stableCollectorsLock.Unlock()
|
||||
kr.CustomMustRegister(cs...)
|
||||
}
|
||||
|
||||
// Reset invokes Reset on all metrics that are resettable.
|
||||
func (kr *kubeRegistry) Reset() {
|
||||
kr.resetLock.RLock()
|
||||
defer kr.resetLock.RUnlock()
|
||||
for _, r := range kr.resettables {
|
||||
r.Reset()
|
||||
}
|
||||
}
|
||||
|
||||
// BuildVersion is a helper function that can be easily mocked.
|
||||
var BuildVersion = version.Get
|
||||
|
||||
func newKubeRegistry(v apimachineryversion.Info) *kubeRegistry {
|
||||
r := &kubeRegistry{
|
||||
PromRegistry: prometheus.NewRegistry(),
|
||||
version: parseVersion(v),
|
||||
hiddenCollectors: make(map[string]Registerable),
|
||||
resettables: make([]resettable, 0),
|
||||
}
|
||||
|
||||
registriesLock.Lock()
|
||||
defer registriesLock.Unlock()
|
||||
registries = append(registries, r)
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
// NewKubeRegistry creates a new vanilla Registry
|
||||
func NewKubeRegistry() KubeRegistry {
|
||||
r := newKubeRegistry(BuildVersion())
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *kubeRegistry) RegisterMetaMetrics() {
|
||||
r.MustRegister(registeredMetricsTotal)
|
||||
r.MustRegister(disabledMetricsTotal)
|
||||
r.MustRegister(hiddenMetricsTotal)
|
||||
r.MustRegister(cardinalityEnforcementUnexpectedCategorizationsTotal)
|
||||
}
|
247
e2e/vendor/k8s.io/component-base/metrics/summary.go
generated
vendored
Normal file
247
e2e/vendor/k8s.io/component-base/metrics/summary.go
generated
vendored
Normal file
@ -0,0 +1,247 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
const (
|
||||
DefAgeBuckets = prometheus.DefAgeBuckets
|
||||
DefBufCap = prometheus.DefBufCap
|
||||
DefMaxAge = prometheus.DefMaxAge
|
||||
)
|
||||
|
||||
// Summary is our internal representation for our wrapping struct around prometheus
|
||||
// summaries. Summary implements both kubeCollector and ObserverMetric
|
||||
//
|
||||
// DEPRECATED: as per the metrics overhaul KEP
|
||||
type Summary struct {
|
||||
ObserverMetric
|
||||
*SummaryOpts
|
||||
lazyMetric
|
||||
selfCollector
|
||||
}
|
||||
|
||||
// NewSummary returns an object which is Summary-like. However, nothing
|
||||
// will be measured until the summary is registered somewhere.
|
||||
//
|
||||
// DEPRECATED: as per the metrics overhaul KEP
|
||||
func NewSummary(opts *SummaryOpts) *Summary {
|
||||
opts.StabilityLevel.setDefaults()
|
||||
|
||||
s := &Summary{
|
||||
SummaryOpts: opts,
|
||||
lazyMetric: lazyMetric{stabilityLevel: opts.StabilityLevel},
|
||||
}
|
||||
s.setPrometheusSummary(noopMetric{})
|
||||
s.lazyInit(s, BuildFQName(opts.Namespace, opts.Subsystem, opts.Name))
|
||||
return s
|
||||
}
|
||||
|
||||
// setPrometheusSummary sets the underlying KubeGauge object, i.e. the thing that does the measurement.
|
||||
func (s *Summary) setPrometheusSummary(summary prometheus.Summary) {
|
||||
s.ObserverMetric = summary
|
||||
s.initSelfCollection(summary)
|
||||
}
|
||||
|
||||
// DeprecatedVersion returns a pointer to the Version or nil
|
||||
func (s *Summary) DeprecatedVersion() *semver.Version {
|
||||
return parseSemver(s.SummaryOpts.DeprecatedVersion)
|
||||
}
|
||||
|
||||
// initializeMetric invokes the actual prometheus.Summary object instantiation
|
||||
// and stores a reference to it
|
||||
func (s *Summary) initializeMetric() {
|
||||
s.SummaryOpts.annotateStabilityLevel()
|
||||
// this actually creates the underlying prometheus gauge.
|
||||
s.setPrometheusSummary(prometheus.NewSummary(s.SummaryOpts.toPromSummaryOpts()))
|
||||
}
|
||||
|
||||
// initializeDeprecatedMetric invokes the actual prometheus.Summary object instantiation
|
||||
// but modifies the Help description prior to object instantiation.
|
||||
func (s *Summary) initializeDeprecatedMetric() {
|
||||
s.SummaryOpts.markDeprecated()
|
||||
s.initializeMetric()
|
||||
}
|
||||
|
||||
// WithContext allows the normal Summary metric to pass in context. The context is no-op now.
|
||||
func (s *Summary) WithContext(ctx context.Context) ObserverMetric {
|
||||
return s.ObserverMetric
|
||||
}
|
||||
|
||||
// SummaryVec is the internal representation of our wrapping struct around prometheus
|
||||
// summaryVecs.
|
||||
//
|
||||
// DEPRECATED: as per the metrics overhaul KEP
|
||||
type SummaryVec struct {
|
||||
*prometheus.SummaryVec
|
||||
*SummaryOpts
|
||||
lazyMetric
|
||||
originalLabels []string
|
||||
}
|
||||
|
||||
// NewSummaryVec returns an object which satisfies kubeCollector and wraps the
|
||||
// prometheus.SummaryVec object. However, the object returned will not measure
|
||||
// anything unless the collector is first registered, since the metric is lazily instantiated,
|
||||
// and only members extracted after
|
||||
// registration will actually measure anything.
|
||||
//
|
||||
// DEPRECATED: as per the metrics overhaul KEP
|
||||
func NewSummaryVec(opts *SummaryOpts, labels []string) *SummaryVec {
|
||||
opts.StabilityLevel.setDefaults()
|
||||
|
||||
fqName := BuildFQName(opts.Namespace, opts.Subsystem, opts.Name)
|
||||
|
||||
v := &SummaryVec{
|
||||
SummaryOpts: opts,
|
||||
originalLabels: labels,
|
||||
lazyMetric: lazyMetric{stabilityLevel: opts.StabilityLevel},
|
||||
}
|
||||
v.lazyInit(v, fqName)
|
||||
return v
|
||||
}
|
||||
|
||||
// DeprecatedVersion returns a pointer to the Version or nil
|
||||
func (v *SummaryVec) DeprecatedVersion() *semver.Version {
|
||||
return parseSemver(v.SummaryOpts.DeprecatedVersion)
|
||||
}
|
||||
|
||||
func (v *SummaryVec) initializeMetric() {
|
||||
v.SummaryOpts.annotateStabilityLevel()
|
||||
v.SummaryVec = prometheus.NewSummaryVec(v.SummaryOpts.toPromSummaryOpts(), v.originalLabels)
|
||||
}
|
||||
|
||||
func (v *SummaryVec) initializeDeprecatedMetric() {
|
||||
v.SummaryOpts.markDeprecated()
|
||||
v.initializeMetric()
|
||||
}
|
||||
|
||||
// Default Prometheus Vec behavior is that member extraction results in creation of a new element
|
||||
// if one with the unique label values is not found in the underlying stored metricMap.
|
||||
// This means that if this function is called but the underlying metric is not registered
|
||||
// (which means it will never be exposed externally nor consumed), the metric will exist in memory
|
||||
// for perpetuity (i.e. throughout application lifecycle).
|
||||
//
|
||||
// For reference: https://github.com/prometheus/client_golang/blob/v0.9.2/prometheus/histogram.go#L460-L470
|
||||
//
|
||||
// In contrast, the Vec behavior in this package is that member extraction before registration
|
||||
// returns a permanent noop object.
|
||||
|
||||
// WithLabelValues returns the ObserverMetric for the given slice of label
|
||||
// values (same order as the VariableLabels in Desc). If that combination of
|
||||
// label values is accessed for the first time, a new ObserverMetric is created IFF the summaryVec
|
||||
// has been registered to a metrics registry.
|
||||
func (v *SummaryVec) WithLabelValues(lvs ...string) ObserverMetric {
|
||||
if !v.IsCreated() {
|
||||
return noop
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
} else {
|
||||
v.initializeLabelAllowListsOnce.Do(func() {
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[v.FQName()]; ok {
|
||||
v.LabelValueAllowLists = allowList
|
||||
allowList.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
})
|
||||
}
|
||||
return v.SummaryVec.WithLabelValues(lvs...)
|
||||
}
|
||||
|
||||
// With returns the ObserverMetric for the given Labels map (the label names
|
||||
// must match those of the VariableLabels in Desc). If that label map is
|
||||
// accessed for the first time, a new ObserverMetric is created IFF the summaryVec has
|
||||
// been registered to a metrics registry.
|
||||
func (v *SummaryVec) With(labels map[string]string) ObserverMetric {
|
||||
if !v.IsCreated() {
|
||||
return noop
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainLabelMap(labels)
|
||||
} else {
|
||||
v.initializeLabelAllowListsOnce.Do(func() {
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[v.FQName()]; ok {
|
||||
v.LabelValueAllowLists = allowList
|
||||
allowList.ConstrainLabelMap(labels)
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
})
|
||||
}
|
||||
return v.SummaryVec.With(labels)
|
||||
}
|
||||
|
||||
// Delete deletes the metric where the variable labels are the same as those
|
||||
// passed in as labels. It returns true if a metric was deleted.
|
||||
//
|
||||
// It is not an error if the number and names of the Labels are inconsistent
|
||||
// with those of the VariableLabels in Desc. However, such inconsistent Labels
|
||||
// can never match an actual metric, so the method will always return false in
|
||||
// that case.
|
||||
func (v *SummaryVec) Delete(labels map[string]string) bool {
|
||||
if !v.IsCreated() {
|
||||
return false // since we haven't created the metric, we haven't deleted a metric with the passed in values
|
||||
}
|
||||
return v.SummaryVec.Delete(labels)
|
||||
}
|
||||
|
||||
// Reset deletes all metrics in this vector.
|
||||
func (v *SummaryVec) Reset() {
|
||||
if !v.IsCreated() {
|
||||
return
|
||||
}
|
||||
|
||||
v.SummaryVec.Reset()
|
||||
}
|
||||
|
||||
// ResetLabelAllowLists resets the label allow list for the SummaryVec.
|
||||
// NOTE: This should only be used in test.
|
||||
func (v *SummaryVec) ResetLabelAllowLists() {
|
||||
v.initializeLabelAllowListsOnce = sync.Once{}
|
||||
v.LabelValueAllowLists = nil
|
||||
}
|
||||
|
||||
// WithContext returns wrapped SummaryVec with context
|
||||
func (v *SummaryVec) WithContext(ctx context.Context) *SummaryVecWithContext {
|
||||
return &SummaryVecWithContext{
|
||||
ctx: ctx,
|
||||
SummaryVec: v,
|
||||
}
|
||||
}
|
||||
|
||||
// SummaryVecWithContext is the wrapper of SummaryVec with context.
|
||||
type SummaryVecWithContext struct {
|
||||
*SummaryVec
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
// WithLabelValues is the wrapper of SummaryVec.WithLabelValues.
|
||||
func (vc *SummaryVecWithContext) WithLabelValues(lvs ...string) ObserverMetric {
|
||||
return vc.SummaryVec.WithLabelValues(lvs...)
|
||||
}
|
||||
|
||||
// With is the wrapper of SummaryVec.With.
|
||||
func (vc *SummaryVecWithContext) With(labels map[string]string) ObserverMetric {
|
||||
return vc.SummaryVec.With(labels)
|
||||
}
|
475
e2e/vendor/k8s.io/component-base/metrics/testutil/metrics.go
generated
vendored
Normal file
475
e2e/vendor/k8s.io/component-base/metrics/testutil/metrics.go
generated
vendored
Normal file
@ -0,0 +1,475 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
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 (
|
||||
// MetricNameLabel is label under which model.Sample stores metric name
|
||||
MetricNameLabel model.LabelName = model.MetricNameLabel
|
||||
// QuantileLabel is label under which model.Sample stores latency quantile value
|
||||
QuantileLabel model.LabelName = model.QuantileLabel
|
||||
)
|
||||
|
||||
// Metrics is generic metrics for other specific metrics
|
||||
type Metrics map[string]model.Samples
|
||||
|
||||
// Equal returns true if all metrics are the same as the arguments.
|
||||
func (m *Metrics) Equal(o Metrics) bool {
|
||||
var leftKeySet []string
|
||||
var rightKeySet []string
|
||||
for k := range *m {
|
||||
leftKeySet = append(leftKeySet, k)
|
||||
}
|
||||
for k := range o {
|
||||
rightKeySet = append(rightKeySet, k)
|
||||
}
|
||||
if !reflect.DeepEqual(leftKeySet, rightKeySet) {
|
||||
return false
|
||||
}
|
||||
for _, k := range leftKeySet {
|
||||
if !(*m)[k].Equal(o[k]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// NewMetrics returns new metrics which are initialized.
|
||||
func NewMetrics() Metrics {
|
||||
result := make(Metrics)
|
||||
return result
|
||||
}
|
||||
|
||||
// ParseMetrics parses Metrics from data returned from prometheus endpoint
|
||||
func ParseMetrics(data string, output *Metrics) error {
|
||||
dec := expfmt.NewDecoder(strings.NewReader(data), expfmt.NewFormat(expfmt.TypeTextPlain))
|
||||
decoder := expfmt.SampleDecoder{
|
||||
Dec: dec,
|
||||
Opts: &expfmt.DecodeOptions{},
|
||||
}
|
||||
|
||||
for {
|
||||
var v model.Vector
|
||||
if err := decoder.Decode(&v); err != nil {
|
||||
if err == io.EOF {
|
||||
// Expected loop termination condition.
|
||||
return nil
|
||||
}
|
||||
continue
|
||||
}
|
||||
for _, metric := range v {
|
||||
name := string(metric.Metric[MetricNameLabel])
|
||||
(*output)[name] = append((*output)[name], metric)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TextToMetricFamilies reads 'in' as the simple and flat text-based exchange
|
||||
// format and creates MetricFamily proto messages. It returns the MetricFamily
|
||||
// proto messages in a map where the metric names are the keys, along with any
|
||||
// error encountered.
|
||||
func TextToMetricFamilies(in io.Reader) (map[string]*dto.MetricFamily, error) {
|
||||
var textParser expfmt.TextParser
|
||||
return textParser.TextToMetricFamilies(in)
|
||||
}
|
||||
|
||||
// PrintSample returns formatted representation of metric Sample
|
||||
func PrintSample(sample *model.Sample) string {
|
||||
buf := make([]string, 0)
|
||||
// Id is a VERY special label. For 'normal' container it's useless, but it's necessary
|
||||
// for 'system' containers (e.g. /docker-daemon, /kubelet, etc.). We know if that's the
|
||||
// case by checking if there's a label "kubernetes_container_name" present. It's hacky
|
||||
// but it works...
|
||||
_, normalContainer := sample.Metric["kubernetes_container_name"]
|
||||
for k, v := range sample.Metric {
|
||||
if strings.HasPrefix(string(k), "__") {
|
||||
continue
|
||||
}
|
||||
|
||||
if string(k) == "id" && normalContainer {
|
||||
continue
|
||||
}
|
||||
buf = append(buf, fmt.Sprintf("%v=%v", string(k), v))
|
||||
}
|
||||
return fmt.Sprintf("[%v] = %v", strings.Join(buf, ","), sample.Value)
|
||||
}
|
||||
|
||||
// ComputeHistogramDelta computes the change in histogram metric for a selected label.
|
||||
// Results are stored in after samples
|
||||
func ComputeHistogramDelta(before, after model.Samples, label model.LabelName) {
|
||||
beforeSamplesMap := make(map[string]*model.Sample)
|
||||
for _, bSample := range before {
|
||||
beforeSamplesMap[makeKey(bSample.Metric[label], bSample.Metric["le"])] = bSample
|
||||
}
|
||||
for _, aSample := range after {
|
||||
if bSample, found := beforeSamplesMap[makeKey(aSample.Metric[label], aSample.Metric["le"])]; found {
|
||||
aSample.Value = aSample.Value - bSample.Value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// 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.
|
||||
// Used only for testing purposes where we need to gather metrics directly from a running binary (without metrics endpoint).
|
||||
func GetHistogramVecFromGatherer(gatherer metrics.Gatherer, metricName string, lvMap map[string]string) (HistogramVec, error) {
|
||||
var metricFamily *dto.MetricFamily
|
||||
m, err := gatherer.Gather()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
metricFamily = findMetricFamily(m, metricName)
|
||||
|
||||
if metricFamily == nil {
|
||||
return nil, fmt.Errorf("metric %q not found", metricName)
|
||||
}
|
||||
|
||||
if len(metricFamily.GetMetric()) == 0 {
|
||||
return nil, fmt.Errorf("metric %q is empty", metricName)
|
||||
}
|
||||
|
||||
vec := make(HistogramVec, 0)
|
||||
for _, metric := range metricFamily.GetMetric() {
|
||||
if LabelsMatch(metric, lvMap) {
|
||||
if hist := metric.GetHistogram(); hist != nil {
|
||||
vec = append(vec, &Histogram{hist})
|
||||
}
|
||||
}
|
||||
}
|
||||
return vec, 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)
|
||||
}
|
||||
|
||||
if b == len(buckets)-1 && math.IsInf(buckets[b].upperBound, 1) {
|
||||
return buckets[len(buckets)-2].upperBound
|
||||
}
|
||||
|
||||
// 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 {
|
||||
var buckets []bucket
|
||||
|
||||
for _, bckt := range hist.Bucket {
|
||||
buckets = append(buckets, bucket{
|
||||
count: float64(bckt.GetCumulativeCount()),
|
||||
upperBound: bckt.GetUpperBound(),
|
||||
})
|
||||
}
|
||||
|
||||
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(hist.GetSampleCount()),
|
||||
upperBound: math.Inf(+1),
|
||||
})
|
||||
}
|
||||
|
||||
return bucketQuantile(q, buckets)
|
||||
}
|
||||
|
||||
// Average computes histogram's average value
|
||||
func (hist *Histogram) Average() float64 {
|
||||
return hist.GetSampleSum() / float64(hist.GetSampleCount())
|
||||
}
|
||||
|
||||
// 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.GetSampleCount() == 0 {
|
||||
return fmt.Errorf("nil or empty histogram SampleCount")
|
||||
}
|
||||
|
||||
if hist.SampleSum == nil || hist.GetSampleSum() == 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.GetUpperBound() < 0 {
|
||||
return fmt.Errorf("nil or negative histogram bucket UpperBound")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetGaugeMetricValue extracts 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 extracts 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 extracts 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
|
||||
}
|
||||
|
||||
// GetHistogramMetricCount extracts count of all samples from ObserverMetric
|
||||
func GetHistogramMetricCount(m metrics.ObserverMetric) (uint64, 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.GetSampleCount(), nil
|
||||
}
|
||||
|
||||
// LabelsMatch returns true if metric has all expected labels otherwise false
|
||||
func LabelsMatch(metric *dto.Metric, labelFilter map[string]string) bool {
|
||||
metricLabels := map[string]string{}
|
||||
|
||||
for _, labelPair := range metric.Label {
|
||||
metricLabels[labelPair.GetName()] = labelPair.GetValue()
|
||||
}
|
||||
|
||||
// length comparison then match key to values in the maps
|
||||
if len(labelFilter) > len(metricLabels) {
|
||||
return false
|
||||
}
|
||||
|
||||
for labelName, labelValue := range labelFilter {
|
||||
if value, ok := metricLabels[labelName]; !ok || value != labelValue {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// GetCounterVecFromGatherer collects a counter that matches the given name
|
||||
// from a gatherer implementing k8s.io/component-base/metrics.Gatherer interface.
|
||||
// It returns all counter values that had a label with a certain name in a map
|
||||
// that uses the label value as keys.
|
||||
//
|
||||
// Used only for testing purposes where we need to gather metrics directly from a running binary (without metrics endpoint).
|
||||
func GetCounterValuesFromGatherer(gatherer metrics.Gatherer, metricName string, lvMap map[string]string, labelName string) (map[string]float64, error) {
|
||||
m, err := gatherer.Gather()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
metricFamily := findMetricFamily(m, metricName)
|
||||
if metricFamily == nil {
|
||||
return nil, fmt.Errorf("metric %q not found", metricName)
|
||||
}
|
||||
if len(metricFamily.GetMetric()) == 0 {
|
||||
return nil, fmt.Errorf("metric %q is empty", metricName)
|
||||
}
|
||||
|
||||
values := make(map[string]float64)
|
||||
for _, metric := range metricFamily.GetMetric() {
|
||||
if LabelsMatch(metric, lvMap) {
|
||||
if counter := metric.GetCounter(); counter != nil {
|
||||
for _, labelPair := range metric.Label {
|
||||
if labelPair.GetName() == labelName {
|
||||
values[labelPair.GetValue()] = counter.GetValue()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return values, nil
|
||||
}
|
||||
|
||||
func findMetricFamily(metricFamilies []*dto.MetricFamily, metricName string) *dto.MetricFamily {
|
||||
for _, mFamily := range metricFamilies {
|
||||
if mFamily.GetName() == metricName {
|
||||
return mFamily
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
151
e2e/vendor/k8s.io/component-base/metrics/testutil/promlint.go
generated
vendored
Normal file
151
e2e/vendor/k8s.io/component-base/metrics/testutil/promlint.go
generated
vendored
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
Copyright 2020 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package testutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus/testutil/promlint"
|
||||
)
|
||||
|
||||
// exceptionMetrics is an exception list of metrics which violates promlint rules.
|
||||
//
|
||||
// The original entries come from the existing metrics when we introduce promlint.
|
||||
// We setup this list for allow and not fail on the current violations.
|
||||
// Generally speaking, you need to fix the problem for a new metric rather than add it into the list.
|
||||
var exceptionMetrics = []string{
|
||||
// k8s.io/apiserver/pkg/server/egressselector
|
||||
"apiserver_egress_dialer_dial_failure_count", // counter metrics should have "_total" suffix
|
||||
|
||||
// k8s.io/apiserver/pkg/server/healthz
|
||||
"apiserver_request_total", // label names should be written in 'snake_case' not 'camelCase'
|
||||
|
||||
// k8s.io/apiserver/pkg/endpoints/filters
|
||||
"authenticated_user_requests", // counter metrics should have "_total" suffix
|
||||
"authentication_attempts", // counter metrics should have "_total" suffix
|
||||
|
||||
// kube-apiserver
|
||||
"aggregator_openapi_v2_regeneration_count",
|
||||
"apiserver_admission_step_admission_duration_seconds_summary",
|
||||
"apiserver_current_inflight_requests",
|
||||
"apiserver_longrunning_gauge",
|
||||
"get_token_count",
|
||||
"get_token_fail_count",
|
||||
"ssh_tunnel_open_count",
|
||||
"ssh_tunnel_open_fail_count",
|
||||
|
||||
// kube-controller-manager
|
||||
"attachdetach_controller_forced_detaches",
|
||||
"authenticated_user_requests",
|
||||
"authentication_attempts",
|
||||
"get_token_count",
|
||||
"get_token_fail_count",
|
||||
"node_collector_evictions_number",
|
||||
}
|
||||
|
||||
// A Problem is an issue detected by a Linter.
|
||||
type Problem promlint.Problem
|
||||
|
||||
func (p *Problem) String() string {
|
||||
return fmt.Sprintf("%s:%s", p.Metric, p.Text)
|
||||
}
|
||||
|
||||
// A Linter is a Prometheus metrics linter. It identifies issues with metric
|
||||
// names, types, and metadata, and reports them to the caller.
|
||||
type Linter struct {
|
||||
promLinter *promlint.Linter
|
||||
}
|
||||
|
||||
// Lint performs a linting pass, returning a slice of Problems indicating any
|
||||
// issues found in the metrics stream. The slice is sorted by metric name
|
||||
// and issue description.
|
||||
func (l *Linter) Lint() ([]Problem, error) {
|
||||
promProblems, err := l.promLinter.Lint()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ignore problems those in exception list
|
||||
problems := make([]Problem, 0, len(promProblems))
|
||||
for i := range promProblems {
|
||||
if !l.shouldIgnore(promProblems[i].Metric) {
|
||||
problems = append(problems, Problem(promProblems[i]))
|
||||
}
|
||||
}
|
||||
|
||||
return problems, nil
|
||||
}
|
||||
|
||||
// shouldIgnore returns true if metric in the exception list, otherwise returns false.
|
||||
func (l *Linter) shouldIgnore(metricName string) bool {
|
||||
for i := range exceptionMetrics {
|
||||
if metricName == exceptionMetrics[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// NewPromLinter creates a new Linter that reads an input stream of Prometheus metrics.
|
||||
// Only the text exposition format is supported.
|
||||
func NewPromLinter(r io.Reader) *Linter {
|
||||
return &Linter{
|
||||
promLinter: promlint.New(r),
|
||||
}
|
||||
}
|
||||
|
||||
func mergeProblems(problems []Problem) string {
|
||||
var problemsMsg []string
|
||||
|
||||
for index := range problems {
|
||||
problemsMsg = append(problemsMsg, problems[index].String())
|
||||
}
|
||||
|
||||
return strings.Join(problemsMsg, ",")
|
||||
}
|
||||
|
||||
// shouldIgnore returns true if metric in the exception list, otherwise returns false.
|
||||
func shouldIgnore(metricName string) bool {
|
||||
for i := range exceptionMetrics {
|
||||
if metricName == exceptionMetrics[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// getLintError will ignore the metrics in exception list and converts lint problem to error.
|
||||
func getLintError(problems []promlint.Problem) error {
|
||||
var filteredProblems []Problem
|
||||
for _, problem := range problems {
|
||||
if shouldIgnore(problem.Metric) {
|
||||
continue
|
||||
}
|
||||
|
||||
filteredProblems = append(filteredProblems, Problem(problem))
|
||||
}
|
||||
|
||||
if len(filteredProblems) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("lint error: %s", mergeProblems(filteredProblems))
|
||||
}
|
159
e2e/vendor/k8s.io/component-base/metrics/testutil/testutil.go
generated
vendored
Normal file
159
e2e/vendor/k8s.io/component-base/metrics/testutil/testutil.go
generated
vendored
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
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"
|
||||
"k8s.io/component-base/metrics/legacyregistry"
|
||||
)
|
||||
|
||||
type TB interface {
|
||||
Logf(format string, args ...any)
|
||||
Errorf(format string, args ...any)
|
||||
Fatalf(format string, args ...any)
|
||||
}
|
||||
|
||||
// CollectAndCompare registers the provided Collector with a newly created
|
||||
// pedantic Registry. It then does the same as GatherAndCompare, gathering the
|
||||
// metrics from the pedantic Registry.
|
||||
func CollectAndCompare(c metrics.Collector, expected io.Reader, metricNames ...string) error {
|
||||
lintProblems, err := testutil.CollectAndLint(c, metricNames...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := getLintError(lintProblems); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return testutil.CollectAndCompare(c, expected, metricNames...)
|
||||
}
|
||||
|
||||
// GatherAndCompare gathers all metrics from the provided Gatherer and compares
|
||||
// it to an expected output read from the provided Reader in the Prometheus text
|
||||
// exposition format. If any metricNames are provided, only metrics with those
|
||||
// names are compared.
|
||||
func GatherAndCompare(g metrics.Gatherer, expected io.Reader, metricNames ...string) error {
|
||||
lintProblems, err := testutil.GatherAndLint(g, metricNames...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := getLintError(lintProblems); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return testutil.GatherAndCompare(g, expected, metricNames...)
|
||||
}
|
||||
|
||||
// CustomCollectAndCompare registers the provided StableCollector with a newly created
|
||||
// registry. It then does the same as GatherAndCompare, gathering the
|
||||
// metrics from the pedantic Registry.
|
||||
func CustomCollectAndCompare(c metrics.StableCollector, expected io.Reader, metricNames ...string) error {
|
||||
registry := metrics.NewKubeRegistry()
|
||||
registry.CustomMustRegister(c)
|
||||
|
||||
return GatherAndCompare(registry, expected, metricNames...)
|
||||
}
|
||||
|
||||
// ScrapeAndCompare calls a remote exporter's endpoint which is expected to return some metrics in
|
||||
// plain text format. Then it compares it with the results that the `expected` would return.
|
||||
// If the `metricNames` is not empty it would filter the comparison only to the given metric names.
|
||||
func ScrapeAndCompare(url string, expected io.Reader, metricNames ...string) error {
|
||||
return testutil.ScrapeAndCompare(url, 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()
|
||||
}
|
||||
|
||||
func AssertVectorCount(t TB, name string, labelFilter map[string]string, wantCount int) {
|
||||
metrics, err := legacyregistry.DefaultGatherer.Gather()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to gather metrics: %s", err)
|
||||
}
|
||||
|
||||
counterSum := 0
|
||||
for _, mf := range metrics {
|
||||
if mf.GetName() != name {
|
||||
continue // Ignore other metrics.
|
||||
}
|
||||
for _, metric := range mf.GetMetric() {
|
||||
if !LabelsMatch(metric, labelFilter) {
|
||||
continue
|
||||
}
|
||||
counterSum += int(metric.GetCounter().GetValue())
|
||||
}
|
||||
}
|
||||
if wantCount != counterSum {
|
||||
t.Errorf("Wanted count %d, got %d for metric %s with labels %#+v", wantCount, counterSum, name, labelFilter)
|
||||
for _, mf := range metrics {
|
||||
if mf.GetName() == name {
|
||||
for _, metric := range mf.GetMetric() {
|
||||
t.Logf("\tnear match: %s", metric.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func AssertHistogramTotalCount(t TB, name string, labelFilter map[string]string, wantCount int) {
|
||||
metrics, err := legacyregistry.DefaultGatherer.Gather()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to gather metrics: %s", err)
|
||||
}
|
||||
counterSum := 0
|
||||
for _, mf := range metrics {
|
||||
if mf.GetName() != name {
|
||||
continue // Ignore other metrics.
|
||||
}
|
||||
for _, metric := range mf.GetMetric() {
|
||||
if !LabelsMatch(metric, labelFilter) {
|
||||
continue
|
||||
}
|
||||
counterSum += int(metric.GetHistogram().GetSampleCount())
|
||||
}
|
||||
}
|
||||
if wantCount != counterSum {
|
||||
t.Errorf("Wanted count %d, got %d for metric %s with labels %#+v", wantCount, counterSum, name, labelFilter)
|
||||
for _, mf := range metrics {
|
||||
if mf.GetName() == name {
|
||||
for _, metric := range mf.GetMetric() {
|
||||
t.Logf("\tnear match: %s\n", metric.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
291
e2e/vendor/k8s.io/component-base/metrics/timing_histogram.go
generated
vendored
Normal file
291
e2e/vendor/k8s.io/component-base/metrics/timing_histogram.go
generated
vendored
Normal file
@ -0,0 +1,291 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
promext "k8s.io/component-base/metrics/prometheusextension"
|
||||
)
|
||||
|
||||
// PrometheusTimingHistogram is the abstraction of the underlying histogram
|
||||
// that we want to promote from the wrapper.
|
||||
type PrometheusTimingHistogram interface {
|
||||
GaugeMetric
|
||||
}
|
||||
|
||||
// TimingHistogram is our internal representation for our wrapping struct around
|
||||
// timing histograms. It implements both kubeCollector and GaugeMetric
|
||||
type TimingHistogram struct {
|
||||
PrometheusTimingHistogram
|
||||
*TimingHistogramOpts
|
||||
nowFunc func() time.Time
|
||||
lazyMetric
|
||||
selfCollector
|
||||
}
|
||||
|
||||
var _ GaugeMetric = &TimingHistogram{}
|
||||
var _ Registerable = &TimingHistogram{}
|
||||
var _ kubeCollector = &TimingHistogram{}
|
||||
|
||||
// NewTimingHistogram returns an object which is TimingHistogram-like. However, nothing
|
||||
// will be measured until the histogram is registered somewhere.
|
||||
func NewTimingHistogram(opts *TimingHistogramOpts) *TimingHistogram {
|
||||
return NewTestableTimingHistogram(time.Now, opts)
|
||||
}
|
||||
|
||||
// NewTestableTimingHistogram adds injection of the clock
|
||||
func NewTestableTimingHistogram(nowFunc func() time.Time, opts *TimingHistogramOpts) *TimingHistogram {
|
||||
opts.StabilityLevel.setDefaults()
|
||||
|
||||
h := &TimingHistogram{
|
||||
TimingHistogramOpts: opts,
|
||||
nowFunc: nowFunc,
|
||||
lazyMetric: lazyMetric{stabilityLevel: opts.StabilityLevel},
|
||||
}
|
||||
h.setPrometheusHistogram(noopMetric{})
|
||||
h.lazyInit(h, BuildFQName(opts.Namespace, opts.Subsystem, opts.Name))
|
||||
return h
|
||||
}
|
||||
|
||||
// setPrometheusHistogram sets the underlying KubeGauge object, i.e. the thing that does the measurement.
|
||||
func (h *TimingHistogram) setPrometheusHistogram(histogram promext.TimingHistogram) {
|
||||
h.PrometheusTimingHistogram = histogram
|
||||
h.initSelfCollection(histogram)
|
||||
}
|
||||
|
||||
// DeprecatedVersion returns a pointer to the Version or nil
|
||||
func (h *TimingHistogram) DeprecatedVersion() *semver.Version {
|
||||
return parseSemver(h.TimingHistogramOpts.DeprecatedVersion)
|
||||
}
|
||||
|
||||
// initializeMetric invokes the actual prometheus.Histogram object instantiation
|
||||
// and stores a reference to it
|
||||
func (h *TimingHistogram) initializeMetric() {
|
||||
h.TimingHistogramOpts.annotateStabilityLevel()
|
||||
// this actually creates the underlying prometheus gauge.
|
||||
histogram, err := promext.NewTestableTimingHistogram(h.nowFunc, h.TimingHistogramOpts.toPromHistogramOpts())
|
||||
if err != nil {
|
||||
panic(err) // handle as for regular histograms
|
||||
}
|
||||
h.setPrometheusHistogram(histogram)
|
||||
}
|
||||
|
||||
// initializeDeprecatedMetric invokes the actual prometheus.Histogram object instantiation
|
||||
// but modifies the Help description prior to object instantiation.
|
||||
func (h *TimingHistogram) initializeDeprecatedMetric() {
|
||||
h.TimingHistogramOpts.markDeprecated()
|
||||
h.initializeMetric()
|
||||
}
|
||||
|
||||
// WithContext allows the normal TimingHistogram metric to pass in context. The context is no-op now.
|
||||
func (h *TimingHistogram) WithContext(ctx context.Context) GaugeMetric {
|
||||
return h.PrometheusTimingHistogram
|
||||
}
|
||||
|
||||
// TimingHistogramVec is the internal representation of our wrapping struct around prometheus
|
||||
// TimingHistogramVecs.
|
||||
type TimingHistogramVec struct {
|
||||
*promext.TimingHistogramVec
|
||||
*TimingHistogramOpts
|
||||
nowFunc func() time.Time
|
||||
lazyMetric
|
||||
originalLabels []string
|
||||
}
|
||||
|
||||
var _ GaugeVecMetric = &TimingHistogramVec{}
|
||||
var _ Registerable = &TimingHistogramVec{}
|
||||
var _ kubeCollector = &TimingHistogramVec{}
|
||||
|
||||
// NewTimingHistogramVec returns an object which satisfies the kubeCollector, Registerable, and GaugeVecMetric interfaces
|
||||
// and wraps an underlying promext.TimingHistogramVec object. Note well the way that
|
||||
// behavior depends on registration and whether this is hidden.
|
||||
func NewTimingHistogramVec(opts *TimingHistogramOpts, labels []string) *TimingHistogramVec {
|
||||
return NewTestableTimingHistogramVec(time.Now, opts, labels)
|
||||
}
|
||||
|
||||
// NewTestableTimingHistogramVec adds injection of the clock.
|
||||
func NewTestableTimingHistogramVec(nowFunc func() time.Time, opts *TimingHistogramOpts, labels []string) *TimingHistogramVec {
|
||||
opts.StabilityLevel.setDefaults()
|
||||
|
||||
fqName := BuildFQName(opts.Namespace, opts.Subsystem, opts.Name)
|
||||
|
||||
v := &TimingHistogramVec{
|
||||
TimingHistogramVec: noopTimingHistogramVec,
|
||||
TimingHistogramOpts: opts,
|
||||
nowFunc: nowFunc,
|
||||
originalLabels: labels,
|
||||
lazyMetric: lazyMetric{stabilityLevel: opts.StabilityLevel},
|
||||
}
|
||||
v.lazyInit(v, fqName)
|
||||
return v
|
||||
}
|
||||
|
||||
// DeprecatedVersion returns a pointer to the Version or nil
|
||||
func (v *TimingHistogramVec) DeprecatedVersion() *semver.Version {
|
||||
return parseSemver(v.TimingHistogramOpts.DeprecatedVersion)
|
||||
}
|
||||
|
||||
func (v *TimingHistogramVec) initializeMetric() {
|
||||
v.TimingHistogramOpts.annotateStabilityLevel()
|
||||
v.TimingHistogramVec = promext.NewTestableTimingHistogramVec(v.nowFunc, v.TimingHistogramOpts.toPromHistogramOpts(), v.originalLabels...)
|
||||
}
|
||||
|
||||
func (v *TimingHistogramVec) initializeDeprecatedMetric() {
|
||||
v.TimingHistogramOpts.markDeprecated()
|
||||
v.initializeMetric()
|
||||
}
|
||||
|
||||
// WithLabelValuesChecked, if called before this vector has been registered in
|
||||
// at least one registry, will return a noop gauge and
|
||||
// an error that passes ErrIsNotRegistered.
|
||||
// If called on a hidden vector,
|
||||
// will return a noop gauge and a nil error.
|
||||
// If called with a syntactic problem in the labels, will
|
||||
// return a noop gauge and an error about the labels.
|
||||
// If none of the above apply, this method will return
|
||||
// the appropriate vector member and a nil error.
|
||||
func (v *TimingHistogramVec) WithLabelValuesChecked(lvs ...string) (GaugeMetric, error) {
|
||||
if !v.IsCreated() {
|
||||
if v.IsHidden() {
|
||||
return noop, nil
|
||||
}
|
||||
return noop, errNotRegistered
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
} else {
|
||||
v.initializeLabelAllowListsOnce.Do(func() {
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[v.FQName()]; ok {
|
||||
v.LabelValueAllowLists = allowList
|
||||
allowList.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
})
|
||||
}
|
||||
ops, err := v.TimingHistogramVec.GetMetricWithLabelValues(lvs...)
|
||||
if err != nil {
|
||||
return noop, err
|
||||
}
|
||||
return ops.(GaugeMetric), err
|
||||
}
|
||||
|
||||
// WithLabelValues calls WithLabelValuesChecked
|
||||
// and handles errors as follows.
|
||||
// An error that passes ErrIsNotRegistered is ignored
|
||||
// and the noop gauge is returned;
|
||||
// all other errors cause a panic.
|
||||
func (v *TimingHistogramVec) WithLabelValues(lvs ...string) GaugeMetric {
|
||||
ans, err := v.WithLabelValuesChecked(lvs...)
|
||||
if err == nil || ErrIsNotRegistered(err) {
|
||||
return ans
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// WithChecked, if called before this vector has been registered in
|
||||
// at least one registry, will return a noop gauge and
|
||||
// an error that passes ErrIsNotRegistered.
|
||||
// If called on a hidden vector,
|
||||
// will return a noop gauge and a nil error.
|
||||
// If called with a syntactic problem in the labels, will
|
||||
// return a noop gauge and an error about the labels.
|
||||
// If none of the above apply, this method will return
|
||||
// the appropriate vector member and a nil error.
|
||||
func (v *TimingHistogramVec) WithChecked(labels map[string]string) (GaugeMetric, error) {
|
||||
if !v.IsCreated() {
|
||||
if v.IsHidden() {
|
||||
return noop, nil
|
||||
}
|
||||
return noop, errNotRegistered
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainLabelMap(labels)
|
||||
} else {
|
||||
v.initializeLabelAllowListsOnce.Do(func() {
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[v.FQName()]; ok {
|
||||
v.LabelValueAllowLists = allowList
|
||||
allowList.ConstrainLabelMap(labels)
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
})
|
||||
}
|
||||
ops, err := v.TimingHistogramVec.GetMetricWith(labels)
|
||||
return ops.(GaugeMetric), err
|
||||
}
|
||||
|
||||
// With calls WithChecked and handles errors as follows.
|
||||
// An error that passes ErrIsNotRegistered is ignored
|
||||
// and the noop gauge is returned;
|
||||
// all other errors cause a panic.
|
||||
func (v *TimingHistogramVec) With(labels map[string]string) GaugeMetric {
|
||||
ans, err := v.WithChecked(labels)
|
||||
if err == nil || ErrIsNotRegistered(err) {
|
||||
return ans
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Delete deletes the metric where the variable labels are the same as those
|
||||
// passed in as labels. It returns true if a metric was deleted.
|
||||
//
|
||||
// It is not an error if the number and names of the Labels are inconsistent
|
||||
// with those of the VariableLabels in Desc. However, such inconsistent Labels
|
||||
// can never match an actual metric, so the method will always return false in
|
||||
// that case.
|
||||
func (v *TimingHistogramVec) Delete(labels map[string]string) bool {
|
||||
if !v.IsCreated() {
|
||||
return false // since we haven't created the metric, we haven't deleted a metric with the passed in values
|
||||
}
|
||||
return v.TimingHistogramVec.Delete(labels)
|
||||
}
|
||||
|
||||
// Reset deletes all metrics in this vector.
|
||||
func (v *TimingHistogramVec) Reset() {
|
||||
if !v.IsCreated() {
|
||||
return
|
||||
}
|
||||
|
||||
v.TimingHistogramVec.Reset()
|
||||
}
|
||||
|
||||
// ResetLabelAllowLists resets the label allow list for the TimingHistogramVec.
|
||||
// NOTE: This should only be used in test.
|
||||
func (v *TimingHistogramVec) ResetLabelAllowLists() {
|
||||
v.initializeLabelAllowListsOnce = sync.Once{}
|
||||
v.LabelValueAllowLists = nil
|
||||
}
|
||||
|
||||
// WithContext returns wrapped TimingHistogramVec with context
|
||||
func (v *TimingHistogramVec) InterfaceWithContext(ctx context.Context) GaugeVecMetric {
|
||||
return &TimingHistogramVecWithContext{
|
||||
ctx: ctx,
|
||||
TimingHistogramVec: v,
|
||||
}
|
||||
}
|
||||
|
||||
// TimingHistogramVecWithContext is the wrapper of TimingHistogramVec with context.
|
||||
// Currently the context is ignored.
|
||||
type TimingHistogramVecWithContext struct {
|
||||
*TimingHistogramVec
|
||||
ctx context.Context
|
||||
}
|
70
e2e/vendor/k8s.io/component-base/metrics/value.go
generated
vendored
Normal file
70
e2e/vendor/k8s.io/component-base/metrics/value.go
generated
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
// ValueType is an enumeration of metric types that represent a simple value.
|
||||
type ValueType int
|
||||
|
||||
// Possible values for the ValueType enum.
|
||||
const (
|
||||
_ ValueType = iota
|
||||
CounterValue
|
||||
GaugeValue
|
||||
UntypedValue
|
||||
)
|
||||
|
||||
func (vt *ValueType) toPromValueType() prometheus.ValueType {
|
||||
return prometheus.ValueType(*vt)
|
||||
}
|
||||
|
||||
// NewLazyConstMetric is a helper of MustNewConstMetric.
|
||||
//
|
||||
// Note: If the metrics described by the desc is hidden, the metrics will not be created.
|
||||
func NewLazyConstMetric(desc *Desc, valueType ValueType, value float64, labelValues ...string) Metric {
|
||||
if desc.IsHidden() {
|
||||
return nil
|
||||
}
|
||||
return prometheus.MustNewConstMetric(desc.toPrometheusDesc(), valueType.toPromValueType(), value, labelValues...)
|
||||
}
|
||||
|
||||
// NewConstMetric is a helper of NewConstMetric.
|
||||
//
|
||||
// Note: If the metrics described by the desc is hidden, the metrics will not be created.
|
||||
func NewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues ...string) (Metric, error) {
|
||||
if desc.IsHidden() {
|
||||
return nil, nil
|
||||
}
|
||||
return prometheus.NewConstMetric(desc.toPrometheusDesc(), valueType.toPromValueType(), value, labelValues...)
|
||||
}
|
||||
|
||||
// NewLazyMetricWithTimestamp is a helper of NewMetricWithTimestamp.
|
||||
//
|
||||
// Warning: the Metric 'm' must be the one created by NewLazyConstMetric(),
|
||||
// otherwise, no stability guarantees would be offered.
|
||||
func NewLazyMetricWithTimestamp(t time.Time, m Metric) Metric {
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return prometheus.NewMetricWithTimestamp(t, m)
|
||||
}
|
37
e2e/vendor/k8s.io/component-base/metrics/version.go
generated
vendored
Normal file
37
e2e/vendor/k8s.io/component-base/metrics/version.go
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import "k8s.io/component-base/version"
|
||||
|
||||
var (
|
||||
buildInfo = NewGaugeVec(
|
||||
&GaugeOpts{
|
||||
Name: "kubernetes_build_info",
|
||||
Help: "A metric with a constant '1' value labeled by major, minor, git version, git commit, git tree state, build date, Go version, and compiler from which Kubernetes was built, and platform on which it is running.",
|
||||
StabilityLevel: ALPHA,
|
||||
},
|
||||
[]string{"major", "minor", "git_version", "git_commit", "git_tree_state", "build_date", "go_version", "compiler", "platform"},
|
||||
)
|
||||
)
|
||||
|
||||
// RegisterBuildInfo registers the build and version info in a metadata metric in prometheus
|
||||
func RegisterBuildInfo(r KubeRegistry) {
|
||||
info := version.Get()
|
||||
r.MustRegister(buildInfo)
|
||||
buildInfo.WithLabelValues(info.Major, info.Minor, info.GitVersion, info.GitCommit, info.GitTreeState, info.BuildDate, info.GoVersion, info.Compiler, info.Platform).Set(1)
|
||||
}
|
50
e2e/vendor/k8s.io/component-base/metrics/version_parser.go
generated
vendored
Normal file
50
e2e/vendor/k8s.io/component-base/metrics/version_parser.go
generated
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
|
||||
apimachineryversion "k8s.io/apimachinery/pkg/version"
|
||||
)
|
||||
|
||||
const (
|
||||
versionRegexpString = `^v(\d+\.\d+\.\d+)`
|
||||
)
|
||||
|
||||
var (
|
||||
versionRe = regexp.MustCompile(versionRegexpString)
|
||||
)
|
||||
|
||||
func parseSemver(s string) *semver.Version {
|
||||
if s != "" {
|
||||
sv := semver.MustParse(s)
|
||||
return &sv
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func parseVersion(ver apimachineryversion.Info) semver.Version {
|
||||
matches := versionRe.FindAllStringSubmatch(ver.String(), -1)
|
||||
|
||||
if len(matches) != 1 {
|
||||
panic(fmt.Sprintf("version string \"%v\" doesn't match expected regular expression: \"%v\"", ver.String(), versionRe.String()))
|
||||
}
|
||||
return semver.MustParse(matches[0][1])
|
||||
}
|
167
e2e/vendor/k8s.io/component-base/metrics/wrappers.go
generated
vendored
Normal file
167
e2e/vendor/k8s.io/component-base/metrics/wrappers.go
generated
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
// This file contains a series of interfaces which we explicitly define for
|
||||
// integrating with prometheus. We redefine the interfaces explicitly here
|
||||
// so that we can prevent breakage if methods are ever added to prometheus
|
||||
// variants of them.
|
||||
|
||||
// Collector defines a subset of prometheus.Collector interface methods
|
||||
type Collector interface {
|
||||
Describe(chan<- *prometheus.Desc)
|
||||
Collect(chan<- prometheus.Metric)
|
||||
}
|
||||
|
||||
// Metric defines a subset of prometheus.Metric interface methods
|
||||
type Metric interface {
|
||||
Desc() *prometheus.Desc
|
||||
Write(*dto.Metric) error
|
||||
}
|
||||
|
||||
// CounterMetric is a Metric that represents a single numerical value that only ever
|
||||
// goes up. That implies that it cannot be used to count items whose number can
|
||||
// also go down, e.g. the number of currently running goroutines. Those
|
||||
// "counters" are represented by Gauges.
|
||||
|
||||
// CounterMetric is an interface which defines a subset of the interface provided by prometheus.Counter
|
||||
type CounterMetric interface {
|
||||
Inc()
|
||||
Add(float64)
|
||||
}
|
||||
|
||||
// CounterVecMetric is an interface which prometheus.CounterVec satisfies.
|
||||
type CounterVecMetric interface {
|
||||
WithLabelValues(...string) CounterMetric
|
||||
With(prometheus.Labels) CounterMetric
|
||||
}
|
||||
|
||||
// GaugeMetric is an interface which defines a subset of the interface provided by prometheus.Gauge
|
||||
type GaugeMetric interface {
|
||||
Set(float64)
|
||||
Inc()
|
||||
Dec()
|
||||
Add(float64)
|
||||
Write(out *dto.Metric) error
|
||||
SetToCurrentTime()
|
||||
}
|
||||
|
||||
// GaugeVecMetric is a collection of Gauges that differ only in label values.
|
||||
type GaugeVecMetric interface {
|
||||
// Default Prometheus Vec behavior is that member extraction results in creation of a new element
|
||||
// if one with the unique label values is not found in the underlying stored metricMap.
|
||||
// This means that if this function is called but the underlying metric is not registered
|
||||
// (which means it will never be exposed externally nor consumed), the metric would exist in memory
|
||||
// for perpetuity (i.e. throughout application lifecycle).
|
||||
//
|
||||
// For reference: https://github.com/prometheus/client_golang/blob/v0.9.2/prometheus/gauge.go#L190-L208
|
||||
//
|
||||
// In contrast, the Vec behavior in this package is that member extraction before registration
|
||||
// returns a permanent noop object.
|
||||
|
||||
// WithLabelValuesChecked, if called before this vector has been registered in
|
||||
// at least one registry, will return a noop gauge and
|
||||
// an error that passes ErrIsNotRegistered.
|
||||
// If called on a hidden vector,
|
||||
// will return a noop gauge and a nil error.
|
||||
// If called with a syntactic problem in the labels, will
|
||||
// return a noop gauge and an error about the labels.
|
||||
// If none of the above apply, this method will return
|
||||
// the appropriate vector member and a nil error.
|
||||
WithLabelValuesChecked(labelValues ...string) (GaugeMetric, error)
|
||||
|
||||
// WithLabelValues calls WithLabelValuesChecked
|
||||
// and handles errors as follows.
|
||||
// An error that passes ErrIsNotRegistered is ignored
|
||||
// and the noop gauge is returned;
|
||||
// all other errors cause a panic.
|
||||
WithLabelValues(labelValues ...string) GaugeMetric
|
||||
|
||||
// WithChecked, if called before this vector has been registered in
|
||||
// at least one registry, will return a noop gauge and
|
||||
// an error that passes ErrIsNotRegistered.
|
||||
// If called on a hidden vector,
|
||||
// will return a noop gauge and a nil error.
|
||||
// If called with a syntactic problem in the labels, will
|
||||
// return a noop gauge and an error about the labels.
|
||||
// If none of the above apply, this method will return
|
||||
// the appropriate vector member and a nil error.
|
||||
WithChecked(labels map[string]string) (GaugeMetric, error)
|
||||
|
||||
// With calls WithChecked and handles errors as follows.
|
||||
// An error that passes ErrIsNotRegistered is ignored
|
||||
// and the noop gauge is returned;
|
||||
// all other errors cause a panic.
|
||||
With(labels map[string]string) GaugeMetric
|
||||
|
||||
// Delete asserts that the vec should have no member for the given label set.
|
||||
// The returned bool indicates whether there was a change.
|
||||
// The return will certainly be `false` if the given label set has the wrong
|
||||
// set of label names.
|
||||
Delete(map[string]string) bool
|
||||
|
||||
// Reset removes all the members
|
||||
Reset()
|
||||
}
|
||||
|
||||
// ObserverMetric captures individual observations.
|
||||
type ObserverMetric interface {
|
||||
Observe(float64)
|
||||
}
|
||||
|
||||
// PromRegistry is an interface which implements a subset of prometheus.Registerer and
|
||||
// prometheus.Gatherer interfaces
|
||||
type PromRegistry interface {
|
||||
Register(prometheus.Collector) error
|
||||
MustRegister(...prometheus.Collector)
|
||||
Unregister(prometheus.Collector) bool
|
||||
Gather() ([]*dto.MetricFamily, error)
|
||||
}
|
||||
|
||||
// Gatherer is the interface for the part of a registry in charge of gathering
|
||||
// the collected metrics into a number of MetricFamilies.
|
||||
type Gatherer interface {
|
||||
prometheus.Gatherer
|
||||
}
|
||||
|
||||
// Registerer is the interface for the part of a registry in charge of registering
|
||||
// the collected metrics.
|
||||
type Registerer interface {
|
||||
prometheus.Registerer
|
||||
}
|
||||
|
||||
// GaugeFunc is a Gauge whose value is determined at collect time by calling a
|
||||
// provided function.
|
||||
//
|
||||
// To create GaugeFunc instances, use NewGaugeFunc.
|
||||
type GaugeFunc interface {
|
||||
Metric
|
||||
Collector
|
||||
}
|
||||
|
||||
func ErrIsNotRegistered(err error) bool {
|
||||
return err == errNotRegistered
|
||||
}
|
||||
|
||||
var errNotRegistered = errors.New("metric vec is not registered yet")
|
Reference in New Issue
Block a user