Skip to content

Commit 38a5332

Browse files
add missing metrics
1 parent ede5f1d commit 38a5332

File tree

6 files changed

+125
-45
lines changed

6 files changed

+125
-45
lines changed

controllers/secretproviderclasspodstatus_controller.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ type SecretProviderClassPodStatusReconciler struct {
6565
writer client.Writer
6666
eventRecorder record.EventRecorder
6767
driverName string
68+
reporter StatsReporter
6869
}
6970

7071
// New creates a new SecretProviderClassPodStatusReconciler
@@ -73,6 +74,10 @@ func New(driverName string, mgr manager.Manager, nodeID string) (*SecretProvider
7374
kubeClient := kubernetes.NewForConfigOrDie(mgr.GetConfig())
7475
eventBroadcaster.StartRecordingToSink(&clientcorev1.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")})
7576
recorder := eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: "csi-secrets-store-controller"})
77+
sr, err := newStatsReporter()
78+
if err != nil {
79+
return nil, err
80+
}
7681

7782
return &SecretProviderClassPodStatusReconciler{
7883
Client: mgr.GetClient(),
@@ -83,6 +88,7 @@ func New(driverName string, mgr manager.Manager, nodeID string) (*SecretProvider
8388
writer: mgr.GetClient(),
8489
eventRecorder: recorder,
8590
driverName: driverName,
91+
reporter: sr,
8692
}, nil
8793
}
8894

@@ -217,7 +223,7 @@ func (r *SecretProviderClassPodStatusReconciler) ListOptionsLabelSelector() clie
217223
// +kubebuilder:rbac:groups="",resources=events,verbs=create;patch
218224
// +kubebuilder:rbac:groups="storage.k8s.io",resources=csidrivers,verbs=get;list;watch,resourceNames=secrets-store.csi.k8s.io
219225

220-
func (r *SecretProviderClassPodStatusReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
226+
func (r *SecretProviderClassPodStatusReconciler) Reconcile(ctx context.Context, req ctrl.Request) (res ctrl.Result, e error) {
221227
r.mutex.Lock()
222228
defer r.mutex.Unlock()
223229

@@ -266,6 +272,18 @@ func (r *SecretProviderClassPodStatusReconciler) Reconcile(ctx context.Context,
266272
return ctrl.Result{}, nil
267273
}
268274

275+
begin := time.Now()
276+
providerName := string(spc.Spec.Provider)
277+
namespace := spcPodStatus.Namespace
278+
secretProviderClass := spc.Name
279+
defer func() {
280+
// if there is SecretObjects defined in the SPC, then report the metric if sync is successful
281+
if e == nil && !res.Requeue {
282+
r.reporter.ReportSyncSecretCtMetric(ctx, providerName, namespace, secretProviderClass)
283+
r.reporter.ReportSyncSecretDuration(ctx, time.Since(begin).Seconds())
284+
}
285+
}()
286+
269287
// determine which pod volume this is associated with
270288
podVol := k8sutil.SPCVolume(pod, r.driverName, spc.Name)
271289
if podVol == nil {

controllers/stats_reporter.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
Copyright 2024 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 controllers
18+
19+
import (
20+
"context"
21+
"go.opentelemetry.io/otel/attribute"
22+
"go.opentelemetry.io/otel/metric"
23+
"go.opentelemetry.io/otel/metric/global"
24+
"runtime"
25+
)
26+
27+
const (
28+
scope = "sigs.k8s.io/secrets-store-csi-driver"
29+
)
30+
31+
var (
32+
providerKey = "provider"
33+
osTypeKey = "os_type"
34+
runtimeOS = runtime.GOOS
35+
namespaceKey = "namespace"
36+
spcKey = "secret_provider_class"
37+
)
38+
39+
type reporter struct {
40+
syncK8sSecretTotal metric.Int64Counter
41+
syncK8sSecretDuration metric.Float64Histogram
42+
}
43+
44+
type StatsReporter interface {
45+
ReportSyncSecretCtMetric(ctx context.Context, provider, namespace, spc string)
46+
ReportSyncSecretDuration(ctx context.Context, duration float64)
47+
}
48+
49+
func newStatsReporter() (StatsReporter, error) {
50+
var err error
51+
52+
r := &reporter{}
53+
meter := global.Meter(scope)
54+
55+
if r.syncK8sSecretTotal, err = meter.Int64Counter("sync_k8s_secret", metric.WithDescription("Total number of k8s secrets synced")); err != nil {
56+
return nil, err
57+
}
58+
if r.syncK8sSecretDuration, err = meter.Float64Histogram("sync_k8s_secret_duration_sec", metric.WithDescription("Distribution of how long it took to sync k8s secret")); err != nil {
59+
return nil, err
60+
}
61+
return r, nil
62+
}
63+
64+
func (r reporter) ReportSyncSecretCtMetric(ctx context.Context, provider, namespace, spc string) {
65+
opt := metric.WithAttributes(
66+
attribute.Key(providerKey).String(provider),
67+
attribute.Key(osTypeKey).String(runtimeOS),
68+
attribute.Key(namespaceKey).String(namespace),
69+
attribute.Key(spcKey).String(spc),
70+
)
71+
r.syncK8sSecretTotal.Add(ctx, 1, opt)
72+
}
73+
74+
func (r reporter) ReportSyncSecretDuration(ctx context.Context, duration float64) {
75+
opt := metric.WithAttributes(
76+
attribute.Key(osTypeKey).String(runtimeOS),
77+
)
78+
r.syncK8sSecretDuration.Record(ctx, duration, opt)
79+
}

docs/book/src/topics/metrics.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ Prometheus is the only exporter that's currently supported with the driver.
1212
| node_unpublish_total | Total number of successful volume unmount requests | `os_type=<runtime os>` |
1313
| node_publish_error_total | Total number of errors with volume mount requests | `os_type=<runtime os>`<br>`provider=<provider name>`<br>`error_type=<error code>`<br>`pod_name=<pod_name>`<br>`pod_namespace=<pod_namespace>`<br>`secret_provider_class=<secret_provider_class>` |
1414
| node_unpublish_error_total | Total number of errors with volume unmount requests | `os_type=<runtime os>` |
15+
| sync_k8s_secret_total | Total number of k8s secrets synced | `os_type=<runtime os>`<br>`provider=<provider name>`<br>`namespace=<namespace>`<br>`secret_provider_class=<secret_provider_class>` |
16+
| sync_k8s_secret_duration_sec | Distribution of how long it took to sync k8s secret | `os_type=<runtime os>` |
1517
| rotation_reconcile_total | Total number of rotation reconciles | `os_type=<runtime os>`<br>`rotated=<true or false>`<br>`pod_name=<pod_name>`<br>`pod_namespace=<pod_namespace>`<br>`secret_provider_class=<secret_provider_class>` |
1618
| rotation_reconcile_error_total | Total number of rotation reconciles with error | `os_type=<runtime os>`<br>`rotated=<true or false>`<br>`error_type=<error code>`<br>`pod_name=<pod_name>`<br>`pod_namespace=<pod_namespace>`<br>`secret_provider_class=<secret_provider_class>` |
1719
| rotation_reconcile_duration_sec | Distribution of how long it took to rotate secrets-store content for pods | `os_type=<runtime os>`<br>`pod_name=<pod_name>`<br>`pod_namespace=<pod_namespace>`<br>`secret_provider_class=<secret_provider_class>` |
@@ -26,6 +28,30 @@ curl localhost:8095/metrics
2628
### Sample Metrics output
2729

2830
```shell
31+
# HELP sync_k8s_secret_duration_sec Distribution of how long it took to sync k8s secret
32+
# TYPE sync_k8s_secret_duration_sec histogram
33+
sync_k8s_secret_duration_sec_bucket{os_type="linux",le="0.1"} 0
34+
sync_k8s_secret_duration_sec_bucket{os_type="linux",le="0.2"} 0
35+
sync_k8s_secret_duration_sec_bucket{os_type="linux",le="0.3"} 0
36+
sync_k8s_secret_duration_sec_bucket{os_type="linux",le="0.4"} 1
37+
sync_k8s_secret_duration_sec_bucket{os_type="linux",le="0.5"} 1
38+
sync_k8s_secret_duration_sec_bucket{os_type="linux",le="1"} 1
39+
sync_k8s_secret_duration_sec_bucket{os_type="linux",le="1.5"} 1
40+
sync_k8s_secret_duration_sec_bucket{os_type="linux",le="2"} 1
41+
sync_k8s_secret_duration_sec_bucket{os_type="linux",le="2.5"} 1
42+
sync_k8s_secret_duration_sec_bucket{os_type="linux",le="3"} 1
43+
sync_k8s_secret_duration_sec_bucket{os_type="linux",le="5"} 1
44+
sync_k8s_secret_duration_sec_bucket{os_type="linux",le="10"} 1
45+
sync_k8s_secret_duration_sec_bucket{os_type="linux",le="15"} 1
46+
sync_k8s_secret_duration_sec_bucket{os_type="linux",le="30"} 1
47+
sync_k8s_secret_duration_sec_bucket{os_type="linux",le="+Inf"} 1
48+
sync_k8s_secret_duration_sec_sum{os_type="linux"} 0.3115892
49+
sync_k8s_secret_duration_sec_count{os_type="linux"} 1
50+
51+
# HELP sync_k8s_secret_total Total number of k8s secrets synced
52+
# TYPE sync_k8s_secret_total counter
53+
sync_k8s_secret_total{namespace="csi-test-secret-ns",os_type="linux",provider="azure",secret_provider_class="csi-test-spc"} 1
54+
2955
# HELP rotation_reconcile_duration_sec Distribution of how long it took to rotate secrets-store content for pods
3056
# TYPE rotation_reconcile_duration_sec histogram
3157
rotation_reconcile_duration_sec_bucket{os_type="linux",le="0.1"} 0

pkg/secrets-store/mocks/stats_reporter_mock.go

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ type FakeReporter struct {
3131
reportNodeUnPublishCtMetricInvoked int
3232
reportNodePublishErrorCtMetricInvoked int
3333
reportNodeUnPublishErrorCtMetricInvoked int
34-
reportSyncK8SecretCtMetricInvoked int
35-
reportSyncK8SecretDurationInvoked int
3634
metricDetails []MetricDetails
3735
}
3836

@@ -71,14 +69,6 @@ func (f *FakeReporter) ReportNodeUnPublishErrorCtMetric(ctx context.Context) {
7169
f.reportNodeUnPublishErrorCtMetricInvoked++
7270
}
7371

74-
func (f *FakeReporter) ReportSyncK8SecretCtMetric(ctx context.Context, provider, podName, podNamespace, spc string, count int) {
75-
f.reportSyncK8SecretCtMetricInvoked++
76-
}
77-
78-
func (f *FakeReporter) ReportSyncK8SecretDuration(ctx context.Context, duration float64) {
79-
f.reportSyncK8SecretDurationInvoked++
80-
}
81-
8272
func (f *FakeReporter) ReportNodePublishCtMetricInvoked() int {
8373
return f.reportNodePublishCtMetricInvoked
8474
}
@@ -91,12 +81,6 @@ func (f *FakeReporter) ReportNodePublishErrorCtMetricInvoked() int {
9181
func (f *FakeReporter) ReportNodeUnPublishErrorCtMetricInvoked() int {
9282
return f.reportNodeUnPublishErrorCtMetricInvoked
9383
}
94-
func (f *FakeReporter) ReportSyncK8SecretCtMetricInvoked() int {
95-
return f.reportSyncK8SecretCtMetricInvoked
96-
}
97-
func (f *FakeReporter) ReportSyncK8SecretDurationInvoked() int {
98-
return f.reportSyncK8SecretDurationInvoked
99-
}
10084

10185
func (f *FakeReporter) GetMetricDetails() []MetricDetails {
10286
return f.metricDetails

pkg/secrets-store/stats_reporter.go

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,13 @@ type reporter struct {
4444
nodeUnPublishTotal metric.Int64Counter
4545
nodePublishErrorTotal metric.Int64Counter
4646
nodeUnPublishErrorTotal metric.Int64Counter
47-
syncK8sSecretTotal metric.Int64Counter
48-
syncK8sSecretDuration metric.Float64Histogram
4947
}
5048

5149
type StatsReporter interface {
5250
ReportNodePublishCtMetric(ctx context.Context, provider, podName, podNamespace, spc string)
5351
ReportNodeUnPublishCtMetric(ctx context.Context)
5452
ReportNodePublishErrorCtMetric(ctx context.Context, provider, podName, podNamespace, spc, errType string)
5553
ReportNodeUnPublishErrorCtMetric(ctx context.Context)
56-
ReportSyncK8SecretCtMetric(ctx context.Context, provider, podName, podNamespace, spc string, count int)
57-
ReportSyncK8SecretDuration(ctx context.Context, duration float64)
5854
}
5955

6056
func NewStatsReporter() (StatsReporter, error) {
@@ -75,12 +71,6 @@ func NewStatsReporter() (StatsReporter, error) {
7571
if r.nodeUnPublishErrorTotal, err = meter.Int64Counter("node_unpublish_error", metric.WithDescription("Total number of node unpublish calls with error")); err != nil {
7672
return nil, err
7773
}
78-
if r.syncK8sSecretTotal, err = meter.Int64Counter("sync_k8s_secret", metric.WithDescription("Total number of k8s secrets synced")); err != nil {
79-
return nil, err
80-
}
81-
if r.syncK8sSecretDuration, err = meter.Float64Histogram("k8s_secret_duration_sec", metric.WithDescription("Distribution of how long it took to sync k8s secret")); err != nil {
82-
return nil, err
83-
}
8474
return r, nil
8575
}
8676

@@ -120,21 +110,3 @@ func (r *reporter) ReportNodeUnPublishErrorCtMetric(ctx context.Context) {
120110
)
121111
r.nodeUnPublishErrorTotal.Add(ctx, 1, opt)
122112
}
123-
124-
func (r *reporter) ReportSyncK8SecretCtMetric(ctx context.Context, provider, podName, podNamespace, spc string, count int) {
125-
opt := metric.WithAttributes(
126-
attribute.Key(providerKey).String(provider),
127-
attribute.Key(osTypeKey).String(runtimeOS),
128-
attribute.Key(podNameKey).String(podName),
129-
attribute.Key(podNamespaceKey).String(podNamespace),
130-
attribute.Key(spcKey).String(spc),
131-
)
132-
r.syncK8sSecretTotal.Add(ctx, int64(count), opt)
133-
}
134-
135-
func (r *reporter) ReportSyncK8SecretDuration(ctx context.Context, duration float64) {
136-
opt := metric.WithAttributes(
137-
attribute.Key(osTypeKey).String(runtimeOS),
138-
)
139-
r.syncK8sSecretDuration.Record(ctx, duration, opt)
140-
}

test/bats/e2e-provider.bats

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ export VALIDATE_TOKENS_AUDIENCE=$(get_token_requests_audience)
428428
assert_match "node_publish_total" "${output}"
429429
assert_match "node_unpublish_total" "${output}"
430430
assert_match "rotation_reconcile_total" "${output}"
431+
assert_match "sync_k8s_secret_total" "${output}"
431432
done
432433
}
433434

0 commit comments

Comments
 (0)