From 80024aefcb0d92db7bbb620e71d45b3bae6a3685 Mon Sep 17 00:00:00 2001 From: Han Kang Date: Wed, 21 Sep 2022 13:07:18 -0700 Subject: [PATCH 1/3] add a feature enabled metric Change-Id: Id872651c4219d4749fc4227da7d944e883e4e355 --- .../metrics/prometheus/feature/metrics.go | 51 ++++++++++++ .../prometheus/feature/metrics_test.go | 77 +++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics.go create mode 100644 staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics_test.go diff --git a/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics.go b/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics.go new file mode 100644 index 00000000000..ab3014cf138 --- /dev/null +++ b/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics.go @@ -0,0 +1,51 @@ +/* +Copyright 2022 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 feature + +import ( + "context" + "fmt" + + k8smetrics "k8s.io/component-base/metrics" + "k8s.io/component-base/metrics/legacyregistry" +) + +var ( + // featureEnabled is a Prometheus Gauge metrics used for recording the enablement of a k8s feature. + featureEnabled = k8smetrics.NewGaugeVec( + &k8smetrics.GaugeOpts{ + Namespace: "k8s", + Name: "feature_enabled", + Help: "This metric records the result of whether a feature is enabled.", + StabilityLevel: k8smetrics.ALPHA, + }, + []string{"name", "enabled"}, + ) +) + +func init() { + legacyregistry.MustRegister(featureEnabled) +} + +func ResetFeatureEnabledMetric() { + featureEnabled.Reset() +} + +func RecordFeatureEnabled(ctx context.Context, name string, enabled bool) error { + featureEnabled.WithContext(ctx).WithLabelValues(name, fmt.Sprintf("%v", enabled)).Set(1) + return nil +} diff --git a/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics_test.go b/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics_test.go new file mode 100644 index 00000000000..b32a53460c5 --- /dev/null +++ b/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics_test.go @@ -0,0 +1,77 @@ +/* +Copyright 2022 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 feature + +import ( + "context" + "strings" + "testing" + + "k8s.io/component-base/metrics/legacyregistry" + "k8s.io/component-base/metrics/testutil" +) + +var ( + testedMetrics = []string{"k8s_feature_enabled"} +) + +func TestObserveHealthcheck(t *testing.T) { + defer legacyregistry.Reset() + defer ResetFeatureEnabledMetric() + + testCases := []struct { + desc string + name string + enabled bool + want string + }{ + { + desc: "test enabled", + name: "feature-a", + enabled: true, + want: ` + # HELP k8s_feature_enabled [ALPHA] This metric records the result of whether a feature is enabled. + # TYPE k8s_feature_enabled gauge + k8s_feature_enabled{enabled="true",name="feature-a"} 1 +`, + }, + { + desc: "test disabled", + name: "feature-b", + enabled: false, + want: ` + # HELP k8s_feature_enabled [ALPHA] This metric records the result of whether a feature is enabled. + # TYPE k8s_feature_enabled gauge + k8s_feature_enabled{enabled="false",name="feature-b"} 1 +`, + }, + } + + for _, test := range testCases { + t.Run(test.desc, func(t *testing.T) { + defer ResetFeatureEnabledMetric() + err := RecordFeatureEnabled(context.Background(), test.name, test.enabled) + if err != nil { + t.Errorf("unexpected err: %v", err) + } + + if err := testutil.GatherAndCompare(legacyregistry.DefaultGatherer, strings.NewReader(test.want), testedMetrics...); err != nil { + t.Fatal(err) + } + }) + } +} From dc2c486059974341b1be4d4874978cb335c29606 Mon Sep 17 00:00:00 2001 From: Han Kang Date: Thu, 22 Sep 2022 08:56:36 -0700 Subject: [PATCH 2/3] rename metric and add feature stage to metrics Change-Id: Iccab766ba2ee16ef54abb79e41ee61a6117fa7dd --- .../metrics/prometheus/feature/metrics.go | 21 +++++++-------- .../prometheus/feature/metrics_test.go | 26 +++++++++---------- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics.go b/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics.go index ab3014cf138..5aecdc50db1 100644 --- a/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics.go +++ b/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics.go @@ -25,27 +25,26 @@ import ( ) var ( - // featureEnabled is a Prometheus Gauge metrics used for recording the enablement of a k8s feature. - featureEnabled = k8smetrics.NewGaugeVec( + // featureInfo is a Prometheus Gauge metrics used for recording the enablement of a k8s feature. + featureInfo = k8smetrics.NewGaugeVec( &k8smetrics.GaugeOpts{ Namespace: "k8s", - Name: "feature_enabled", - Help: "This metric records the result of whether a feature is enabled.", + Name: "feature_info", + Help: "This metric records the data about the stage and enablement of a k8s feature.", StabilityLevel: k8smetrics.ALPHA, }, - []string{"name", "enabled"}, + []string{"name", "stage", "enabled"}, ) ) func init() { - legacyregistry.MustRegister(featureEnabled) + legacyregistry.MustRegister(featureInfo) } -func ResetFeatureEnabledMetric() { - featureEnabled.Reset() +func ResetFeatureInfoMetric() { + featureInfo.Reset() } -func RecordFeatureEnabled(ctx context.Context, name string, enabled bool) error { - featureEnabled.WithContext(ctx).WithLabelValues(name, fmt.Sprintf("%v", enabled)).Set(1) - return nil +func RecordFeatureInfo(ctx context.Context, name string, stage string, enabled bool) { + featureInfo.WithContext(ctx).WithLabelValues(name, stage, fmt.Sprintf("%v", enabled)).Set(1) } diff --git a/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics_test.go b/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics_test.go index b32a53460c5..49f4b1274b4 100644 --- a/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics_test.go +++ b/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics_test.go @@ -26,48 +26,48 @@ import ( ) var ( - testedMetrics = []string{"k8s_feature_enabled"} + testedMetrics = []string{"k8s_feature_info"} ) func TestObserveHealthcheck(t *testing.T) { defer legacyregistry.Reset() - defer ResetFeatureEnabledMetric() + defer ResetFeatureInfoMetric() testCases := []struct { desc string name string + stage string enabled bool want string }{ { desc: "test enabled", name: "feature-a", + stage: "ALPHA", enabled: true, want: ` - # HELP k8s_feature_enabled [ALPHA] This metric records the result of whether a feature is enabled. - # TYPE k8s_feature_enabled gauge - k8s_feature_enabled{enabled="true",name="feature-a"} 1 + # HELP k8s_feature_info [ALPHA] This metric records the data about the stage and enablement of a k8s feature. + # TYPE k8s_feature_info gauge + k8s_feature_info{enabled="true",name="feature-a",stage="ALPHA"} 1 `, }, { desc: "test disabled", name: "feature-b", + stage: "BETA", enabled: false, want: ` - # HELP k8s_feature_enabled [ALPHA] This metric records the result of whether a feature is enabled. - # TYPE k8s_feature_enabled gauge - k8s_feature_enabled{enabled="false",name="feature-b"} 1 + # HELP k8s_feature_info [ALPHA] This metric records the data about the stage and enablement of a k8s feature. + # TYPE k8s_feature_info gauge + k8s_feature_info{enabled="false",name="feature-b",stage="BETA"} 1 `, }, } for _, test := range testCases { t.Run(test.desc, func(t *testing.T) { - defer ResetFeatureEnabledMetric() - err := RecordFeatureEnabled(context.Background(), test.name, test.enabled) - if err != nil { - t.Errorf("unexpected err: %v", err) - } + defer ResetFeatureInfoMetric() + RecordFeatureInfo(context.Background(), test.name, test.stage, test.enabled) if err := testutil.GatherAndCompare(legacyregistry.DefaultGatherer, strings.NewReader(test.want), testedMetrics...); err != nil { t.Fatal(err) From 2f2b018a3e33aa28d8fd56e37a0e09a7e3dccb8c Mon Sep 17 00:00:00 2001 From: Han Kang Date: Thu, 22 Sep 2022 11:09:19 -0700 Subject: [PATCH 3/3] change prefix to make it consistent with kubernetes_build_info Change-Id: Ia0f65bec6c0dc092c3db9b5b1c22059a0c8c9776 --- .../metrics/prometheus/feature/metrics.go | 2 +- .../prometheus/feature/metrics_test.go | 14 ++--- .../metrics/prometheus/health/metrics.go | 4 +- .../metrics/prometheus/health/metrics_test.go | 54 +++++++++---------- 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics.go b/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics.go index 5aecdc50db1..c1bee3c04c7 100644 --- a/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics.go +++ b/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics.go @@ -28,7 +28,7 @@ var ( // featureInfo is a Prometheus Gauge metrics used for recording the enablement of a k8s feature. featureInfo = k8smetrics.NewGaugeVec( &k8smetrics.GaugeOpts{ - Namespace: "k8s", + Namespace: "kubernetes", Name: "feature_info", Help: "This metric records the data about the stage and enablement of a k8s feature.", StabilityLevel: k8smetrics.ALPHA, diff --git a/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics_test.go b/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics_test.go index 49f4b1274b4..0489fed8358 100644 --- a/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics_test.go +++ b/staging/src/k8s.io/component-base/metrics/prometheus/feature/metrics_test.go @@ -26,7 +26,7 @@ import ( ) var ( - testedMetrics = []string{"k8s_feature_info"} + testedMetrics = []string{"kubernetes_feature_info"} ) func TestObserveHealthcheck(t *testing.T) { @@ -46,9 +46,9 @@ func TestObserveHealthcheck(t *testing.T) { stage: "ALPHA", enabled: true, want: ` - # HELP k8s_feature_info [ALPHA] This metric records the data about the stage and enablement of a k8s feature. - # TYPE k8s_feature_info gauge - k8s_feature_info{enabled="true",name="feature-a",stage="ALPHA"} 1 + # HELP kubernetes_feature_info [ALPHA] This metric records the data about the stage and enablement of a k8s feature. + # TYPE kubernetes_feature_info gauge + kubernetes_feature_info{enabled="true",name="feature-a",stage="ALPHA"} 1 `, }, { @@ -57,9 +57,9 @@ func TestObserveHealthcheck(t *testing.T) { stage: "BETA", enabled: false, want: ` - # HELP k8s_feature_info [ALPHA] This metric records the data about the stage and enablement of a k8s feature. - # TYPE k8s_feature_info gauge - k8s_feature_info{enabled="false",name="feature-b",stage="BETA"} 1 + # HELP kubernetes_feature_info [ALPHA] This metric records the data about the stage and enablement of a k8s feature. + # TYPE kubernetes_feature_info gauge + kubernetes_feature_info{enabled="false",name="feature-b",stage="BETA"} 1 `, }, } diff --git a/staging/src/k8s.io/component-base/metrics/prometheus/health/metrics.go b/staging/src/k8s.io/component-base/metrics/prometheus/health/metrics.go index 4be16d7cb0b..7e429528b75 100644 --- a/staging/src/k8s.io/component-base/metrics/prometheus/health/metrics.go +++ b/staging/src/k8s.io/component-base/metrics/prometheus/health/metrics.go @@ -44,7 +44,7 @@ var ( // healthcheck is a Prometheus Gauge metrics used for recording the results of a k8s healthcheck. healthcheck = k8smetrics.NewGaugeVec( &k8smetrics.GaugeOpts{ - Namespace: "k8s", + Namespace: "kubernetes", Name: "healthcheck", Help: "This metric records the result of a single healthcheck.", StabilityLevel: k8smetrics.ALPHA, @@ -55,7 +55,7 @@ var ( // healthchecksTotal is a Prometheus Counter metrics used for counting the results of a k8s healthcheck. healthchecksTotal = k8smetrics.NewCounterVec( &k8smetrics.CounterOpts{ - Namespace: "k8s", + Namespace: "kubernetes", Name: "healthchecks_total", Help: "This metric records the results of all healthcheck.", StabilityLevel: k8smetrics.ALPHA, diff --git a/staging/src/k8s.io/component-base/metrics/prometheus/health/metrics_test.go b/staging/src/k8s.io/component-base/metrics/prometheus/health/metrics_test.go index 9ba52a3099a..1910d4ec291 100644 --- a/staging/src/k8s.io/component-base/metrics/prometheus/health/metrics_test.go +++ b/staging/src/k8s.io/component-base/metrics/prometheus/health/metrics_test.go @@ -26,7 +26,7 @@ import ( ) var ( - testedMetrics = []string{"k8s_healthcheck", "k8s_healthchecks_total"} + testedMetrics = []string{"kubernetes_healthcheck", "kubernetes_healthchecks_total"} ) func TestObserveHealthcheck(t *testing.T) { @@ -35,14 +35,14 @@ func TestObserveHealthcheck(t *testing.T) { initialState := Error healthcheckName := "healthcheck-a" initialOutput := ` - # HELP k8s_healthcheck [ALPHA] This metric records the result of a single healthcheck. - # TYPE k8s_healthcheck gauge - k8s_healthcheck{name="healthcheck-a",status="error",type="healthz"} 1 - k8s_healthcheck{name="healthcheck-a",status="pending",type="healthz"} 0 - k8s_healthcheck{name="healthcheck-a",status="success",type="healthz"} 0 - # HELP k8s_healthchecks_total [ALPHA] This metric records the results of all healthcheck. - # TYPE k8s_healthchecks_total counter - k8s_healthchecks_total{name="healthcheck-a",status="error",type="healthz"} 1 + # HELP kubernetes_healthcheck [ALPHA] This metric records the result of a single healthcheck. + # TYPE kubernetes_healthcheck gauge + kubernetes_healthcheck{name="healthcheck-a",status="error",type="healthz"} 1 + kubernetes_healthcheck{name="healthcheck-a",status="pending",type="healthz"} 0 + kubernetes_healthcheck{name="healthcheck-a",status="success",type="healthz"} 0 + # HELP kubernetes_healthchecks_total [ALPHA] This metric records the results of all healthcheck. + # TYPE kubernetes_healthchecks_total counter + kubernetes_healthchecks_total{name="healthcheck-a",status="error",type="healthz"} 1 ` testCases := []struct { desc string @@ -57,15 +57,15 @@ func TestObserveHealthcheck(t *testing.T) { hcType: Healthz, hcStatus: Pending, want: ` - # HELP k8s_healthcheck [ALPHA] This metric records the result of a single healthcheck. - # TYPE k8s_healthcheck gauge - k8s_healthcheck{name="healthcheck-a",status="error",type="healthz"} 0 - k8s_healthcheck{name="healthcheck-a",status="pending",type="healthz"} 1 - k8s_healthcheck{name="healthcheck-a",status="success",type="healthz"} 0 - # HELP k8s_healthchecks_total [ALPHA] This metric records the results of all healthcheck. - # TYPE k8s_healthchecks_total counter - k8s_healthchecks_total{name="healthcheck-a",status="error",type="healthz"} 1 - k8s_healthchecks_total{name="healthcheck-a",status="pending",type="healthz"} 1 + # HELP kubernetes_healthcheck [ALPHA] This metric records the result of a single healthcheck. + # TYPE kubernetes_healthcheck gauge + kubernetes_healthcheck{name="healthcheck-a",status="error",type="healthz"} 0 + kubernetes_healthcheck{name="healthcheck-a",status="pending",type="healthz"} 1 + kubernetes_healthcheck{name="healthcheck-a",status="success",type="healthz"} 0 + # HELP kubernetes_healthchecks_total [ALPHA] This metric records the results of all healthcheck. + # TYPE kubernetes_healthchecks_total counter + kubernetes_healthchecks_total{name="healthcheck-a",status="error",type="healthz"} 1 + kubernetes_healthchecks_total{name="healthcheck-a",status="pending",type="healthz"} 1 `, }, { @@ -74,15 +74,15 @@ func TestObserveHealthcheck(t *testing.T) { hcType: Healthz, hcStatus: Success, want: ` - # HELP k8s_healthcheck [ALPHA] This metric records the result of a single healthcheck. - # TYPE k8s_healthcheck gauge - k8s_healthcheck{name="healthcheck-a",status="error",type="healthz"} 0 - k8s_healthcheck{name="healthcheck-a",status="pending",type="healthz"} 0 - k8s_healthcheck{name="healthcheck-a",status="success",type="healthz"} 1 - # HELP k8s_healthchecks_total [ALPHA] This metric records the results of all healthcheck. - # TYPE k8s_healthchecks_total counter - k8s_healthchecks_total{name="healthcheck-a",status="error",type="healthz"} 1 - k8s_healthchecks_total{name="healthcheck-a",status="success",type="healthz"} 1 + # HELP kubernetes_healthcheck [ALPHA] This metric records the result of a single healthcheck. + # TYPE kubernetes_healthcheck gauge + kubernetes_healthcheck{name="healthcheck-a",status="error",type="healthz"} 0 + kubernetes_healthcheck{name="healthcheck-a",status="pending",type="healthz"} 0 + kubernetes_healthcheck{name="healthcheck-a",status="success",type="healthz"} 1 + # HELP kubernetes_healthchecks_total [ALPHA] This metric records the results of all healthcheck. + # TYPE kubernetes_healthchecks_total counter + kubernetes_healthchecks_total{name="healthcheck-a",status="error",type="healthz"} 1 + kubernetes_healthchecks_total{name="healthcheck-a",status="success",type="healthz"} 1 `, }, }