1
vendor/k8s.io/component-base/metrics/OWNERS
generated
vendored
1
vendor/k8s.io/component-base/metrics/OWNERS
generated
vendored
@@ -6,5 +6,6 @@ approvers:
|
||||
- RainbowMango
|
||||
reviewers:
|
||||
- sig-instrumentation-reviewers
|
||||
- YoyinZyc
|
||||
labels:
|
||||
- sig/instrumentation
|
||||
|
||||
20
vendor/k8s.io/component-base/metrics/collector.go
generated
vendored
20
vendor/k8s.io/component-base/metrics/collector.go
generated
vendored
@@ -49,10 +49,10 @@ type StableCollector interface {
|
||||
// is a convenient assistant for custom collectors.
|
||||
// It is recommend that 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().
|
||||
registrable map[string]*Desc // stores registrable 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
|
||||
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.
|
||||
@@ -64,7 +64,7 @@ func (bsc *BaseStableCollector) DescribeWithStability(ch chan<- *Desc) {
|
||||
// Describe sends all descriptors to the provided channel.
|
||||
// It intend to be called by prometheus registry.
|
||||
func (bsc *BaseStableCollector) Describe(ch chan<- *prometheus.Desc) {
|
||||
for _, d := range bsc.registrable {
|
||||
for _, d := range bsc.registerable {
|
||||
ch <- d.toPrometheusDesc()
|
||||
}
|
||||
}
|
||||
@@ -128,11 +128,11 @@ func (bsc *BaseStableCollector) init(self StableCollector) {
|
||||
}
|
||||
|
||||
func (bsc *BaseStableCollector) trackRegistrableDescriptor(d *Desc) {
|
||||
if bsc.registrable == nil {
|
||||
bsc.registrable = make(map[string]*Desc)
|
||||
if bsc.registerable == nil {
|
||||
bsc.registerable = make(map[string]*Desc)
|
||||
}
|
||||
|
||||
bsc.registrable[d.fqName] = d
|
||||
bsc.registerable[d.fqName] = d
|
||||
}
|
||||
|
||||
func (bsc *BaseStableCollector) trackHiddenDescriptor(d *Desc) {
|
||||
@@ -158,7 +158,7 @@ func (bsc *BaseStableCollector) Create(version *semver.Version, self StableColle
|
||||
}
|
||||
}
|
||||
|
||||
if len(bsc.registrable) > 0 {
|
||||
if len(bsc.registerable) > 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ func (bsc *BaseStableCollector) ClearState() {
|
||||
}
|
||||
|
||||
bsc.descriptors = nil
|
||||
bsc.registrable = nil
|
||||
bsc.registerable = nil
|
||||
bsc.hidden = nil
|
||||
bsc.self = nil
|
||||
}
|
||||
|
||||
65
vendor/k8s.io/component-base/metrics/counter.go
generated
vendored
65
vendor/k8s.io/component-base/metrics/counter.go
generated
vendored
@@ -17,8 +17,10 @@ limitations under the License.
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/blang/semver"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
// Counter is our internal representation for our wrapping struct around prometheus
|
||||
@@ -30,6 +32,9 @@ type Counter struct {
|
||||
selfCollector
|
||||
}
|
||||
|
||||
// The implementation of the Metric interface is expected by testutil.GetCounterMetricValue.
|
||||
var _ Metric = &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.
|
||||
@@ -45,6 +50,22 @@ func NewCounter(opts *CounterOpts) *Counter {
|
||||
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
|
||||
@@ -71,6 +92,11 @@ func (c *Counter) initializeDeprecatedMetric() {
|
||||
c.initializeMetric()
|
||||
}
|
||||
|
||||
// WithContext allows the normal Counter metric to pass in context. The context is no-op now.
|
||||
func (c *Counter) WithContext(ctx context.Context) CounterMetric {
|
||||
return c.CounterMetric
|
||||
}
|
||||
|
||||
// CounterVec is the internal representation of our wrapping struct around prometheus
|
||||
// counterVecs. CounterVec implements both kubeCollector and CounterVecMetric.
|
||||
type CounterVec struct {
|
||||
@@ -86,13 +112,20 @@ type CounterVec struct {
|
||||
func NewCounterVec(opts *CounterOpts, labels []string) *CounterVec {
|
||||
opts.StabilityLevel.setDefaults()
|
||||
|
||||
fqName := BuildFQName(opts.Namespace, opts.Subsystem, opts.Name)
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[fqName]; ok {
|
||||
opts.LabelValueAllowLists = allowList
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
|
||||
cv := &CounterVec{
|
||||
CounterVec: noopCounterVec,
|
||||
CounterOpts: opts,
|
||||
originalLabels: labels,
|
||||
lazyMetric: lazyMetric{},
|
||||
}
|
||||
cv.lazyInit(cv, BuildFQName(opts.Namespace, opts.Subsystem, opts.Name))
|
||||
cv.lazyInit(cv, fqName)
|
||||
return cv
|
||||
}
|
||||
|
||||
@@ -132,6 +165,9 @@ 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)
|
||||
}
|
||||
return v.CounterVec.WithLabelValues(lvs...)
|
||||
}
|
||||
|
||||
@@ -143,6 +179,9 @@ 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)
|
||||
}
|
||||
return v.CounterVec.With(labels)
|
||||
}
|
||||
|
||||
@@ -168,3 +207,27 @@ func (v *CounterVec) Reset() {
|
||||
|
||||
v.CounterVec.Reset()
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
2
vendor/k8s.io/component-base/metrics/desc.go
generated
vendored
2
vendor/k8s.io/component-base/metrics/desc.go
generated
vendored
@@ -23,7 +23,7 @@ import (
|
||||
"github.com/blang/semver"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
"k8s.io/klog"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// Desc is a prometheus.Desc extension.
|
||||
|
||||
45
vendor/k8s.io/component-base/metrics/gauge.go
generated
vendored
45
vendor/k8s.io/component-base/metrics/gauge.go
generated
vendored
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/blang/semver"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
@@ -73,6 +74,11 @@ func (g *Gauge) initializeDeprecatedMetric() {
|
||||
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 {
|
||||
@@ -88,13 +94,20 @@ type GaugeVec struct {
|
||||
func NewGaugeVec(opts *GaugeOpts, labels []string) *GaugeVec {
|
||||
opts.StabilityLevel.setDefaults()
|
||||
|
||||
fqName := BuildFQName(opts.Namespace, opts.Subsystem, opts.Name)
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[fqName]; ok {
|
||||
opts.LabelValueAllowLists = allowList
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
|
||||
cv := &GaugeVec{
|
||||
GaugeVec: noopGaugeVec,
|
||||
GaugeOpts: opts,
|
||||
originalLabels: labels,
|
||||
lazyMetric: lazyMetric{},
|
||||
}
|
||||
cv.lazyInit(cv, BuildFQName(opts.Namespace, opts.Subsystem, opts.Name))
|
||||
cv.lazyInit(cv, fqName)
|
||||
return cv
|
||||
}
|
||||
|
||||
@@ -133,6 +146,9 @@ func (v *GaugeVec) WithLabelValues(lvs ...string) GaugeMetric {
|
||||
if !v.IsCreated() {
|
||||
return noop // return no-op gauge
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
}
|
||||
return v.GaugeVec.WithLabelValues(lvs...)
|
||||
}
|
||||
|
||||
@@ -144,6 +160,9 @@ func (v *GaugeVec) With(labels map[string]string) GaugeMetric {
|
||||
if !v.IsCreated() {
|
||||
return noop // return no-op gauge
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainLabelMap(labels)
|
||||
}
|
||||
return v.GaugeVec.With(labels)
|
||||
}
|
||||
|
||||
@@ -191,3 +210,27 @@ func NewGaugeFunc(opts GaugeOpts, function func() float64) GaugeFunc {
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
45
vendor/k8s.io/component-base/metrics/histogram.go
generated
vendored
45
vendor/k8s.io/component-base/metrics/histogram.go
generated
vendored
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/blang/semver"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
@@ -83,6 +84,11 @@ func (h *Histogram) initializeDeprecatedMetric() {
|
||||
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 {
|
||||
return h.ObserverMetric
|
||||
}
|
||||
|
||||
// HistogramVec is the internal representation of our wrapping struct around prometheus
|
||||
// histogramVecs.
|
||||
type HistogramVec struct {
|
||||
@@ -98,13 +104,20 @@ type HistogramVec struct {
|
||||
func NewHistogramVec(opts *HistogramOpts, labels []string) *HistogramVec {
|
||||
opts.StabilityLevel.setDefaults()
|
||||
|
||||
fqName := BuildFQName(opts.Namespace, opts.Subsystem, opts.Name)
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[fqName]; ok {
|
||||
opts.LabelValueAllowLists = allowList
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
|
||||
v := &HistogramVec{
|
||||
HistogramVec: noopHistogramVec,
|
||||
HistogramOpts: opts,
|
||||
originalLabels: labels,
|
||||
lazyMetric: lazyMetric{},
|
||||
}
|
||||
v.lazyInit(v, BuildFQName(opts.Namespace, opts.Subsystem, opts.Name))
|
||||
v.lazyInit(v, fqName)
|
||||
return v
|
||||
}
|
||||
|
||||
@@ -139,6 +152,9 @@ func (v *HistogramVec) WithLabelValues(lvs ...string) ObserverMetric {
|
||||
if !v.IsCreated() {
|
||||
return noop
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
}
|
||||
return v.HistogramVec.WithLabelValues(lvs...)
|
||||
}
|
||||
|
||||
@@ -150,6 +166,9 @@ func (v *HistogramVec) With(labels map[string]string) ObserverMetric {
|
||||
if !v.IsCreated() {
|
||||
return noop
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainLabelMap(labels)
|
||||
}
|
||||
return v.HistogramVec.With(labels)
|
||||
}
|
||||
|
||||
@@ -175,3 +194,27 @@ func (v *HistogramVec) Reset() {
|
||||
|
||||
v.HistogramVec.Reset()
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// WithLabelValues is the wrapper of HistogramVec.WithLabelValues.
|
||||
func (vc *HistogramVecWithContext) WithLabelValues(lvs ...string) ObserverMetric {
|
||||
return vc.HistogramVec.WithLabelValues(lvs...)
|
||||
}
|
||||
|
||||
// With is the wrapper of HistogramVec.With.
|
||||
func (vc *HistogramVecWithContext) With(labels map[string]string) ObserverMetric {
|
||||
return vc.HistogramVec.With(labels)
|
||||
}
|
||||
|
||||
14
vendor/k8s.io/component-base/metrics/http.go
generated
vendored
14
vendor/k8s.io/component-base/metrics/http.go
generated
vendored
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
@@ -61,3 +62,16 @@ func (ho *HandlerOpts) toPromhttpHandlerOpts() promhttp.HandlerOpts {
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
35
vendor/k8s.io/component-base/metrics/legacyregistry/registry.go
generated
vendored
35
vendor/k8s.io/component-base/metrics/legacyregistry/registry.go
generated
vendored
@@ -29,6 +29,18 @@ 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
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -46,23 +58,12 @@ func Handler() http.Handler {
|
||||
return promhttp.InstrumentMetricHandler(prometheus.DefaultRegisterer, promhttp.HandlerFor(defaultRegistry, promhttp.HandlerOpts{}))
|
||||
}
|
||||
|
||||
// Register registers a collectable metric but uses the global registry
|
||||
func Register(c metrics.Registerable) error {
|
||||
err := defaultRegistry.Register(c)
|
||||
return err
|
||||
}
|
||||
|
||||
// MustRegister registers registerable metrics but uses the global registry.
|
||||
func MustRegister(cs ...metrics.Registerable) {
|
||||
defaultRegistry.MustRegister(cs...)
|
||||
}
|
||||
|
||||
// RawMustRegister registers prometheus collectors but uses the global registry, this
|
||||
// bypasses the metric stability framework
|
||||
//
|
||||
// Deprecated
|
||||
func RawMustRegister(cs ...prometheus.Collector) {
|
||||
defaultRegistry.RawMustRegister(cs...)
|
||||
// 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{}))
|
||||
}
|
||||
|
||||
// CustomRegister registers a custom collector but uses the global registry.
|
||||
|
||||
28
vendor/k8s.io/component-base/metrics/metric.go
generated
vendored
28
vendor/k8s.io/component-base/metrics/metric.go
generated
vendored
@@ -23,7 +23,7 @@ import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
|
||||
"k8s.io/klog"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
/*
|
||||
@@ -87,10 +87,24 @@ func (r *lazyMetric) lazyInit(self kubeCollector, fqName string) {
|
||||
r.self = self
|
||||
}
|
||||
|
||||
// determineDeprecationStatus figures out whether the lazy metric should be deprecated or not.
|
||||
// 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.
|
||||
func (r *lazyMetric) determineDeprecationStatus(version semver.Version) {
|
||||
// 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
|
||||
@@ -99,6 +113,7 @@ func (r *lazyMetric) determineDeprecationStatus(version semver.Version) {
|
||||
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
|
||||
@@ -126,7 +141,7 @@ func (r *lazyMetric) IsDeprecated() bool {
|
||||
// created.
|
||||
func (r *lazyMetric) Create(version *semver.Version) bool {
|
||||
if version != nil {
|
||||
r.determineDeprecationStatus(*version)
|
||||
r.preprocessMetric(*version)
|
||||
}
|
||||
// let's not create if this metric is slated to be hidden
|
||||
if r.IsHidden() {
|
||||
@@ -188,9 +203,6 @@ func (c *selfCollector) Collect(ch chan<- prometheus.Metric) {
|
||||
// no-op vecs for convenience
|
||||
var noopCounterVec = &prometheus.CounterVec{}
|
||||
var noopHistogramVec = &prometheus.HistogramVec{}
|
||||
|
||||
// lint:ignore U1000 Keep it for future use
|
||||
var noopSummaryVec = &prometheus.SummaryVec{}
|
||||
var noopGaugeVec = &prometheus.GaugeVec{}
|
||||
var noopObserverVec = &noopObserverVector{}
|
||||
|
||||
|
||||
125
vendor/k8s.io/component-base/metrics/options.go
generated
vendored
Normal file
125
vendor/k8s.io/component-base/metrics/options.go
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
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"
|
||||
"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
|
||||
}
|
||||
|
||||
// NewOptions returns default metrics options
|
||||
func NewOptions() *Options {
|
||||
return &Options{}
|
||||
}
|
||||
|
||||
// Validate validates metrics flags options.
|
||||
func (o *Options) Validate() []error {
|
||||
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 {
|
||||
o = NewOptions()
|
||||
}
|
||||
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'.")
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
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 has a list of kv pair with format `metricName:labelName=labelValue, labelValue,...`")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
126
vendor/k8s.io/component-base/metrics/opts.go
generated
vendored
126
vendor/k8s.io/component-base/metrics/opts.go
generated
vendored
@@ -18,10 +18,17 @@ package metrics
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
)
|
||||
|
||||
var (
|
||||
labelValueAllowLists = map[string]*MetricLabelAllowList{}
|
||||
allowListLock sync.RWMutex
|
||||
)
|
||||
|
||||
// KubeOpts is superset struct for prometheus.Opts. The prometheus Opts structure
|
||||
@@ -31,15 +38,16 @@ import (
|
||||
// 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
|
||||
Namespace string
|
||||
Subsystem string
|
||||
Name string
|
||||
Help string
|
||||
ConstLabels map[string]string
|
||||
DeprecatedVersion string
|
||||
deprecateOnce sync.Once
|
||||
annotateOnce sync.Once
|
||||
StabilityLevel StabilityLevel
|
||||
LabelValueAllowLists *MetricLabelAllowList
|
||||
}
|
||||
|
||||
// BuildFQName joins the given three name components by "_". Empty name
|
||||
@@ -125,7 +133,7 @@ func (o *GaugeOpts) annotateStabilityLevel() {
|
||||
|
||||
// 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 {
|
||||
func (o *GaugeOpts) toPromGaugeOpts() prometheus.GaugeOpts {
|
||||
return prometheus.GaugeOpts{
|
||||
Namespace: o.Namespace,
|
||||
Subsystem: o.Subsystem,
|
||||
@@ -140,16 +148,17 @@ func (o GaugeOpts) toPromGaugeOpts() prometheus.GaugeOpts {
|
||||
// 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
|
||||
Namespace string
|
||||
Subsystem string
|
||||
Name string
|
||||
Help string
|
||||
ConstLabels map[string]string
|
||||
Buckets []float64
|
||||
DeprecatedVersion string
|
||||
deprecateOnce sync.Once
|
||||
annotateOnce sync.Once
|
||||
StabilityLevel StabilityLevel
|
||||
LabelValueAllowLists *MetricLabelAllowList
|
||||
}
|
||||
|
||||
// Modify help description on the metric description.
|
||||
@@ -169,7 +178,7 @@ func (o *HistogramOpts) annotateStabilityLevel() {
|
||||
|
||||
// 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 {
|
||||
func (o *HistogramOpts) toPromHistogramOpts() prometheus.HistogramOpts {
|
||||
return prometheus.HistogramOpts{
|
||||
Namespace: o.Namespace,
|
||||
Subsystem: o.Subsystem,
|
||||
@@ -186,19 +195,20 @@ func (o HistogramOpts) toPromHistogramOpts() prometheus.HistogramOpts {
|
||||
// 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
|
||||
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
|
||||
LabelValueAllowLists *MetricLabelAllowList
|
||||
}
|
||||
|
||||
// Modify help description on the metric description.
|
||||
@@ -224,7 +234,7 @@ var (
|
||||
|
||||
// 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 {
|
||||
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
|
||||
@@ -243,3 +253,49 @@ func (o SummaryOpts) toPromSummaryOpts() prometheus.SummaryOpts {
|
||||
BufCap: o.BufCap,
|
||||
}
|
||||
}
|
||||
|
||||
type MetricLabelAllowList struct {
|
||||
labelToAllowList map[string]sets.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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.NewString(strings.Split(labelValues, ",")...)
|
||||
|
||||
allowList, ok := labelValueAllowLists[metricName]
|
||||
if ok {
|
||||
allowList.labelToAllowList[labelName] = valueSet
|
||||
} else {
|
||||
labelToAllowList := make(map[string]sets.String)
|
||||
labelToAllowList[labelName] = valueSet
|
||||
labelValueAllowLists[metricName] = &MetricLabelAllowList{
|
||||
labelToAllowList,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
26
vendor/k8s.io/component-base/metrics/processstarttime.go
generated
vendored
26
vendor/k8s.io/component-base/metrics/processstarttime.go
generated
vendored
@@ -17,12 +17,9 @@ limitations under the License.
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/procfs"
|
||||
|
||||
"k8s.io/klog"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
var processStartTime = NewGaugeVec(
|
||||
@@ -43,19 +40,12 @@ func RegisterProcessStartTime(registrationFunc func(Registerable) error) error {
|
||||
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 registrationFunc(processStartTime)
|
||||
}
|
||||
|
||||
func getProcessStart() (float64, error) {
|
||||
pid := os.Getpid()
|
||||
p, err := procfs.NewProc(pid)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if stat, err := p.NewStat(); err == nil {
|
||||
return stat.StartTime()
|
||||
}
|
||||
return 0, err
|
||||
return nil
|
||||
}
|
||||
|
||||
38
vendor/k8s.io/component-base/metrics/processstarttime_others.go
generated
vendored
Normal file
38
vendor/k8s.io/component-base/metrics/processstarttime_others.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
// +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
|
||||
}
|
||||
33
vendor/k8s.io/component-base/metrics/processstarttime_windows.go
generated
vendored
Normal file
33
vendor/k8s.io/component-base/metrics/processstarttime_windows.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
// +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
|
||||
}
|
||||
130
vendor/k8s.io/component-base/metrics/prometheus/workqueue/metrics.go
generated
vendored
Normal file
130
vendor/k8s.io/component-base/metrics/prometheus/workqueue/metrics.go
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
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,
|
||||
Help: "Current depth of workqueue",
|
||||
}, []string{"name"})
|
||||
|
||||
adds = k8smetrics.NewCounterVec(&k8smetrics.CounterOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: AddsKey,
|
||||
Help: "Total number of adds handled by workqueue",
|
||||
}, []string{"name"})
|
||||
|
||||
latency = k8smetrics.NewHistogramVec(&k8smetrics.HistogramOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: QueueLatencyKey,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
Help: "How many seconds has the longest running " +
|
||||
"processor for workqueue been running.",
|
||||
}, []string{"name"})
|
||||
|
||||
retries = k8smetrics.NewCounterVec(&k8smetrics.CounterOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: RetriesKey,
|
||||
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)
|
||||
}
|
||||
76
vendor/k8s.io/component-base/metrics/registry.go
generated
vendored
76
vendor/k8s.io/component-base/metrics/registry.go
generated
vendored
@@ -30,10 +30,12 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
showHiddenOnce sync.Once
|
||||
showHidden atomic.Value
|
||||
registries []*kubeRegistry // stores all registries created by NewKubeRegistry()
|
||||
registriesLock sync.RWMutex
|
||||
showHiddenOnce sync.Once
|
||||
disabledMetricsLock sync.RWMutex
|
||||
showHidden atomic.Value
|
||||
registries []*kubeRegistry // stores all registries created by NewKubeRegistry()
|
||||
registriesLock sync.RWMutex
|
||||
disabledMetrics = map[string]struct{}{}
|
||||
)
|
||||
|
||||
// shouldHide be used to check if a specific metric with deprecated version should be hidden
|
||||
@@ -51,19 +53,6 @@ func shouldHide(currentVersion *semver.Version, deprecatedVersion *semver.Versio
|
||||
return false
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// ValidateShowHiddenMetricsVersion checks invalid version for which show hidden metrics.
|
||||
func ValidateShowHiddenMetricsVersion(v string) []error {
|
||||
err := validateShowHiddenMetricsVersion(parseVersion(version.Get()), v)
|
||||
@@ -74,6 +63,12 @@ func ValidateShowHiddenMetricsVersion(v string) []error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetDisabledMetric(name string) {
|
||||
disabledMetricsLock.Lock()
|
||||
defer disabledMetricsLock.Unlock()
|
||||
disabledMetrics[name] = struct{}{}
|
||||
}
|
||||
|
||||
// SetShowHidden will enable showing hidden metrics. This will no-opt
|
||||
// after the initial call
|
||||
func SetShowHidden() {
|
||||
@@ -110,17 +105,30 @@ type Registerable interface {
|
||||
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()
|
||||
}
|
||||
|
||||
// kubeRegistry is a wrapper around a prometheus registry-type object. Upon initialization
|
||||
@@ -133,6 +141,8 @@ type kubeRegistry struct {
|
||||
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
|
||||
@@ -142,11 +152,11 @@ type kubeRegistry struct {
|
||||
// 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
|
||||
}
|
||||
|
||||
@@ -158,6 +168,7 @@ func (kr *kubeRegistry) MustRegister(cs ...Registerable) {
|
||||
for _, c := range cs {
|
||||
if c.Create(&kr.version) {
|
||||
metrics = append(metrics, c)
|
||||
kr.addResettable(c)
|
||||
} else {
|
||||
kr.trackHiddenCollector(c)
|
||||
}
|
||||
@@ -168,7 +179,7 @@ func (kr *kubeRegistry) MustRegister(cs ...Registerable) {
|
||||
// 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)
|
||||
}
|
||||
@@ -180,14 +191,13 @@ func (kr *kubeRegistry) CustomRegister(c StableCollector) error {
|
||||
// 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...)
|
||||
}
|
||||
|
||||
@@ -198,6 +208,19 @@ func (kr *kubeRegistry) CustomMustRegister(cs ...StableCollector) {
|
||||
// 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
|
||||
@@ -279,6 +302,15 @@ func (kr *kubeRegistry) enableHiddenStableCollectors() {
|
||||
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
|
||||
|
||||
@@ -287,6 +319,7 @@ func newKubeRegistry(v apimachineryversion.Info) *kubeRegistry {
|
||||
PromRegistry: prometheus.NewRegistry(),
|
||||
version: parseVersion(v),
|
||||
hiddenCollectors: make(map[string]Registerable),
|
||||
resettables: make([]resettable, 0),
|
||||
}
|
||||
|
||||
registriesLock.Lock()
|
||||
@@ -300,6 +333,5 @@ func newKubeRegistry(v apimachineryversion.Info) *kubeRegistry {
|
||||
// pre-registered.
|
||||
func NewKubeRegistry() KubeRegistry {
|
||||
r := newKubeRegistry(BuildVersion())
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
45
vendor/k8s.io/component-base/metrics/summary.go
generated
vendored
45
vendor/k8s.io/component-base/metrics/summary.go
generated
vendored
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/blang/semver"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
@@ -74,6 +75,11 @@ func (s *Summary) initializeDeprecatedMetric() {
|
||||
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.
|
||||
//
|
||||
@@ -93,12 +99,19 @@ type SummaryVec struct {
|
||||
func NewSummaryVec(opts *SummaryOpts, labels []string) *SummaryVec {
|
||||
opts.StabilityLevel.setDefaults()
|
||||
|
||||
fqName := BuildFQName(opts.Namespace, opts.Subsystem, opts.Name)
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[fqName]; ok {
|
||||
opts.LabelValueAllowLists = allowList
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
|
||||
v := &SummaryVec{
|
||||
SummaryOpts: opts,
|
||||
originalLabels: labels,
|
||||
lazyMetric: lazyMetric{},
|
||||
}
|
||||
v.lazyInit(v, BuildFQName(opts.Namespace, opts.Subsystem, opts.Name))
|
||||
v.lazyInit(v, fqName)
|
||||
return v
|
||||
}
|
||||
|
||||
@@ -133,6 +146,9 @@ func (v *SummaryVec) WithLabelValues(lvs ...string) ObserverMetric {
|
||||
if !v.IsCreated() {
|
||||
return noop
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
}
|
||||
return v.SummaryVec.WithLabelValues(lvs...)
|
||||
}
|
||||
|
||||
@@ -144,6 +160,9 @@ func (v *SummaryVec) With(labels map[string]string) ObserverMetric {
|
||||
if !v.IsCreated() {
|
||||
return noop
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainLabelMap(labels)
|
||||
}
|
||||
return v.SummaryVec.With(labels)
|
||||
}
|
||||
|
||||
@@ -169,3 +188,27 @@ func (v *SummaryVec) Reset() {
|
||||
|
||||
v.SummaryVec.Reset()
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
129
vendor/k8s.io/component-base/metrics/testutil/metrics.go
generated
vendored
129
vendor/k8s.io/component-base/metrics/testutil/metrics.go
generated
vendored
@@ -43,8 +43,8 @@ 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 {
|
||||
leftKeySet := []string{}
|
||||
rightKeySet := []string{}
|
||||
var leftKeySet []string
|
||||
var rightKeySet []string
|
||||
for k := range *m {
|
||||
leftKeySet = append(leftKeySet, k)
|
||||
}
|
||||
@@ -86,35 +86,22 @@ func ParseMetrics(data string, output *Metrics) error {
|
||||
continue
|
||||
}
|
||||
for _, metric := range v {
|
||||
name := string(metric.Metric[model.MetricNameLabel])
|
||||
name := string(metric.Metric[MetricNameLabel])
|
||||
(*output)[name] = append((*output)[name], metric)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ExtractMetricSamples parses the prometheus metric samples from the input string.
|
||||
func ExtractMetricSamples(metricsBlob string) ([]*model.Sample, error) {
|
||||
dec := expfmt.NewDecoder(strings.NewReader(metricsBlob), expfmt.FmtText)
|
||||
decoder := expfmt.SampleDecoder{
|
||||
Dec: dec,
|
||||
Opts: &expfmt.DecodeOptions{},
|
||||
}
|
||||
|
||||
var samples []*model.Sample
|
||||
for {
|
||||
var v model.Vector
|
||||
if err := decoder.Decode(&v); err != nil {
|
||||
if err == io.EOF {
|
||||
// Expected loop termination condition.
|
||||
return samples, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
samples = append(samples, v...)
|
||||
}
|
||||
// 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 formated representation of metric Sample
|
||||
// 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
|
||||
@@ -198,22 +185,22 @@ func GetHistogramFromGatherer(gatherer metrics.Gatherer, metricName string) (His
|
||||
return Histogram{}, err
|
||||
}
|
||||
for _, mFamily := range m {
|
||||
if mFamily.Name != nil && *mFamily.Name == metricName {
|
||||
if mFamily.GetName() == metricName {
|
||||
metricFamily = mFamily
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if metricFamily == nil {
|
||||
return Histogram{}, fmt.Errorf("Metric %q not found", metricName)
|
||||
return Histogram{}, fmt.Errorf("metric %q not found", metricName)
|
||||
}
|
||||
|
||||
if metricFamily.GetMetric() == nil {
|
||||
return Histogram{}, fmt.Errorf("Metric %q is empty", metricName)
|
||||
return Histogram{}, fmt.Errorf("metric %q is empty", metricName)
|
||||
}
|
||||
|
||||
if len(metricFamily.GetMetric()) == 0 {
|
||||
return Histogram{}, fmt.Errorf("Metric %q is empty", metricName)
|
||||
return Histogram{}, fmt.Errorf("metric %q is empty", metricName)
|
||||
}
|
||||
|
||||
return Histogram{
|
||||
@@ -253,6 +240,10 @@ func bucketQuantile(q float64, buckets []bucket) float64 {
|
||||
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
|
||||
@@ -264,48 +255,39 @@ func bucketQuantile(q float64, buckets []bucket) float64 {
|
||||
// Quantile computes q-th quantile of a cumulative histogram.
|
||||
// It's expected the histogram is valid (by calling Validate)
|
||||
func (hist *Histogram) Quantile(q float64) float64 {
|
||||
buckets := []bucket{}
|
||||
var buckets []bucket
|
||||
|
||||
for _, bckt := range hist.Bucket {
|
||||
buckets = append(buckets, bucket{
|
||||
count: float64(*bckt.CumulativeCount),
|
||||
upperBound: *bckt.UpperBound,
|
||||
count: float64(bckt.GetCumulativeCount()),
|
||||
upperBound: bckt.GetUpperBound(),
|
||||
})
|
||||
}
|
||||
|
||||
// bucketQuantile expects the upper bound of the last bucket to be +inf
|
||||
// buckets[len(buckets)-1].upperBound = math.Inf(+1)
|
||||
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 reset 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.SampleSum / float64(*hist.SampleCount)
|
||||
}
|
||||
|
||||
// Clear clears all fields of the wrapped histogram
|
||||
func (hist *Histogram) Clear() {
|
||||
if hist.SampleCount != nil {
|
||||
*hist.SampleCount = 0
|
||||
}
|
||||
if hist.SampleSum != nil {
|
||||
*hist.SampleSum = 0
|
||||
}
|
||||
for _, b := range hist.Bucket {
|
||||
if b.CumulativeCount != nil {
|
||||
*b.CumulativeCount = 0
|
||||
}
|
||||
}
|
||||
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.SampleCount == 0 {
|
||||
if hist.SampleCount == nil || hist.GetSampleCount() == 0 {
|
||||
return fmt.Errorf("nil or empty histogram SampleCount")
|
||||
}
|
||||
|
||||
if hist.SampleSum == nil || *hist.SampleSum == 0 {
|
||||
if hist.SampleSum == nil || hist.GetSampleSum() == 0 {
|
||||
return fmt.Errorf("nil or empty histogram SampleSum")
|
||||
}
|
||||
|
||||
@@ -313,7 +295,7 @@ func (hist *Histogram) Validate() error {
|
||||
if bckt == nil {
|
||||
return fmt.Errorf("empty histogram bucket")
|
||||
}
|
||||
if bckt.UpperBound == nil || *bckt.UpperBound < 0 {
|
||||
if bckt.UpperBound == nil || bckt.GetUpperBound() < 0 {
|
||||
return fmt.Errorf("nil or negative histogram bucket UpperBound")
|
||||
}
|
||||
}
|
||||
@@ -321,29 +303,60 @@ func (hist *Histogram) Validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetGaugeMetricValue extract metric value from GaugeMetric
|
||||
// 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 0, fmt.Errorf("error writing m: %v", err)
|
||||
}
|
||||
return metricProto.Gauge.GetValue(), nil
|
||||
}
|
||||
|
||||
// GetCounterMetricValue extract metric value from CounterMetric
|
||||
// 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 0, fmt.Errorf("error writing m: %v", err)
|
||||
}
|
||||
return metricProto.Counter.GetValue(), nil
|
||||
}
|
||||
|
||||
// GetHistogramMetricValue extract sum of all samples from ObserverMetric
|
||||
// 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 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
|
||||
}
|
||||
|
||||
156
vendor/k8s.io/component-base/metrics/testutil/promlint.go
generated
vendored
Normal file
156
vendor/k8s.io/component-base/metrics/testutil/promlint.go
generated
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
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/kubernetes/vendor/k8s.io/apiserver/pkg/server/egressselector
|
||||
"apiserver_egress_dialer_dial_failure_count", // counter metrics should have "_total" suffix
|
||||
|
||||
// k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/server/healthz
|
||||
"apiserver_request_total", // label names should be written in 'snake_case' not 'camelCase'
|
||||
|
||||
// k8s.io/kubernetes/vendor/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",
|
||||
|
||||
// k8s.io/kubernetes/pkg/kubelet/server/stats
|
||||
// The two metrics have been deprecated and will be removed in release v1.20+.
|
||||
"container_cpu_usage_seconds_total", // non-counter metrics should not have "_total" suffix
|
||||
"node_cpu_usage_seconds_total", // non-counter metrics should not have "_total" suffix
|
||||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
16
vendor/k8s.io/component-base/metrics/testutil/testutil.go
generated
vendored
16
vendor/k8s.io/component-base/metrics/testutil/testutil.go
generated
vendored
@@ -30,6 +30,14 @@ import (
|
||||
// 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...)
|
||||
}
|
||||
|
||||
@@ -38,6 +46,14 @@ func CollectAndCompare(c metrics.Collector, expected io.Reader, metricNames ...s
|
||||
// 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...)
|
||||
}
|
||||
|
||||
|
||||
2
vendor/k8s.io/component-base/metrics/version.go
generated
vendored
2
vendor/k8s.io/component-base/metrics/version.go
generated
vendored
@@ -25,7 +25,7 @@ var (
|
||||
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", "gitVersion", "gitCommit", "gitTreeState", "buildDate", "goVersion", "compiler", "platform"},
|
||||
[]string{"major", "minor", "git_version", "git_commit", "git_tree_state", "build_date", "go_version", "compiler", "platform"},
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user