From ee481149d7bb44b7ce59590b159436b128a46e53 Mon Sep 17 00:00:00 2001 From: Anish Ramasekar Date: Sat, 9 Mar 2024 13:29:56 -0800 Subject: [PATCH] Add metrics for authentication config reload Signed-off-by: Anish Ramasekar Kubernetes-commit: 62ac88b9ea5dace6a61b784f4654fcf379b958e2 --- .../authenticationconfig/metrics/metrics.go | 88 ++++++++++++++ .../metrics/metrics_test.go | 109 ++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 pkg/server/options/authenticationconfig/metrics/metrics.go create mode 100644 pkg/server/options/authenticationconfig/metrics/metrics_test.go diff --git a/pkg/server/options/authenticationconfig/metrics/metrics.go b/pkg/server/options/authenticationconfig/metrics/metrics.go new file mode 100644 index 000000000..e57ba5563 --- /dev/null +++ b/pkg/server/options/authenticationconfig/metrics/metrics.go @@ -0,0 +1,88 @@ +/* +Copyright 2024 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 ( + "crypto/sha256" + "fmt" + "sync" + + "k8s.io/component-base/metrics" + "k8s.io/component-base/metrics/legacyregistry" +) + +const ( + namespace = "apiserver" + subsystem = "authentication_config_controller" +) + +var ( + authenticationConfigAutomaticReloadsTotal = metrics.NewCounterVec( + &metrics.CounterOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "automatic_reloads_total", + Help: "Total number of automatic reloads of authentication configuration split by status and apiserver identity.", + StabilityLevel: metrics.ALPHA, + }, + []string{"status", "apiserver_id_hash"}, + ) + + authenticationConfigAutomaticReloadLastTimestampSeconds = metrics.NewGaugeVec( + &metrics.GaugeOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "automatic_reload_last_timestamp_seconds", + Help: "Timestamp of the last automatic reload of authentication configuration split by status and apiserver identity.", + StabilityLevel: metrics.ALPHA, + }, + []string{"status", "apiserver_id_hash"}, + ) +) + +var registerMetrics sync.Once + +func RegisterMetrics() { + registerMetrics.Do(func() { + legacyregistry.MustRegister(authenticationConfigAutomaticReloadsTotal) + legacyregistry.MustRegister(authenticationConfigAutomaticReloadLastTimestampSeconds) + }) +} + +func ResetMetricsForTest() { + authenticationConfigAutomaticReloadsTotal.Reset() + authenticationConfigAutomaticReloadLastTimestampSeconds.Reset() +} + +func RecordAuthenticationConfigAutomaticReloadFailure(apiServerID string) { + apiServerIDHash := getHash(apiServerID) + authenticationConfigAutomaticReloadsTotal.WithLabelValues("failure", apiServerIDHash).Inc() + authenticationConfigAutomaticReloadLastTimestampSeconds.WithLabelValues("failure", apiServerIDHash).SetToCurrentTime() +} + +func RecordAuthenticationConfigAutomaticReloadSuccess(apiServerID string) { + apiServerIDHash := getHash(apiServerID) + authenticationConfigAutomaticReloadsTotal.WithLabelValues("success", apiServerIDHash).Inc() + authenticationConfigAutomaticReloadLastTimestampSeconds.WithLabelValues("success", apiServerIDHash).SetToCurrentTime() +} + +func getHash(data string) string { + if len(data) == 0 { + return "" + } + return fmt.Sprintf("sha256:%x", sha256.Sum256([]byte(data))) +} diff --git a/pkg/server/options/authenticationconfig/metrics/metrics_test.go b/pkg/server/options/authenticationconfig/metrics/metrics_test.go new file mode 100644 index 000000000..75ef1868d --- /dev/null +++ b/pkg/server/options/authenticationconfig/metrics/metrics_test.go @@ -0,0 +1,109 @@ +/* +Copyright 2024 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 ( + "strings" + "testing" + + "k8s.io/component-base/metrics/legacyregistry" + "k8s.io/component-base/metrics/testutil" +) + +const ( + testAPIServerID = "testAPIServerID" + testAPIServerIDHash = "sha256:14f9d63e669337ac6bfda2e2162915ee6a6067743eddd4e5c374b572f951ff37" +) + +func TestRecordAuthenticationConfigAutomaticReloadFailure(t *testing.T) { + expectedValue := ` + # HELP apiserver_authentication_config_controller_automatic_reloads_total [ALPHA] Total number of automatic reloads of authentication configuration split by status and apiserver identity. + # TYPE apiserver_authentication_config_controller_automatic_reloads_total counter + apiserver_authentication_config_controller_automatic_reloads_total {apiserver_id_hash="sha256:14f9d63e669337ac6bfda2e2162915ee6a6067743eddd4e5c374b572f951ff37",status="failure"} 1 + ` + metrics := []string{ + namespace + "_" + subsystem + "_automatic_reloads_total", + } + + authenticationConfigAutomaticReloadsTotal.Reset() + RegisterMetrics() + + RecordAuthenticationConfigAutomaticReloadFailure(testAPIServerID) + if err := testutil.GatherAndCompare(legacyregistry.DefaultGatherer, strings.NewReader(expectedValue), metrics...); err != nil { + t.Fatal(err) + } +} + +func TestRecordAuthenticationConfigAutomaticReloadSuccess(t *testing.T) { + expectedValue := ` + # HELP apiserver_authentication_config_controller_automatic_reloads_total [ALPHA] Total number of automatic reloads of authentication configuration split by status and apiserver identity. + # TYPE apiserver_authentication_config_controller_automatic_reloads_total counter + apiserver_authentication_config_controller_automatic_reloads_total {apiserver_id_hash="sha256:14f9d63e669337ac6bfda2e2162915ee6a6067743eddd4e5c374b572f951ff37",status="success"} 1 + ` + metrics := []string{ + namespace + "_" + subsystem + "_automatic_reloads_total", + } + + authenticationConfigAutomaticReloadsTotal.Reset() + RegisterMetrics() + + RecordAuthenticationConfigAutomaticReloadSuccess(testAPIServerID) + if err := testutil.GatherAndCompare(legacyregistry.DefaultGatherer, strings.NewReader(expectedValue), metrics...); err != nil { + t.Fatal(err) + } +} + +func TestAuthenticationConfigAutomaticReloadLastTimestampSeconds(t *testing.T) { + testCases := []struct { + expectedValue string + resultLabel string + timestamp int64 + }{ + { + expectedValue: ` + # HELP apiserver_authentication_config_controller_automatic_reload_last_timestamp_seconds [ALPHA] Timestamp of the last automatic reload of authentication configuration split by status and apiserver identity. + # TYPE apiserver_authentication_config_controller_automatic_reload_last_timestamp_seconds gauge + apiserver_authentication_config_controller_automatic_reload_last_timestamp_seconds{apiserver_id_hash="sha256:14f9d63e669337ac6bfda2e2162915ee6a6067743eddd4e5c374b572f951ff37",status="failure"} 1.689101941e+09 + `, + resultLabel: "failure", + timestamp: 1689101941, + }, + { + expectedValue: ` + # HELP apiserver_authentication_config_controller_automatic_reload_last_timestamp_seconds [ALPHA] Timestamp of the last automatic reload of authentication configuration split by status and apiserver identity. + # TYPE apiserver_authentication_config_controller_automatic_reload_last_timestamp_seconds gauge + apiserver_authentication_config_controller_automatic_reload_last_timestamp_seconds{apiserver_id_hash="sha256:14f9d63e669337ac6bfda2e2162915ee6a6067743eddd4e5c374b572f951ff37",status="success"} 1.689101941e+09 + `, + resultLabel: "success", + timestamp: 1689101941, + }, + } + + metrics := []string{ + namespace + "_" + subsystem + "_automatic_reload_last_timestamp_seconds", + } + RegisterMetrics() + + for _, tc := range testCases { + authenticationConfigAutomaticReloadLastTimestampSeconds.Reset() + authenticationConfigAutomaticReloadLastTimestampSeconds.WithLabelValues(tc.resultLabel, testAPIServerIDHash).Set(float64(tc.timestamp)) + + if err := testutil.GatherAndCompare(legacyregistry.DefaultGatherer, strings.NewReader(tc.expectedValue), metrics...); err != nil { + t.Fatal(err) + } + } +}