Skip to content

Commit 19431e0

Browse files
authored
Merge pull request kubernetes#77037 from logicalhan/counter-wrapper
Add wrappers for prometheus.Counter/CounterVec and prometheus.Registry
2 parents 805b6cb + 6d83923 commit 19431e0

File tree

26 files changed

+1540
-0
lines changed

26 files changed

+1540
-0
lines changed

staging/src/k8s.io/apiextensions-apiserver/go.sum

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

staging/src/k8s.io/apiserver/go.sum

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ filegroup(
1414
"//staging/src/k8s.io/component-base/config:all-srcs",
1515
"//staging/src/k8s.io/component-base/featuregate:all-srcs",
1616
"//staging/src/k8s.io/component-base/logs:all-srcs",
17+
"//staging/src/k8s.io/component-base/metrics:all-srcs",
1718
],
1819
tags = ["automanaged"],
1920
visibility = ["//visibility:public"],

staging/src/k8s.io/component-base/go.mod

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

staging/src/k8s.io/component-base/go.sum

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package(default_visibility = ["//visibility:public"])
2+
3+
load(
4+
"@io_bazel_rules_go//go:def.bzl",
5+
"go_library",
6+
"go_test",
7+
)
8+
9+
go_library(
10+
name = "go_default_library",
11+
srcs = [
12+
"counter.go",
13+
"metric.go",
14+
"opts.go",
15+
"registry.go",
16+
"version_parser.go",
17+
"wrappers.go",
18+
],
19+
importmap = "k8s.io/kubernetes/vendor/k8s.io/component-base/metrics",
20+
importpath = "k8s.io/component-base/metrics",
21+
deps = [
22+
"//staging/src/k8s.io/apimachinery/pkg/version:go_default_library",
23+
"//vendor/github.com/blang/semver:go_default_library",
24+
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
25+
"//vendor/github.com/prometheus/client_model/go:go_default_library",
26+
"//vendor/k8s.io/klog:go_default_library",
27+
],
28+
)
29+
30+
go_test(
31+
name = "go_default_test",
32+
srcs = [
33+
"counter_test.go",
34+
"registry_test.go",
35+
"version_parser_test.go",
36+
],
37+
embed = [":go_default_library"],
38+
deps = [
39+
"//staging/src/k8s.io/apimachinery/pkg/version:go_default_library",
40+
"//vendor/github.com/blang/semver:go_default_library",
41+
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
42+
"//vendor/github.com/prometheus/common/expfmt:go_default_library",
43+
"//vendor/github.com/stretchr/testify/assert:go_default_library",
44+
],
45+
)
46+
47+
filegroup(
48+
name = "package-srcs",
49+
srcs = glob(["**"]),
50+
tags = ["automanaged"],
51+
visibility = ["//visibility:private"],
52+
)
53+
54+
filegroup(
55+
name = "all-srcs",
56+
srcs = [
57+
":package-srcs",
58+
"//staging/src/k8s.io/component-base/metrics/legacyregistry:all-srcs",
59+
],
60+
tags = ["automanaged"],
61+
)
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
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 metrics
18+
19+
import (
20+
"github.com/blang/semver"
21+
"github.com/prometheus/client_golang/prometheus"
22+
)
23+
24+
// Counter is our internal representation for our wrapping struct around prometheus
25+
// counters. Counter implements both KubeCollector and CounterMetric.
26+
type Counter struct {
27+
CounterMetric
28+
*CounterOpts
29+
lazyMetric
30+
selfCollector
31+
}
32+
33+
// NewCounter returns an object which satisfies the KubeCollector and CounterMetric interfaces.
34+
// However, the object returned will not measure anything unless the collector is first
35+
// registered, since the metric is lazily instantiated.
36+
func NewCounter(opts *CounterOpts) *Counter {
37+
// todo: handle defaulting better
38+
if opts.StabilityLevel == "" {
39+
opts.StabilityLevel = ALPHA
40+
}
41+
kc := &Counter{
42+
CounterOpts: opts,
43+
lazyMetric: lazyMetric{},
44+
}
45+
kc.setPrometheusCounter(noop)
46+
kc.lazyInit(kc)
47+
return kc
48+
}
49+
50+
// setPrometheusCounter sets the underlying CounterMetric object, i.e. the thing that does the measurement.
51+
func (c *Counter) setPrometheusCounter(counter prometheus.Counter) {
52+
c.CounterMetric = counter
53+
c.initSelfCollection(counter)
54+
}
55+
56+
// DeprecatedVersion returns a pointer to the Version or nil
57+
func (c *Counter) DeprecatedVersion() *semver.Version {
58+
return c.CounterOpts.DeprecatedVersion
59+
}
60+
61+
// initializeMetric invocation creates the actual underlying Counter. Until this method is called
62+
// the underlying counter is a no-op.
63+
func (c *Counter) initializeMetric() {
64+
c.CounterOpts.annotateStabilityLevel()
65+
// this actually creates the underlying prometheus counter.
66+
c.setPrometheusCounter(prometheus.NewCounter(c.CounterOpts.toPromCounterOpts()))
67+
}
68+
69+
// initializeDeprecatedMetric invocation creates the actual (but deprecated) Counter. Until this method
70+
// is called the underlying counter is a no-op.
71+
func (c *Counter) initializeDeprecatedMetric() {
72+
c.CounterOpts.markDeprecated()
73+
c.initializeMetric()
74+
}
75+
76+
// CounterVec is the internal representation of our wrapping struct around prometheus
77+
// counterVecs. CounterVec implements both KubeCollector and CounterVecMetric.
78+
type CounterVec struct {
79+
*prometheus.CounterVec
80+
*CounterOpts
81+
lazyMetric
82+
originalLabels []string
83+
}
84+
85+
// NewCounterVec returns an object which satisfies the KubeCollector and CounterVecMetric interfaces.
86+
// However, the object returned will not measure anything unless the collector is first
87+
// registered, since the metric is lazily instantiated.
88+
func NewCounterVec(opts *CounterOpts, labels []string) *CounterVec {
89+
cv := &CounterVec{
90+
CounterVec: noopCounterVec,
91+
CounterOpts: opts,
92+
originalLabels: labels,
93+
lazyMetric: lazyMetric{},
94+
}
95+
cv.lazyInit(cv)
96+
return cv
97+
}
98+
99+
// DeprecatedVersion returns a pointer to the Version or nil
100+
func (v *CounterVec) DeprecatedVersion() *semver.Version {
101+
return v.CounterOpts.DeprecatedVersion
102+
}
103+
104+
// initializeMetric invocation creates the actual underlying CounterVec. Until this method is called
105+
// the underlying counterVec is a no-op.
106+
func (v *CounterVec) initializeMetric() {
107+
v.CounterVec = prometheus.NewCounterVec(v.CounterOpts.toPromCounterOpts(), v.originalLabels)
108+
}
109+
110+
// initializeDeprecatedMetric invocation creates the actual (but deprecated) CounterVec. Until this method is called
111+
// the underlying counterVec is a no-op.
112+
func (v *CounterVec) initializeDeprecatedMetric() {
113+
v.CounterOpts.markDeprecated()
114+
v.initializeMetric()
115+
}
116+
117+
// Default Prometheus behavior actually results in the creation of a new metric
118+
// if a metric with the unique label values is not found in the underlying stored metricMap.
119+
// This means that if this function is called but the underlying metric is not registered
120+
// (which means it will never be exposed externally nor consumed), the metric will exist in memory
121+
// for perpetuity (i.e. throughout application lifecycle).
122+
//
123+
// For reference: https://github.com/prometheus/client_golang/blob/v0.9.2/prometheus/counter.go#L179-L197
124+
125+
// WithLabelValues returns the Counter for the given slice of label
126+
// values (same order as the VariableLabels in Desc). If that combination of
127+
// label values is accessed for the first time, a new Counter is created IFF the counterVec
128+
// has been registered to a metrics registry.
129+
func (v *CounterVec) WithLabelValues(lvs ...string) CounterMetric {
130+
if !v.IsCreated() {
131+
return noop // return no-op counter
132+
}
133+
return v.CounterVec.WithLabelValues(lvs...)
134+
}
135+
136+
// With returns the Counter for the given Labels map (the label names
137+
// must match those of the VariableLabels in Desc). If that label map is
138+
// accessed for the first time, a new Counter is created IFF the counterVec has
139+
// been registered to a metrics registry.
140+
func (v *CounterVec) With(labels prometheus.Labels) CounterMetric {
141+
if !v.IsCreated() {
142+
return noop // return no-op counter
143+
}
144+
return v.CounterVec.With(labels)
145+
}

0 commit comments

Comments
 (0)