improve IAM module

Signed-off-by: hongming <talonwan@yunify.com>
This commit is contained in:
hongming
2020-05-22 09:35:05 +08:00
parent 0d12529051
commit 8f93266ec0
640 changed files with 50221 additions and 18179 deletions

View File

@@ -1,12 +1,9 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- piosz
- brancz
- sig-instrumentation-approvers
- logicalhan
reviewers:
- piosz
- brancz
- logicalhan
- sig-instrumentation-reviewers
labels:
- sig/instrumentation

148
vendor/k8s.io/component-base/metrics/collector.go generated vendored Normal file
View File

@@ -0,0 +1,148 @@
/*
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"
"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
}
// BaseStableCollector which implements almost all of the methods defined by StableCollector
// is a convenient assistant for custom collectors.
// It is recommend that inherit BaseStableCollector when implementing custom collectors.
type BaseStableCollector struct {
descriptors []*Desc // stores all Desc collected from DescribeWithStability().
registrable []*Desc // stores registrable Desc(not be hidden), 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 intend to be called by prometheus registry.
func (bsc *BaseStableCollector) Describe(ch chan<- *prometheus.Desc) {
for _, d := range bsc.registrable {
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) {
bsc.descriptors = append(bsc.descriptors, 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)
}
}
// 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 {
if version != nil {
d.determineDeprecationStatus(*version)
}
d.createOnce.Do(func() {
d.createLock.Lock()
defer d.createLock.Unlock()
if d.IsHidden() {
// do nothing for hidden metrics
} else if d.IsDeprecated() {
d.initializeDeprecatedDesc()
bsc.registrable = append(bsc.registrable, d)
d.isCreated = true
} else {
d.initialize()
bsc.registrable = append(bsc.registrable, d)
d.isCreated = true
}
})
}
if len(bsc.registrable) > 0 {
return true
}
return false
}
// Check if our BaseStableCollector implements necessary interface
var _ StableCollector = &BaseStableCollector{}

View File

@@ -34,10 +34,8 @@ type Counter struct {
// 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 {
// todo: handle defaulting better
if opts.StabilityLevel == "" {
opts.StabilityLevel = ALPHA
}
opts.StabilityLevel.setDefaults()
kc := &Counter{
CounterOpts: opts,
lazyMetric: lazyMetric{},
@@ -86,10 +84,8 @@ type CounterVec struct {
// However, the object returned will not measure anything unless the collector is first
// registered, since the metric is lazily instantiated.
func NewCounterVec(opts *CounterOpts, labels []string) *CounterVec {
// todo: handle defaulting better
if opts.StabilityLevel == "" {
opts.StabilityLevel = ALPHA
}
opts.StabilityLevel.setDefaults()
cv := &CounterVec{
CounterVec: noopCounterVec,
CounterOpts: opts,
@@ -143,7 +139,7 @@ func (v *CounterVec) WithLabelValues(lvs ...string) CounterMetric {
// 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 prometheus.Labels) CounterMetric {
func (v *CounterVec) With(labels map[string]string) CounterMetric {
if !v.IsCreated() {
return noop // return no-op counter
}
@@ -157,9 +153,18 @@ func (v *CounterVec) With(labels prometheus.Labels) CounterMetric {
// 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 prometheus.Labels) bool {
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()
}

173
vendor/k8s.io/component-base/metrics/desc.go generated vendored Normal file
View File

@@ -0,0 +1,173 @@
/*
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"
"strings"
"sync"
"github.com/blang/semver"
"github.com/prometheus/client_golang/prometheus"
"k8s.io/klog"
)
// 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
// 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,
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.
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
}
func (d *Desc) markDeprecated() {
d.deprecateOnce.Do(func() {
d.help = fmt.Sprintf("(Deprecated since %s) %s", d.deprecatedVersion, d.help)
})
}
func (d *Desc) annotateStabilityLevel() {
d.annotateOnce.Do(func() {
d.help = fmt.Sprintf("[%v] %v", d.stabilityLevel, d.help)
})
}
func (d *Desc) initialize() {
d.annotateStabilityLevel()
// this actually creates the underlying prometheus desc.
d.promDesc = prometheus.NewDesc(d.fqName, d.help, 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 {
// remove stability from help if any
stabilityStr := fmt.Sprintf("[%v] ", d.stabilityLevel)
rawHelp := strings.Replace(d.help, stabilityStr, "", -1)
return NewDesc(d.fqName, rawHelp, d.variableLabels, d.constLabels, d.stabilityLevel, d.deprecatedVersion)
}

View File

@@ -19,6 +19,8 @@ package metrics
import (
"github.com/blang/semver"
"github.com/prometheus/client_golang/prometheus"
"k8s.io/component-base/version"
)
// Gauge is our internal representation for our wrapping struct around prometheus
@@ -34,10 +36,8 @@ type Gauge struct {
// 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 {
// todo: handle defaulting better
if opts.StabilityLevel == "" {
opts.StabilityLevel = ALPHA
}
opts.StabilityLevel.setDefaults()
kc := &Gauge{
GaugeOpts: opts,
lazyMetric: lazyMetric{},
@@ -86,10 +86,8 @@ type GaugeVec struct {
// However, the object returned will not measure anything unless the collector is first
// registered, since the metric is lazily instantiated.
func NewGaugeVec(opts *GaugeOpts, labels []string) *GaugeVec {
// todo: handle defaulting better
if opts.StabilityLevel == "" {
opts.StabilityLevel = ALPHA
}
opts.StabilityLevel.setDefaults()
cv := &GaugeVec{
GaugeVec: noopGaugeVec,
GaugeOpts: opts,
@@ -142,7 +140,7 @@ func (v *GaugeVec) WithLabelValues(lvs ...string) GaugeMetric {
// 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 prometheus.Labels) GaugeMetric {
func (v *GaugeVec) With(labels map[string]string) GaugeMetric {
if !v.IsCreated() {
return noop // return no-op gauge
}
@@ -156,9 +154,40 @@ func (v *GaugeVec) With(labels prometheus.Labels) GaugeMetric {
// 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 prometheus.Labels) bool {
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()
}
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)
}

View File

@@ -21,6 +21,19 @@ 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)
}
// Histogram is our internal representation for our wrapping struct around prometheus
// histograms. Summary implements both kubeCollector and ObserverMetric
type Histogram struct {
@@ -33,10 +46,8 @@ type Histogram struct {
// NewHistogram returns an object which is Histogram-like. However, nothing
// will be measured until the histogram is registered somewhere.
func NewHistogram(opts *HistogramOpts) *Histogram {
// todo: handle defaulting better
if opts.StabilityLevel == "" {
opts.StabilityLevel = ALPHA
}
opts.StabilityLevel.setDefaults()
h := &Histogram{
HistogramOpts: opts,
lazyMetric: lazyMetric{},
@@ -85,10 +96,8 @@ type HistogramVec struct {
// prometheus.HistogramVec object. However, the object returned will not measure
// anything unless the collector is first registered, since the metric is lazily instantiated.
func NewHistogramVec(opts *HistogramOpts, labels []string) *HistogramVec {
// todo: handle defaulting better
if opts.StabilityLevel == "" {
opts.StabilityLevel = ALPHA
}
opts.StabilityLevel.setDefaults()
v := &HistogramVec{
HistogramVec: noopHistogramVec,
HistogramOpts: opts,
@@ -137,7 +146,7 @@ func (v *HistogramVec) WithLabelValues(lvs ...string) ObserverMetric {
// 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 prometheus.Labels) ObserverMetric {
func (v *HistogramVec) With(labels map[string]string) ObserverMetric {
if !v.IsCreated() {
return noop
}
@@ -151,9 +160,18 @@ func (v *HistogramVec) With(labels prometheus.Labels) ObserverMetric {
// 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 prometheus.Labels) bool {
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()
}

63
vendor/k8s.io/component-base/metrics/http.go generated vendored Normal file
View File

@@ -0,0 +1,63 @@
/*
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 (
"net/http"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
// These constants cause handlers serving metrics to behave as described if
// errors are encountered.
const (
// Serve an HTTP status code 500 upon the first error
// encountered. Report the error message in the body.
HTTPErrorOnError promhttp.HandlerErrorHandling = iota
// 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
// Panic 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 {
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())
}

22
vendor/k8s.io/component-base/metrics/labels.go generated vendored Normal file
View 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

View File

@@ -17,16 +17,18 @@ limitations under the License.
package legacyregistry
import (
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"k8s.io/component-base/metrics"
"net/http"
)
var (
defaultRegistry = metrics.NewKubeRegistry()
// DefaultGatherer exposes the global registry gatherer
DefaultGatherer prometheus.Gatherer = defaultRegistry
DefaultGatherer metrics.Gatherer = defaultRegistry
)
func init() {
@@ -41,24 +43,18 @@ func init() {
// Deprecated: Please note the issues described in the doc comment of
// InstrumentHandler. You might want to consider using promhttp.Handler instead.
func Handler() http.Handler {
return prometheus.InstrumentHandler("prometheus", promhttp.HandlerFor(defaultRegistry, promhttp.HandlerOpts{}))
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)
// sideload global prom registry as fallback
prometheus.Register(c)
return err
}
// MustRegister registers registerable metrics but uses the global registry.
func MustRegister(cs ...metrics.Registerable) {
defaultRegistry.MustRegister(cs...)
// sideload global prom registry as fallback
for _, c := range cs {
prometheus.Register(c)
}
}
// RawMustRegister registers prometheus collectors but uses the global registry, this
@@ -67,10 +63,6 @@ func MustRegister(cs ...metrics.Registerable) {
// Deprecated
func RawMustRegister(cs ...prometheus.Collector) {
defaultRegistry.RawMustRegister(cs...)
// sideload global prom registry as fallback
for _, c := range cs {
prometheus.Register(c)
}
}
// RawRegister registers a prometheus collector but uses the global registry, this
@@ -79,7 +71,24 @@ func RawMustRegister(cs ...prometheus.Collector) {
// Deprecated
func RawRegister(c prometheus.Collector) error {
err := defaultRegistry.RawRegister(c)
// sideload global prom registry as fallback
prometheus.Register(c)
return err
}
// 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)
}
}

View File

@@ -17,11 +17,13 @@ limitations under the License.
package metrics
import (
"sync"
"github.com/blang/semver"
"github.com/prometheus/client_golang/prometheus"
dto "github.com/prometheus/client_model/go"
"k8s.io/klog"
"sync"
)
/*
@@ -99,8 +101,9 @@ func (r *lazyMetric) determineDeprecationStatus(version semver.Version) {
klog.Warningf("Hidden metrics have been manually overridden, showing this very deprecated metric.")
return
}
if selfVersion.LT(version) {
klog.Warningf("This metric has been deprecated for more than one release, hiding.")
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
}
})
@@ -140,6 +143,19 @@ func (r *lazyMetric) Create(version *semver.Version) bool {
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 = *(new(sync.Once))
r.createOnce = *(new(sync.Once))
}
/*
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.

View File

@@ -18,9 +18,10 @@ package metrics
import (
"fmt"
"github.com/prometheus/client_golang/prometheus"
"sync"
"time"
"github.com/prometheus/client_golang/prometheus"
)
// KubeOpts is superset struct for prometheus.Opts. The prometheus Opts structure
@@ -34,13 +35,24 @@ type KubeOpts struct {
Subsystem string
Name string
Help string
ConstLabels prometheus.Labels
ConstLabels map[string]string
DeprecatedVersion string
deprecateOnce sync.Once
annotateOnce sync.Once
StabilityLevel StabilityLevel
}
// 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
@@ -53,6 +65,16 @@ const (
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
@@ -122,7 +144,7 @@ type HistogramOpts struct {
Subsystem string
Name string
Help string
ConstLabels prometheus.Labels
ConstLabels map[string]string
Buckets []float64
DeprecatedVersion string
deprecateOnce sync.Once
@@ -168,7 +190,7 @@ type SummaryOpts struct {
Subsystem string
Name string
Help string
ConstLabels prometheus.Labels
ConstLabels map[string]string
Objectives map[float64]float64
MaxAge time.Duration
AgeBuckets uint32
@@ -194,16 +216,28 @@ func (o *SummaryOpts) annotateStabilityLevel() {
})
}
// 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: o.Objectives,
Objectives: objectives,
MaxAge: o.MaxAge,
AgeBuckets: o.AgeBuckets,
BufCap: o.BufCap,

View File

@@ -17,11 +17,13 @@ limitations under the License.
package metrics
import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/procfs"
"k8s.io/klog"
"os"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/procfs"
"k8s.io/klog"
)
var processStartTime = prometheus.NewGaugeVec(

View File

@@ -17,6 +17,7 @@ limitations under the License.
package metrics
import (
"fmt"
"sync"
"sync/atomic"
@@ -31,13 +32,58 @@ import (
var (
showHiddenOnce sync.Once
showHidden atomic.Value
registries []*kubeRegistry // stores all registries created by NewKubeRegistry()
registriesLock sync.RWMutex
)
// 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
}
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)
if err != nil {
return []error{err}
}
return nil
}
// 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()
}
})
}
@@ -52,7 +98,12 @@ func ShouldShowHidden() bool {
// 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()
}
// KubeRegistry is an interface which implements a subset of prometheus.Registerer and
@@ -62,6 +113,8 @@ type KubeRegistry interface {
RawRegister(prometheus.Collector) error
// Deprecated
RawMustRegister(...prometheus.Collector)
CustomRegister(c StableCollector) error
CustomMustRegister(cs ...StableCollector)
Register(Registerable) error
MustRegister(...Registerable)
Unregister(Registerable) bool
@@ -73,7 +126,9 @@ type KubeRegistry interface {
// automatic behavior can be configured for metric versioning.
type kubeRegistry struct {
PromRegistry
version semver.Version
version semver.Version
hiddenCollectors []Registerable // stores all collectors that has been hidden
hiddenCollectorsLock sync.RWMutex
}
// Register registers a new Collector to be included in metrics
@@ -85,6 +140,9 @@ func (kr *kubeRegistry) Register(c Registerable) error {
if c.Create(&kr.version) {
return kr.PromRegistry.Register(c)
}
kr.trackHiddenCollector(c)
return nil
}
@@ -96,11 +154,36 @@ func (kr *kubeRegistry) MustRegister(cs ...Registerable) {
for _, c := range cs {
if c.Create(&kr.version) {
metrics = append(metrics, c)
} else {
kr.trackHiddenCollector(c)
}
}
kr.PromRegistry.MustRegister(metrics...)
}
// CustomRegister registers a new custom collector.
func (kr *kubeRegistry) CustomRegister(c StableCollector) error {
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) {
collectors := make([]prometheus.Collector, 0, len(cs))
for _, c := range cs {
if c.Create(&kr.version, c) {
collectors = append(collectors, c)
}
}
kr.PromRegistry.MustRegister(collectors...)
}
// RawRegister 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.
@@ -140,22 +223,43 @@ 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 = append(kr.hiddenCollectors, c)
}
// enableHiddenCollectors will re-register all of the hidden collectors.
func (kr *kubeRegistry) enableHiddenCollectors() {
kr.hiddenCollectorsLock.Lock()
defer kr.hiddenCollectorsLock.Unlock()
for _, c := range kr.hiddenCollectors {
c.ClearState()
kr.MustRegister(c)
}
kr.hiddenCollectors = nil
}
func newKubeRegistry(v apimachineryversion.Info) *kubeRegistry {
r := &kubeRegistry{
PromRegistry: prometheus.NewRegistry(),
version: parseVersion(v),
}
return r
}
func registerMetadataMetrics(r *kubeRegistry) {
RegisterBuildInfo(r)
registriesLock.Lock()
defer registriesLock.Unlock()
registries = append(registries, r)
return r
}
// NewKubeRegistry creates a new vanilla Registry without any Collectors
// pre-registered.
func NewKubeRegistry() KubeRegistry {
r := newKubeRegistry(version.Get())
registerMetadataMetrics(r)
return r
}

View File

@@ -37,10 +37,8 @@ type Summary struct {
//
// DEPRECATED: as per the metrics overhaul KEP
func NewSummary(opts *SummaryOpts) *Summary {
// todo: handle defaulting better
if opts.StabilityLevel == "" {
opts.StabilityLevel = ALPHA
}
opts.StabilityLevel.setDefaults()
s := &Summary{
SummaryOpts: opts,
lazyMetric: lazyMetric{},
@@ -93,10 +91,8 @@ type SummaryVec struct {
//
// DEPRECATED: as per the metrics overhaul KEP
func NewSummaryVec(opts *SummaryOpts, labels []string) *SummaryVec {
// todo: handle defaulting better
if opts.StabilityLevel == "" {
opts.StabilityLevel = ALPHA
}
opts.StabilityLevel.setDefaults()
v := &SummaryVec{
SummaryOpts: opts,
originalLabels: labels,
@@ -144,7 +140,7 @@ func (v *SummaryVec) WithLabelValues(lvs ...string) ObserverMetric {
// 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 prometheus.Labels) ObserverMetric {
func (v *SummaryVec) With(labels map[string]string) ObserverMetric {
if !v.IsCreated() {
return noop
}
@@ -158,9 +154,18 @@ func (v *SummaryVec) With(labels prometheus.Labels) ObserverMetric {
// 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 prometheus.Labels) bool {
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()
}

60
vendor/k8s.io/component-base/metrics/value.go generated vendored Normal file
View File

@@ -0,0 +1,60 @@
/*
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...)
}
// 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)
}

View File

@@ -18,9 +18,11 @@ package metrics
import (
"fmt"
"github.com/blang/semver"
apimachineryversion "k8s.io/apimachinery/pkg/version"
"regexp"
"github.com/blang/semver"
apimachineryversion "k8s.io/apimachinery/pkg/version"
)
const (

View File

@@ -18,7 +18,6 @@ package metrics
import (
"github.com/prometheus/client_golang/prometheus"
dto "github.com/prometheus/client_model/go"
)
@@ -79,3 +78,18 @@ type PromRegistry interface {
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
}
// 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
}