Skip to content

Commit 7b619f5

Browse files
author
Han Kang
committed
move global registry code into subdirectory 'legacyregistry'
1 parent 04db3dc commit 7b619f5

File tree

8 files changed

+341
-80
lines changed

8 files changed

+341
-80
lines changed

staging/src/k8s.io/component-base/metrics/BUILD

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ filegroup(
5353

5454
filegroup(
5555
name = "all-srcs",
56-
srcs = [":package-srcs"],
56+
srcs = [
57+
":package-srcs",
58+
"//staging/src/k8s.io/component-base/metrics/legacyregistry:all-srcs",
59+
],
5760
tags = ["automanaged"],
5861
)

staging/src/k8s.io/component-base/metrics/counter_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ func TestCounter(t *testing.T) {
7474

7575
for _, test := range tests {
7676
t.Run(test.desc, func(t *testing.T) {
77-
registry := newKubeRegistry(&apimachineryversion.Info{
77+
registry := NewKubeRegistry(&apimachineryversion.Info{
7878
Major: "1",
7979
Minor: "15",
8080
GitVersion: "v1.15.0-alpha-1.12345",
@@ -175,7 +175,7 @@ func TestCounterVec(t *testing.T) {
175175

176176
for _, test := range tests {
177177
t.Run(test.desc, func(t *testing.T) {
178-
registry := newKubeRegistry(&apimachineryversion.Info{
178+
registry := NewKubeRegistry(&apimachineryversion.Info{
179179
Major: "1",
180180
Minor: "15",
181181
GitVersion: "v1.15.0-alpha-1.12345",
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package(default_visibility = ["//visibility:public"])
2+
3+
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
4+
5+
go_library(
6+
name = "go_default_library",
7+
srcs = ["registry.go"],
8+
importmap = "k8s.io/kubernetes/vendor/k8s.io/component-base/metrics/legacyregistry",
9+
importpath = "k8s.io/component-base/metrics/legacyregistry",
10+
deps = [
11+
"//staging/src/k8s.io/apimachinery/pkg/version:go_default_library",
12+
"//staging/src/k8s.io/component-base/metrics:go_default_library",
13+
"//vendor/github.com/prometheus/client_model/go:go_default_library",
14+
],
15+
)
16+
17+
filegroup(
18+
name = "package-srcs",
19+
srcs = glob(["**"]),
20+
tags = ["automanaged"],
21+
visibility = ["//visibility:private"],
22+
)
23+
24+
filegroup(
25+
name = "all-srcs",
26+
srcs = [":package-srcs"],
27+
tags = ["automanaged"],
28+
)
29+
30+
go_test(
31+
name = "go_default_test",
32+
srcs = ["registry_test.go"],
33+
embed = [":go_default_library"],
34+
deps = [
35+
"//staging/src/k8s.io/apimachinery/pkg/version:go_default_library",
36+
"//staging/src/k8s.io/component-base/metrics:go_default_library",
37+
"//vendor/github.com/blang/semver:go_default_library",
38+
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
39+
"//vendor/github.com/stretchr/testify/assert:go_default_library",
40+
],
41+
)
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package legacyregistry
18+
19+
import (
20+
apimachineryversion "k8s.io/apimachinery/pkg/version"
21+
"k8s.io/component-base/metrics"
22+
"sync"
23+
)
24+
25+
var globalRegistryFactory = metricsRegistryFactory{
26+
registerQueue: make([]metrics.KubeCollector, 0),
27+
mustRegisterQueue: make([]metrics.KubeCollector, 0),
28+
}
29+
30+
type metricsRegistryFactory struct {
31+
globalRegistry metrics.KubeRegistry
32+
kubeVersion *apimachineryversion.Info
33+
registrationLock sync.Mutex
34+
registerQueue []metrics.KubeCollector
35+
mustRegisterQueue []metrics.KubeCollector
36+
}
37+
38+
// SetRegistryFactoryVersion sets the kubernetes version information for all
39+
// subsequent metrics registry initializations. Only the first call has an effect.
40+
// If a version is not set, then metrics registry creation will no-opt
41+
func SetRegistryFactoryVersion(ver *apimachineryversion.Info) []error {
42+
globalRegistryFactory.registrationLock.Lock()
43+
defer globalRegistryFactory.registrationLock.Unlock()
44+
if globalRegistryFactory.kubeVersion != nil {
45+
return nil
46+
}
47+
registrationErrs := make([]error, 0)
48+
globalRegistryFactory.globalRegistry = metrics.NewKubeRegistry(ver)
49+
globalRegistryFactory.kubeVersion = ver
50+
for _, c := range globalRegistryFactory.registerQueue {
51+
err := globalRegistryFactory.globalRegistry.Register(c)
52+
if err != nil {
53+
registrationErrs = append(registrationErrs, err)
54+
}
55+
}
56+
for _, c := range globalRegistryFactory.mustRegisterQueue {
57+
globalRegistryFactory.globalRegistry.MustRegister(c)
58+
}
59+
return registrationErrs
60+
}
61+
62+
// Register registers a collectable metric, but it uses a global registry. Registration is deferred
63+
// until the global registry has a version to use.
64+
func Register(c metrics.KubeCollector) error {
65+
globalRegistryFactory.registrationLock.Lock()
66+
defer globalRegistryFactory.registrationLock.Unlock()
67+
68+
if globalRegistryFactory.kubeVersion != nil {
69+
return globalRegistryFactory.globalRegistry.Register(c)
70+
}
71+
globalRegistryFactory.registerQueue = append(globalRegistryFactory.registerQueue, c)
72+
return nil
73+
}
74+
75+
// MustRegister works like Register but registers any number of
76+
// Collectors and panics upon the first registration that causes an
77+
// error. Registration is deferred until the global registry has a version to use.
78+
func MustRegister(cs ...metrics.KubeCollector) {
79+
globalRegistryFactory.registrationLock.Lock()
80+
defer globalRegistryFactory.registrationLock.Unlock()
81+
82+
if globalRegistryFactory.kubeVersion != nil {
83+
globalRegistryFactory.globalRegistry.MustRegister(cs...)
84+
return
85+
}
86+
for _, c := range cs {
87+
globalRegistryFactory.mustRegisterQueue = append(globalRegistryFactory.mustRegisterQueue, c)
88+
}
89+
}
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package legacyregistry
18+
19+
import (
20+
"github.com/blang/semver"
21+
"github.com/prometheus/client_golang/prometheus"
22+
"github.com/stretchr/testify/assert"
23+
"k8s.io/component-base/metrics"
24+
"testing"
25+
26+
apimachineryversion "k8s.io/apimachinery/pkg/version"
27+
)
28+
29+
func init() {
30+
SetRegistryFactoryVersion(&apimachineryversion.Info{
31+
Major: "1",
32+
Minor: "15",
33+
GitVersion: "v1.15.0-alpha-1.12345",
34+
})
35+
}
36+
37+
var (
38+
v115 = semver.MustParse("1.15.0")
39+
v114 = semver.MustParse("1.14.0")
40+
alphaCounter = metrics.NewCounter(
41+
&metrics.CounterOpts{
42+
Namespace: "some_namespace",
43+
Name: "test_counter_name",
44+
Subsystem: "subsystem",
45+
StabilityLevel: metrics.ALPHA,
46+
Help: "counter help",
47+
},
48+
)
49+
alphaDeprecatedCounter = metrics.NewCounter(
50+
&metrics.CounterOpts{
51+
Namespace: "some_namespace",
52+
Name: "test_alpha_dep_counter",
53+
Subsystem: "subsystem",
54+
StabilityLevel: metrics.ALPHA,
55+
Help: "counter help",
56+
DeprecatedVersion: &v115,
57+
},
58+
)
59+
alphaHiddenCounter = metrics.NewCounter(
60+
&metrics.CounterOpts{
61+
Namespace: "some_namespace",
62+
Name: "test_alpha_hidden_counter",
63+
Subsystem: "subsystem",
64+
StabilityLevel: metrics.ALPHA,
65+
Help: "counter help",
66+
DeprecatedVersion: &v114,
67+
},
68+
)
69+
)
70+
71+
func TestRegister(t *testing.T) {
72+
var tests = []struct {
73+
desc string
74+
metrics []*metrics.Counter
75+
registryVersion *semver.Version
76+
expectedErrors []error
77+
expectedIsCreatedValues []bool
78+
expectedIsDeprecated []bool
79+
expectedIsHidden []bool
80+
}{
81+
{
82+
desc: "test registering same metric multiple times",
83+
metrics: []*metrics.Counter{alphaCounter, alphaCounter},
84+
expectedErrors: []error{nil, prometheus.AlreadyRegisteredError{}},
85+
expectedIsCreatedValues: []bool{true, true},
86+
expectedIsDeprecated: []bool{false, false},
87+
expectedIsHidden: []bool{false, false},
88+
},
89+
}
90+
91+
for _, test := range tests {
92+
t.Run(test.desc, func(t *testing.T) {
93+
//t.Errorf("len %v - %v\n", len(test.metrics), len(test.expectedErrors))
94+
for i, m := range test.metrics {
95+
//t.Errorf("m %v\n", m)
96+
err := Register(m)
97+
if err != test.expectedErrors[i] && err.Error() != test.expectedErrors[i].Error() {
98+
t.Errorf("Got unexpected error %v, wanted %v", err, test.expectedErrors[i])
99+
}
100+
if m.IsCreated() != test.expectedIsCreatedValues[i] {
101+
t.Errorf("Got isCreated == %v, wanted isCreated to be %v", m.IsCreated(), test.expectedIsCreatedValues[i])
102+
}
103+
if m.IsDeprecated() != test.expectedIsDeprecated[i] {
104+
t.Errorf("Got IsDeprecated == %v, wanted IsDeprecated to be %v", m.IsDeprecated(), test.expectedIsDeprecated[i])
105+
}
106+
if m.IsHidden() != test.expectedIsHidden[i] {
107+
t.Errorf("Got IsHidden == %v, wanted IsHidden to be %v", m.IsHidden(), test.expectedIsDeprecated[i])
108+
}
109+
}
110+
})
111+
}
112+
}
113+
114+
func TestMustRegister(t *testing.T) {
115+
var tests = []struct {
116+
desc string
117+
metrics []*metrics.Counter
118+
registryVersion *semver.Version
119+
expectedPanics []bool
120+
}{
121+
{
122+
desc: "test must registering same deprecated metric",
123+
metrics: []*metrics.Counter{alphaDeprecatedCounter, alphaDeprecatedCounter},
124+
expectedPanics: []bool{false, true},
125+
},
126+
{
127+
desc: "test alpha hidden metric",
128+
metrics: []*metrics.Counter{alphaHiddenCounter},
129+
expectedPanics: []bool{false},
130+
},
131+
}
132+
133+
for _, test := range tests {
134+
t.Run(test.desc, func(t *testing.T) {
135+
for i, m := range test.metrics {
136+
if test.expectedPanics[i] {
137+
assert.Panics(t,
138+
func() { MustRegister(m) },
139+
"Did not panic even though we expected it.")
140+
} else {
141+
MustRegister(m)
142+
}
143+
}
144+
})
145+
}
146+
}
147+
148+
func TestDeferredRegister(t *testing.T) {
149+
// reset the global registry for this test.
150+
globalRegistryFactory = metricsRegistryFactory{
151+
registerQueue: make([]metrics.KubeCollector, 0),
152+
mustRegisterQueue: make([]metrics.KubeCollector, 0),
153+
}
154+
var err error
155+
err = Register(alphaDeprecatedCounter)
156+
if err != nil {
157+
t.Errorf("Got err == %v, expected no error", err)
158+
}
159+
err = Register(alphaDeprecatedCounter)
160+
if err != nil {
161+
t.Errorf("Got err == %v, expected no error", err)
162+
}
163+
// set the global registry version
164+
errs := SetRegistryFactoryVersion(&apimachineryversion.Info{
165+
Major: "1",
166+
Minor: "15",
167+
GitVersion: "v1.15.0-alpha-1.12345",
168+
})
169+
if len(errs) != 1 {
170+
t.Errorf("Got %d errs, expected 1", len(errs))
171+
for _, err := range errs {
172+
t.Logf("\t Got %v", err)
173+
}
174+
}
175+
}
176+
177+
func TestDeferredMustRegister(t *testing.T) {
178+
// reset the global registry for this test.
179+
globalRegistryFactory = metricsRegistryFactory{
180+
registerQueue: make([]metrics.KubeCollector, 0),
181+
mustRegisterQueue: make([]metrics.KubeCollector, 0),
182+
}
183+
MustRegister(alphaDeprecatedCounter)
184+
185+
MustRegister(alphaDeprecatedCounter)
186+
assert.Panics(t,
187+
func() {
188+
SetRegistryFactoryVersion(&apimachineryversion.Info{
189+
Major: "1",
190+
Minor: "15",
191+
GitVersion: "v1.15.0-alpha-1.12345",
192+
})
193+
},
194+
"Did not panic even though we expected it.")
195+
}

staging/src/k8s.io/component-base/metrics/metric.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ method call depending on whether the metric is deprecated or not.
3232
*/
3333
type KubeCollector interface {
3434
Collector
35-
LazyMetric
35+
lazyKubeMetric
3636
DeprecatedVersion() *semver.Version
3737
// Each collector metric should provide an initialization function
3838
// for both deprecated and non-deprecated variants of a metric. This
@@ -43,19 +43,19 @@ type KubeCollector interface {
4343
}
4444

4545
/*
46-
LazyMetric defines our registration functionality. LazyMetric objects are expected
46+
lazyKubeMetric defines our metric registration interface. lazyKubeMetric objects are expected
4747
to lazily instantiate metrics (i.e defer metric instantiation until when
4848
the Create() function is explicitly called).
4949
*/
50-
type LazyMetric interface {
50+
type lazyKubeMetric interface {
5151
Create(*semver.Version) bool
5252
IsCreated() bool
5353
IsHidden() bool
5454
IsDeprecated() bool
5555
}
5656

5757
/*
58-
lazyMetric implements LazyMetric. A lazy metric is lazy because it waits until metric
58+
lazyMetric implements lazyKubeMetric. A lazy metric is lazy because it waits until metric
5959
registration time before instantiation. Add it as an anonymous field to a struct that
6060
implements KubeCollector to get deferred registration behavior. You must call lazyInit
6161
with the KubeCollector itself as an argument.

0 commit comments

Comments
 (0)