mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 10:51:29 +00:00
allow explicit disabling of metrics as an escape hatch.
Change-Id: I92895987d140e0e94eea3e4dea872c298d82babb
This commit is contained in:
parent
033d950152
commit
0e32c43e07
@ -49,10 +49,10 @@ type StableCollector interface {
|
|||||||
// is a convenient assistant for custom collectors.
|
// is a convenient assistant for custom collectors.
|
||||||
// It is recommend that inherit BaseStableCollector when implementing custom collectors.
|
// It is recommend that inherit BaseStableCollector when implementing custom collectors.
|
||||||
type BaseStableCollector struct {
|
type BaseStableCollector struct {
|
||||||
descriptors map[string]*Desc // stores all descriptors by pair<fqName, Desc>, these are collected from DescribeWithStability().
|
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.
|
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.
|
hidden map[string]*Desc // stores hidden descriptors by pair<fqName, Desc>, is a subset of descriptors.
|
||||||
self StableCollector
|
self StableCollector
|
||||||
}
|
}
|
||||||
|
|
||||||
// DescribeWithStability sends all descriptors to the provided channel.
|
// 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.
|
// Describe sends all descriptors to the provided channel.
|
||||||
// It intend to be called by prometheus registry.
|
// It intend to be called by prometheus registry.
|
||||||
func (bsc *BaseStableCollector) Describe(ch chan<- *prometheus.Desc) {
|
func (bsc *BaseStableCollector) Describe(ch chan<- *prometheus.Desc) {
|
||||||
for _, d := range bsc.registrable {
|
for _, d := range bsc.registerable {
|
||||||
ch <- d.toPrometheusDesc()
|
ch <- d.toPrometheusDesc()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,11 +128,11 @@ func (bsc *BaseStableCollector) init(self StableCollector) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (bsc *BaseStableCollector) trackRegistrableDescriptor(d *Desc) {
|
func (bsc *BaseStableCollector) trackRegistrableDescriptor(d *Desc) {
|
||||||
if bsc.registrable == nil {
|
if bsc.registerable == nil {
|
||||||
bsc.registrable = make(map[string]*Desc)
|
bsc.registerable = make(map[string]*Desc)
|
||||||
}
|
}
|
||||||
|
|
||||||
bsc.registrable[d.fqName] = d
|
bsc.registerable[d.fqName] = d
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bsc *BaseStableCollector) trackHiddenDescriptor(d *Desc) {
|
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
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,7 +173,7 @@ func (bsc *BaseStableCollector) ClearState() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bsc.descriptors = nil
|
bsc.descriptors = nil
|
||||||
bsc.registrable = nil
|
bsc.registerable = nil
|
||||||
bsc.hidden = nil
|
bsc.hidden = nil
|
||||||
bsc.self = nil
|
bsc.self = nil
|
||||||
}
|
}
|
||||||
|
@ -87,10 +87,24 @@ func (r *lazyMetric) lazyInit(self kubeCollector, fqName string) {
|
|||||||
r.self = self
|
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 method takes a Version argument which should be the version of the binary in which
|
||||||
// this code is currently being executed.
|
// this code is currently being executed. A metric can be hidden under two conditions:
|
||||||
func (r *lazyMetric) determineDeprecationStatus(version semver.Version) {
|
// 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()
|
selfVersion := r.self.DeprecatedVersion()
|
||||||
if selfVersion == nil {
|
if selfVersion == nil {
|
||||||
return
|
return
|
||||||
@ -99,6 +113,7 @@ func (r *lazyMetric) determineDeprecationStatus(version semver.Version) {
|
|||||||
if selfVersion.LTE(version) {
|
if selfVersion.LTE(version) {
|
||||||
r.isDeprecated = true
|
r.isDeprecated = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if ShouldShowHidden() {
|
if ShouldShowHidden() {
|
||||||
klog.Warningf("Hidden metrics (%s) have been manually overridden, showing this very deprecated metric.", r.fqName)
|
klog.Warningf("Hidden metrics (%s) have been manually overridden, showing this very deprecated metric.", r.fqName)
|
||||||
return
|
return
|
||||||
@ -126,7 +141,7 @@ func (r *lazyMetric) IsDeprecated() bool {
|
|||||||
// created.
|
// created.
|
||||||
func (r *lazyMetric) Create(version *semver.Version) bool {
|
func (r *lazyMetric) Create(version *semver.Version) bool {
|
||||||
if version != nil {
|
if version != nil {
|
||||||
r.determineDeprecationStatus(*version)
|
r.preprocessMetric(*version)
|
||||||
}
|
}
|
||||||
// let's not create if this metric is slated to be hidden
|
// let's not create if this metric is slated to be hidden
|
||||||
if r.IsHidden() {
|
if r.IsHidden() {
|
||||||
|
@ -28,6 +28,7 @@ import (
|
|||||||
// Options has all parameters needed for exposing metrics from components
|
// Options has all parameters needed for exposing metrics from components
|
||||||
type Options struct {
|
type Options struct {
|
||||||
ShowHiddenMetricsForVersion string
|
ShowHiddenMetricsForVersion string
|
||||||
|
DisabledMetrics []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewOptions returns default metrics options
|
// NewOptions returns default metrics options
|
||||||
@ -56,12 +57,21 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) {
|
|||||||
"The format is <major>.<minor>, e.g.: '1.16'. "+
|
"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, "+
|
"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.")
|
"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.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply applies parameters into global configuration of metrics.
|
// Apply applies parameters into global configuration of metrics.
|
||||||
func (o *Options) Apply() {
|
func (o *Options) Apply() {
|
||||||
if o != nil && len(o.ShowHiddenMetricsForVersion) > 0 {
|
if o != nil && len(o.ShowHiddenMetricsForVersion) > 0 {
|
||||||
SetShowHidden()
|
SetShowHidden()
|
||||||
|
// set disabled metrics
|
||||||
|
for _, metricName := range o.DisabledMetrics {
|
||||||
|
SetDisabledMetric(metricName)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,10 +30,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
showHiddenOnce sync.Once
|
showHiddenOnce sync.Once
|
||||||
showHidden atomic.Value
|
disabledMetricsLock sync.RWMutex
|
||||||
registries []*kubeRegistry // stores all registries created by NewKubeRegistry()
|
showHidden atomic.Value
|
||||||
registriesLock sync.RWMutex
|
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
|
// shouldHide be used to check if a specific metric with deprecated version should be hidden
|
||||||
@ -61,6 +63,12 @@ func ValidateShowHiddenMetricsVersion(v string) []error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetDisabledMetric(name string) {
|
||||||
|
disabledMetricsLock.Lock()
|
||||||
|
defer disabledMetricsLock.Unlock()
|
||||||
|
disabledMetrics[name] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
// SetShowHidden will enable showing hidden metrics. This will no-opt
|
// SetShowHidden will enable showing hidden metrics. This will no-opt
|
||||||
// after the initial call
|
// after the initial call
|
||||||
func SetShowHidden() {
|
func SetShowHidden() {
|
||||||
|
@ -515,3 +515,39 @@ func TestRegistryReset(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDisabledMetrics(t *testing.T) {
|
||||||
|
SetDisabledMetric("should_be_disabled")
|
||||||
|
currentVersion := apimachineryversion.Info{
|
||||||
|
Major: "1",
|
||||||
|
Minor: "17",
|
||||||
|
GitVersion: "v1.17.1-alpha-1.12345",
|
||||||
|
}
|
||||||
|
registry := newKubeRegistry(currentVersion)
|
||||||
|
disabledMetric := NewCounterVec(&CounterOpts{
|
||||||
|
Name: "should_be_disabled",
|
||||||
|
Help: "this metric should be disabled",
|
||||||
|
}, []string{"label"})
|
||||||
|
// gauges cannot be reset
|
||||||
|
enabledMetric := NewGauge(&GaugeOpts{
|
||||||
|
Name: "should_be_enabled",
|
||||||
|
Help: "this metric should not be disabled",
|
||||||
|
})
|
||||||
|
|
||||||
|
registry.MustRegister(disabledMetric)
|
||||||
|
registry.MustRegister(enabledMetric)
|
||||||
|
disabledMetric.WithLabelValues("one").Inc()
|
||||||
|
disabledMetric.WithLabelValues("two").Inc()
|
||||||
|
disabledMetric.WithLabelValues("two").Inc()
|
||||||
|
enabledMetric.Inc()
|
||||||
|
|
||||||
|
enabledMetricOutput := `
|
||||||
|
# HELP should_be_enabled [ALPHA] this metric should not be disabled
|
||||||
|
# TYPE should_be_enabled gauge
|
||||||
|
should_be_enabled 1
|
||||||
|
`
|
||||||
|
|
||||||
|
if err := testutil.GatherAndCompare(registry, strings.NewReader(enabledMetricOutput), "should_be_disabled", "should_be_enabled"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user