feat(tenant): expose additional metrics (#1517)

* feat(tenant): expose additional metrics

Signed-off-by: Hristo Hristov <me@hhristov.info>

* feat(tenant): expose additional metrics

Signed-off-by: Hristo Hristov <me@hhristov.info>

* feat(tenant): expose additional metrics

Signed-off-by: Hristo Hristov <me@hhristov.info>

* feat(tenant): expose additional metrics

Signed-off-by: Hristo Hristov <me@hhristov.info>

* chore(lint): fix golint problems

Signed-off-by: Hristo Hristov <me@hhristov.info>

* feat(tenant): expose additional metrics

Signed-off-by: Hristo Hristov <me@hhristov.info>

* feat(tenant): expose additional metrics

Signed-off-by: Hristo Hristov <me@hhristov.info>

* feat(tenant): fix linting

Signed-off-by: Hristo Hristov <me@hhristov.info>

* feat(tenant): expose additional metrics

Signed-off-by: Hristo Hristov <me@hhristov.info>

* feat(tenant): expose additional metrics

Signed-off-by: Hristo Hristov <me@hhristov.info>

* feat(tenant): expose additional metrics

Signed-off-by: Hristo Hristov <me@hhristov.info>

* feat(tenant): expose additional metrics

Signed-off-by: Hristo Hristov <me@hhristov.info>

---------

Signed-off-by: Hristo Hristov <me@hhristov.info>
This commit is contained in:
Hristo Hristov
2025-08-01 15:57:38 +02:00
committed by GitHub
parent bdcae3af42
commit e234200d1c
4 changed files with 98 additions and 6 deletions
+8 -1
View File
@@ -53,7 +53,7 @@ func (r Manager) Reconcile(ctx context.Context, request ctrl.Request) (result ct
r.Log.Info("Request object not found, could have been deleted after reconcile request")
// If tenant was deleted or cannot be found, clean up metrics
r.Metrics.DeleteTenantMetric(request.Name)
r.Metrics.DeleteAllMetrics(request.Name)
return reconcile.Result{}, nil
}
@@ -62,6 +62,9 @@ func (r Manager) Reconcile(ctx context.Context, request ctrl.Request) (result ct
return
}
preRecNamespaces := instance.Status.Namespaces
// Ensuring the Tenant Status
if err = r.updateTenantStatus(ctx, instance); err != nil {
r.Log.Error(err, "Cannot update Tenant status")
@@ -91,6 +94,10 @@ func (r Manager) Reconcile(ctx context.Context, request ctrl.Request) (result ct
return
}
// Ensuring Status metrics are exposed
r.Log.Info("Ensuring all status metrics are exposed")
r.syncStatusMetrics(instance, preRecNamespaces)
// Ensuring Namespace metadata
r.Log.Info("Starting processing of Namespaces", "items", len(instance.Status.Namespaces))
+34
View File
@@ -0,0 +1,34 @@
// Copyright 2020-2025 Project Capsule Authors
// SPDX-License-Identifier: Apache-2.0
package tenant
import (
"slices"
capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2"
)
// Exposing Status Metrics for tenant.
func (r *Manager) syncStatusMetrics(tenant *capsulev1beta2.Tenant, preRecNamespaces []string) {
var cordoned float64 = 0
// Expose namespace-tenant relationship
for _, ns := range tenant.Status.Namespaces {
r.Metrics.TenantNamespaceRelationshipGauge.WithLabelValues(tenant.GetName(), ns).Set(1)
}
// Cleanup deleted namespaces
for _, ns := range preRecNamespaces {
if !slices.Contains(tenant.Status.Namespaces, ns) {
r.Metrics.DeleteNamespaceRelationshipMetrics(ns)
}
}
if tenant.Spec.Cordoned {
cordoned = 1
}
// Expose cordoned status
r.Metrics.TenantNamespaceCounterGauge.WithLabelValues(tenant.Name).Set(float64(tenant.Status.Size))
// Expose the namespace counter
r.Metrics.TenantCordonedStatusGauge.WithLabelValues(tenant.Name).Set(cordoned)
}
+1 -2
View File
@@ -53,8 +53,7 @@ func (r *Manager) syncResourceQuotas(ctx context.Context, tenant *capsulev1beta2
}
// Remove prior metrics, to avoid cleaning up for metrics of deleted ResourceQuotas
r.Metrics.DeleteTenantMetric(tenant.Name)
r.Metrics.DeleteTenantResourceMetrics(tenant.Name)
// Expose the namespace quota and usage as metrics for the tenant
r.Metrics.TenantResourceUsageGauge.WithLabelValues(tenant.Name, "namespaces", "").Set(float64(tenant.Status.Size))
+55 -3
View File
@@ -9,8 +9,11 @@ import (
)
type TenantRecorder struct {
TenantResourceUsageGauge *prometheus.GaugeVec
TenantResourceLimitGauge *prometheus.GaugeVec
TenantNamespaceRelationshipGauge *prometheus.GaugeVec
TenantCordonedStatusGauge *prometheus.GaugeVec
TenantNamespaceCounterGauge *prometheus.GaugeVec
TenantResourceUsageGauge *prometheus.GaugeVec
TenantResourceLimitGauge *prometheus.GaugeVec
}
func MustMakeTenantRecorder() *TenantRecorder {
@@ -22,6 +25,27 @@ func MustMakeTenantRecorder() *TenantRecorder {
func NewTenantRecorder() *TenantRecorder {
return &TenantRecorder{
TenantNamespaceRelationshipGauge: prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: metricsPrefix,
Name: "tenant_namespace_relationship",
Help: "Mapping metric showing namespace to tenant relationships",
}, []string{"tenant", "namespace"},
),
TenantCordonedStatusGauge: prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: metricsPrefix,
Name: "tenant_status",
Help: "Tenant cordon state indicating if tenant operations are restricted (1) or allowed (0) for resource creation and modification",
}, []string{"tenant"},
),
TenantNamespaceCounterGauge: prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: metricsPrefix,
Name: "tenant_namespace_count",
Help: "Total number of namespaces currently owned by the tenant",
}, []string{"tenant"},
),
TenantResourceUsageGauge: prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: metricsPrefix,
@@ -41,13 +65,16 @@ func NewTenantRecorder() *TenantRecorder {
func (r *TenantRecorder) Collectors() []prometheus.Collector {
return []prometheus.Collector{
r.TenantNamespaceRelationshipGauge,
r.TenantCordonedStatusGauge,
r.TenantNamespaceCounterGauge,
r.TenantResourceUsageGauge,
r.TenantResourceLimitGauge,
}
}
// DeleteCondition deletes the condition metrics for the ref.
func (r *TenantRecorder) DeleteTenantMetric(tenant string) {
func (r *TenantRecorder) DeleteTenantResourceMetrics(tenant string) {
r.TenantResourceUsageGauge.DeletePartialMatch(map[string]string{
"tenant": tenant,
})
@@ -55,3 +82,28 @@ func (r *TenantRecorder) DeleteTenantMetric(tenant string) {
"tenant": tenant,
})
}
// DeleteCondition deletes the condition metrics for the ref.
func (r *TenantRecorder) DeleteTenantStatusMetrics(tenant string) {
r.TenantNamespaceRelationshipGauge.DeletePartialMatch(map[string]string{
"tenant": tenant,
})
r.TenantResourceUsageGauge.DeletePartialMatch(map[string]string{
"tenant": tenant,
})
r.TenantResourceLimitGauge.DeletePartialMatch(map[string]string{
"tenant": tenant,
})
}
// DeleteCondition deletes the condition metrics for the ref.
func (r *TenantRecorder) DeleteNamespaceRelationshipMetrics(namespace string) {
r.TenantNamespaceRelationshipGauge.DeletePartialMatch(map[string]string{
"namespace": namespace,
})
}
func (r *TenantRecorder) DeleteAllMetrics(tenant string) {
r.DeleteTenantResourceMetrics(tenant)
r.DeleteTenantStatusMetrics(tenant)
}