mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 04:06:03 +00:00
Merge pull request #85714 from RainbowMango/pr_clear_desc_state
Add API for clear descriptor status
This commit is contained in:
commit
fa246f8188
@ -40,6 +40,7 @@ go_test(
|
|||||||
srcs = [
|
srcs = [
|
||||||
"collector_test.go",
|
"collector_test.go",
|
||||||
"counter_test.go",
|
"counter_test.go",
|
||||||
|
"desc_test.go",
|
||||||
"gauge_test.go",
|
"gauge_test.go",
|
||||||
"histogram_test.go",
|
"histogram_test.go",
|
||||||
"opts_test.go",
|
"opts_test.go",
|
||||||
|
@ -115,26 +115,12 @@ func (bsc *BaseStableCollector) Create(version *semver.Version, self StableColle
|
|||||||
bsc.init(self)
|
bsc.init(self)
|
||||||
|
|
||||||
for _, d := range bsc.descriptors {
|
for _, d := range bsc.descriptors {
|
||||||
if version != nil {
|
d.create(version)
|
||||||
d.determineDeprecationStatus(*version)
|
if d.IsHidden() {
|
||||||
|
// do nothing for hidden metrics
|
||||||
|
} else {
|
||||||
|
bsc.registrable = append(bsc.registrable, d)
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
if len(bsc.registrable) > 0 {
|
||||||
|
@ -18,7 +18,6 @@ package metrics
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/blang/semver"
|
"github.com/blang/semver"
|
||||||
@ -42,7 +41,8 @@ type Desc struct {
|
|||||||
variableLabels []string
|
variableLabels []string
|
||||||
|
|
||||||
// promDesc is the descriptor used by every Prometheus Metric.
|
// promDesc is the descriptor used by every Prometheus Metric.
|
||||||
promDesc *prometheus.Desc
|
promDesc *prometheus.Desc
|
||||||
|
annotatedHelp string
|
||||||
|
|
||||||
// stabilityLevel represents the API guarantees for a given defined metric.
|
// stabilityLevel represents the API guarantees for a given defined metric.
|
||||||
stabilityLevel StabilityLevel
|
stabilityLevel StabilityLevel
|
||||||
@ -73,6 +73,7 @@ func NewDesc(fqName string, help string, variableLabels []string, constLabels La
|
|||||||
d := &Desc{
|
d := &Desc{
|
||||||
fqName: fqName,
|
fqName: fqName,
|
||||||
help: help,
|
help: help,
|
||||||
|
annotatedHelp: help,
|
||||||
variableLabels: variableLabels,
|
variableLabels: variableLabels,
|
||||||
constLabels: constLabels,
|
constLabels: constLabels,
|
||||||
stabilityLevel: stabilityLevel,
|
stabilityLevel: stabilityLevel,
|
||||||
@ -86,6 +87,7 @@ func NewDesc(fqName string, help string, variableLabels []string, constLabels La
|
|||||||
// String formats the Desc as a string.
|
// String formats the Desc as a string.
|
||||||
// The stability metadata maybe annotated in 'HELP' section if called after registry,
|
// The stability metadata maybe annotated in 'HELP' section if called after registry,
|
||||||
// otherwise not.
|
// otherwise not.
|
||||||
|
// e.g. "Desc{fqName: "normal_stable_descriptor", help: "[STABLE] this is a stable descriptor", constLabels: {}, variableLabels: []}"
|
||||||
func (d *Desc) String() string {
|
func (d *Desc) String() string {
|
||||||
if d.isCreated {
|
if d.isCreated {
|
||||||
return d.promDesc.String()
|
return d.promDesc.String()
|
||||||
@ -136,22 +138,76 @@ func (d *Desc) IsDeprecated() bool {
|
|||||||
return d.isDeprecated
|
return d.isDeprecated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsCreated returns if metric has been created.
|
||||||
|
func (d *Desc) IsCreated() bool {
|
||||||
|
d.createLock.RLock()
|
||||||
|
defer d.createLock.RUnlock()
|
||||||
|
|
||||||
|
return d.isCreated
|
||||||
|
}
|
||||||
|
|
||||||
|
// create forces the initialization of Desc which has been deferred until
|
||||||
|
// the point at which this method is invoked. This method will determine whether
|
||||||
|
// the Desc is deprecated or hidden, no-opting if the Desc should be considered
|
||||||
|
// hidden. Furthermore, this function no-opts and returns true if Desc is already
|
||||||
|
// created.
|
||||||
|
func (d *Desc) create(version *semver.Version) bool {
|
||||||
|
if version != nil {
|
||||||
|
d.determineDeprecationStatus(*version)
|
||||||
|
}
|
||||||
|
|
||||||
|
// let's not create if this metric is slated to be hidden
|
||||||
|
if d.IsHidden() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
d.createOnce.Do(func() {
|
||||||
|
d.createLock.Lock()
|
||||||
|
defer d.createLock.Unlock()
|
||||||
|
|
||||||
|
d.isCreated = true
|
||||||
|
if d.IsDeprecated() {
|
||||||
|
d.initializeDeprecatedDesc()
|
||||||
|
} else {
|
||||||
|
d.initialize()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return d.IsCreated()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearState will clear all the states marked by Create.
|
||||||
|
// It intends to be used for re-register a hidden metric.
|
||||||
|
func (d *Desc) ClearState() {
|
||||||
|
d.isDeprecated = false
|
||||||
|
d.isHidden = false
|
||||||
|
d.isCreated = false
|
||||||
|
|
||||||
|
d.markDeprecationOnce = *new(sync.Once)
|
||||||
|
d.createOnce = *new(sync.Once)
|
||||||
|
d.deprecateOnce = *new(sync.Once)
|
||||||
|
d.hideOnce = *new(sync.Once)
|
||||||
|
d.annotateOnce = *new(sync.Once)
|
||||||
|
|
||||||
|
d.annotatedHelp = d.help
|
||||||
|
d.promDesc = nil
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Desc) markDeprecated() {
|
func (d *Desc) markDeprecated() {
|
||||||
d.deprecateOnce.Do(func() {
|
d.deprecateOnce.Do(func() {
|
||||||
d.help = fmt.Sprintf("(Deprecated since %s) %s", d.deprecatedVersion, d.help)
|
d.annotatedHelp = fmt.Sprintf("(Deprecated since %s) %s", d.deprecatedVersion, d.annotatedHelp)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Desc) annotateStabilityLevel() {
|
func (d *Desc) annotateStabilityLevel() {
|
||||||
d.annotateOnce.Do(func() {
|
d.annotateOnce.Do(func() {
|
||||||
d.help = fmt.Sprintf("[%v] %v", d.stabilityLevel, d.help)
|
d.annotatedHelp = fmt.Sprintf("[%v] %v", d.stabilityLevel, d.annotatedHelp)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Desc) initialize() {
|
func (d *Desc) initialize() {
|
||||||
d.annotateStabilityLevel()
|
d.annotateStabilityLevel()
|
||||||
|
|
||||||
// this actually creates the underlying prometheus desc.
|
// this actually creates the underlying prometheus desc.
|
||||||
d.promDesc = prometheus.NewDesc(d.fqName, d.help, d.variableLabels, prometheus.Labels(d.constLabels))
|
d.promDesc = prometheus.NewDesc(d.fqName, d.annotatedHelp, d.variableLabels, prometheus.Labels(d.constLabels))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Desc) initializeDeprecatedDesc() {
|
func (d *Desc) initializeDeprecatedDesc() {
|
||||||
@ -165,9 +221,5 @@ func (d *Desc) initializeDeprecatedDesc() {
|
|||||||
// 1. Desc `D` is registered to registry 'A' in TestA (Note: `D` maybe created)
|
// 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')
|
// 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 {
|
func (d *Desc) GetRawDesc() *Desc {
|
||||||
// remove stability from help if any
|
return NewDesc(d.fqName, d.help, d.variableLabels, d.constLabels, d.stabilityLevel, d.deprecatedVersion)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
164
staging/src/k8s.io/component-base/metrics/desc_test.go
Normal file
164
staging/src/k8s.io/component-base/metrics/desc_test.go
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
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 (
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/version"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDescCreate(t *testing.T) {
|
||||||
|
currentVersion := parseVersion(version.Info{
|
||||||
|
Major: "1",
|
||||||
|
Minor: "17",
|
||||||
|
GitVersion: "v1.17.0-alpha-1.12345",
|
||||||
|
})
|
||||||
|
|
||||||
|
var tests = []struct {
|
||||||
|
name string
|
||||||
|
fqName string
|
||||||
|
help string
|
||||||
|
stabilityLevel StabilityLevel
|
||||||
|
deprecatedVersion string
|
||||||
|
|
||||||
|
shouldCreate bool
|
||||||
|
expectedAnnotatedHelp string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "alpha descriptor should be created",
|
||||||
|
fqName: "normal_alpha_descriptor",
|
||||||
|
help: "this is an alpha descriptor",
|
||||||
|
stabilityLevel: ALPHA,
|
||||||
|
deprecatedVersion: "",
|
||||||
|
shouldCreate: true,
|
||||||
|
expectedAnnotatedHelp: "[ALPHA] this is an alpha descriptor",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "stable descriptor should be created",
|
||||||
|
fqName: "normal_stable_descriptor",
|
||||||
|
help: "this is a stable descriptor",
|
||||||
|
stabilityLevel: STABLE,
|
||||||
|
deprecatedVersion: "",
|
||||||
|
shouldCreate: true,
|
||||||
|
expectedAnnotatedHelp: "[STABLE] this is a stable descriptor",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "deprecated descriptor should be created",
|
||||||
|
fqName: "deprecated_stable_descriptor",
|
||||||
|
help: "this is a deprecated descriptor",
|
||||||
|
stabilityLevel: STABLE,
|
||||||
|
deprecatedVersion: "1.17.0",
|
||||||
|
shouldCreate: true,
|
||||||
|
expectedAnnotatedHelp: "[STABLE] (Deprecated since 1.17.0) this is a deprecated descriptor",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "hidden descriptor should not be created",
|
||||||
|
fqName: "hidden_stable_descriptor",
|
||||||
|
help: "this is a hidden descriptor",
|
||||||
|
stabilityLevel: STABLE,
|
||||||
|
deprecatedVersion: "1.16.0",
|
||||||
|
shouldCreate: false,
|
||||||
|
expectedAnnotatedHelp: "this is a hidden descriptor", // hidden descriptor shall not be annotated.
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
tc := test
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
desc := NewDesc(tc.fqName, tc.help, nil, nil, tc.stabilityLevel, tc.deprecatedVersion)
|
||||||
|
|
||||||
|
if desc.IsCreated() {
|
||||||
|
t.Fatal("Descriptor should not be created by default.")
|
||||||
|
}
|
||||||
|
|
||||||
|
desc.create(¤tVersion)
|
||||||
|
desc.create(¤tVersion) // we can safely create a descriptor over and over again.
|
||||||
|
|
||||||
|
if desc.IsCreated() != tc.shouldCreate {
|
||||||
|
t.Fatalf("expected create state: %v, but got: %v", tc.shouldCreate, desc.IsCreated())
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(desc.String(), tc.expectedAnnotatedHelp) {
|
||||||
|
t.Fatalf("expected annotated help: %s, but not in descriptor: %s", tc.expectedAnnotatedHelp, desc.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDescClearState(t *testing.T) {
|
||||||
|
currentVersion := parseVersion(version.Info{
|
||||||
|
Major: "1",
|
||||||
|
Minor: "17",
|
||||||
|
GitVersion: "v1.17.0-alpha-1.12345",
|
||||||
|
})
|
||||||
|
|
||||||
|
var tests = []struct {
|
||||||
|
name string
|
||||||
|
fqName string
|
||||||
|
help string
|
||||||
|
stabilityLevel StabilityLevel
|
||||||
|
deprecatedVersion string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "alpha descriptor",
|
||||||
|
fqName: "normal_alpha_descriptor",
|
||||||
|
help: "this is an alpha descriptor",
|
||||||
|
stabilityLevel: ALPHA,
|
||||||
|
deprecatedVersion: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "stable descriptor",
|
||||||
|
fqName: "normal_stable_descriptor",
|
||||||
|
help: "this is a stable descriptor",
|
||||||
|
stabilityLevel: STABLE,
|
||||||
|
deprecatedVersion: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "deprecated descriptor",
|
||||||
|
fqName: "deprecated_stable_descriptor",
|
||||||
|
help: "this is a deprecated descriptor",
|
||||||
|
stabilityLevel: STABLE,
|
||||||
|
deprecatedVersion: "1.17.0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "hidden descriptor",
|
||||||
|
fqName: "hidden_stable_descriptor",
|
||||||
|
help: "this is a hidden descriptor",
|
||||||
|
stabilityLevel: STABLE,
|
||||||
|
deprecatedVersion: "1.16.0",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
tc := test
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
descA := NewDesc(tc.fqName, tc.help, nil, nil, tc.stabilityLevel, tc.deprecatedVersion)
|
||||||
|
descB := NewDesc(tc.fqName, tc.help, nil, nil, tc.stabilityLevel, tc.deprecatedVersion)
|
||||||
|
|
||||||
|
descA.create(¤tVersion)
|
||||||
|
descA.ClearState()
|
||||||
|
|
||||||
|
// create
|
||||||
|
if !reflect.DeepEqual(*descA, *descB) {
|
||||||
|
t.Fatal("descriptor state hasn't be cleaned up")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user