Skip to content

Commit e234200

Browse files
authored
feat(tenant): expose additional metrics (#1517)
* feat(tenant): expose additional metrics Signed-off-by: Hristo Hristov <[email protected]> * feat(tenant): expose additional metrics Signed-off-by: Hristo Hristov <[email protected]> * feat(tenant): expose additional metrics Signed-off-by: Hristo Hristov <[email protected]> * feat(tenant): expose additional metrics Signed-off-by: Hristo Hristov <[email protected]> * chore(lint): fix golint problems Signed-off-by: Hristo Hristov <[email protected]> * feat(tenant): expose additional metrics Signed-off-by: Hristo Hristov <[email protected]> * feat(tenant): expose additional metrics Signed-off-by: Hristo Hristov <[email protected]> * feat(tenant): fix linting Signed-off-by: Hristo Hristov <[email protected]> * feat(tenant): expose additional metrics Signed-off-by: Hristo Hristov <[email protected]> * feat(tenant): expose additional metrics Signed-off-by: Hristo Hristov <[email protected]> * feat(tenant): expose additional metrics Signed-off-by: Hristo Hristov <[email protected]> * feat(tenant): expose additional metrics Signed-off-by: Hristo Hristov <[email protected]> --------- Signed-off-by: Hristo Hristov <[email protected]>
1 parent bdcae3a commit e234200

File tree

4 files changed

+98
-6
lines changed

4 files changed

+98
-6
lines changed

controllers/tenant/manager.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func (r Manager) Reconcile(ctx context.Context, request ctrl.Request) (result ct
5353
r.Log.Info("Request object not found, could have been deleted after reconcile request")
5454

5555
// If tenant was deleted or cannot be found, clean up metrics
56-
r.Metrics.DeleteTenantMetric(request.Name)
56+
r.Metrics.DeleteAllMetrics(request.Name)
5757

5858
return reconcile.Result{}, nil
5959
}
@@ -62,6 +62,9 @@ func (r Manager) Reconcile(ctx context.Context, request ctrl.Request) (result ct
6262

6363
return
6464
}
65+
66+
preRecNamespaces := instance.Status.Namespaces
67+
6568
// Ensuring the Tenant Status
6669
if err = r.updateTenantStatus(ctx, instance); err != nil {
6770
r.Log.Error(err, "Cannot update Tenant status")
@@ -91,6 +94,10 @@ func (r Manager) Reconcile(ctx context.Context, request ctrl.Request) (result ct
9194

9295
return
9396
}
97+
// Ensuring Status metrics are exposed
98+
r.Log.Info("Ensuring all status metrics are exposed")
99+
r.syncStatusMetrics(instance, preRecNamespaces)
100+
94101
// Ensuring Namespace metadata
95102
r.Log.Info("Starting processing of Namespaces", "items", len(instance.Status.Namespaces))
96103

controllers/tenant/metrics.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2020-2025 Project Capsule Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
package tenant
4+
5+
import (
6+
"slices"
7+
8+
capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2"
9+
)
10+
11+
// Exposing Status Metrics for tenant.
12+
func (r *Manager) syncStatusMetrics(tenant *capsulev1beta2.Tenant, preRecNamespaces []string) {
13+
var cordoned float64 = 0
14+
15+
// Expose namespace-tenant relationship
16+
for _, ns := range tenant.Status.Namespaces {
17+
r.Metrics.TenantNamespaceRelationshipGauge.WithLabelValues(tenant.GetName(), ns).Set(1)
18+
}
19+
20+
// Cleanup deleted namespaces
21+
for _, ns := range preRecNamespaces {
22+
if !slices.Contains(tenant.Status.Namespaces, ns) {
23+
r.Metrics.DeleteNamespaceRelationshipMetrics(ns)
24+
}
25+
}
26+
27+
if tenant.Spec.Cordoned {
28+
cordoned = 1
29+
}
30+
// Expose cordoned status
31+
r.Metrics.TenantNamespaceCounterGauge.WithLabelValues(tenant.Name).Set(float64(tenant.Status.Size))
32+
// Expose the namespace counter
33+
r.Metrics.TenantCordonedStatusGauge.WithLabelValues(tenant.Name).Set(cordoned)
34+
}

controllers/tenant/resourcequotas.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ func (r *Manager) syncResourceQuotas(ctx context.Context, tenant *capsulev1beta2
5353
}
5454

5555
// Remove prior metrics, to avoid cleaning up for metrics of deleted ResourceQuotas
56-
r.Metrics.DeleteTenantMetric(tenant.Name)
57-
56+
r.Metrics.DeleteTenantResourceMetrics(tenant.Name)
5857
// Expose the namespace quota and usage as metrics for the tenant
5958
r.Metrics.TenantResourceUsageGauge.WithLabelValues(tenant.Name, "namespaces", "").Set(float64(tenant.Status.Size))
6059

pkg/metrics/tenant_recorder.go

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@ import (
99
)
1010

1111
type TenantRecorder struct {
12-
TenantResourceUsageGauge *prometheus.GaugeVec
13-
TenantResourceLimitGauge *prometheus.GaugeVec
12+
TenantNamespaceRelationshipGauge *prometheus.GaugeVec
13+
TenantCordonedStatusGauge *prometheus.GaugeVec
14+
TenantNamespaceCounterGauge *prometheus.GaugeVec
15+
TenantResourceUsageGauge *prometheus.GaugeVec
16+
TenantResourceLimitGauge *prometheus.GaugeVec
1417
}
1518

1619
func MustMakeTenantRecorder() *TenantRecorder {
@@ -22,6 +25,27 @@ func MustMakeTenantRecorder() *TenantRecorder {
2225

2326
func NewTenantRecorder() *TenantRecorder {
2427
return &TenantRecorder{
28+
TenantNamespaceRelationshipGauge: prometheus.NewGaugeVec(
29+
prometheus.GaugeOpts{
30+
Namespace: metricsPrefix,
31+
Name: "tenant_namespace_relationship",
32+
Help: "Mapping metric showing namespace to tenant relationships",
33+
}, []string{"tenant", "namespace"},
34+
),
35+
TenantCordonedStatusGauge: prometheus.NewGaugeVec(
36+
prometheus.GaugeOpts{
37+
Namespace: metricsPrefix,
38+
Name: "tenant_status",
39+
Help: "Tenant cordon state indicating if tenant operations are restricted (1) or allowed (0) for resource creation and modification",
40+
}, []string{"tenant"},
41+
),
42+
TenantNamespaceCounterGauge: prometheus.NewGaugeVec(
43+
prometheus.GaugeOpts{
44+
Namespace: metricsPrefix,
45+
Name: "tenant_namespace_count",
46+
Help: "Total number of namespaces currently owned by the tenant",
47+
}, []string{"tenant"},
48+
),
2549
TenantResourceUsageGauge: prometheus.NewGaugeVec(
2650
prometheus.GaugeOpts{
2751
Namespace: metricsPrefix,
@@ -41,17 +65,45 @@ func NewTenantRecorder() *TenantRecorder {
4165

4266
func (r *TenantRecorder) Collectors() []prometheus.Collector {
4367
return []prometheus.Collector{
68+
r.TenantNamespaceRelationshipGauge,
69+
r.TenantCordonedStatusGauge,
70+
r.TenantNamespaceCounterGauge,
4471
r.TenantResourceUsageGauge,
4572
r.TenantResourceLimitGauge,
4673
}
4774
}
4875

4976
// DeleteCondition deletes the condition metrics for the ref.
50-
func (r *TenantRecorder) DeleteTenantMetric(tenant string) {
77+
func (r *TenantRecorder) DeleteTenantResourceMetrics(tenant string) {
78+
r.TenantResourceUsageGauge.DeletePartialMatch(map[string]string{
79+
"tenant": tenant,
80+
})
81+
r.TenantResourceLimitGauge.DeletePartialMatch(map[string]string{
82+
"tenant": tenant,
83+
})
84+
}
85+
86+
// DeleteCondition deletes the condition metrics for the ref.
87+
func (r *TenantRecorder) DeleteTenantStatusMetrics(tenant string) {
88+
r.TenantNamespaceRelationshipGauge.DeletePartialMatch(map[string]string{
89+
"tenant": tenant,
90+
})
5191
r.TenantResourceUsageGauge.DeletePartialMatch(map[string]string{
5292
"tenant": tenant,
5393
})
5494
r.TenantResourceLimitGauge.DeletePartialMatch(map[string]string{
5595
"tenant": tenant,
5696
})
5797
}
98+
99+
// DeleteCondition deletes the condition metrics for the ref.
100+
func (r *TenantRecorder) DeleteNamespaceRelationshipMetrics(namespace string) {
101+
r.TenantNamespaceRelationshipGauge.DeletePartialMatch(map[string]string{
102+
"namespace": namespace,
103+
})
104+
}
105+
106+
func (r *TenantRecorder) DeleteAllMetrics(tenant string) {
107+
r.DeleteTenantResourceMetrics(tenant)
108+
r.DeleteTenantStatusMetrics(tenant)
109+
}

0 commit comments

Comments
 (0)