mirror of
https://github.com/projectcapsule/capsule.git
synced 2026-08-25 16:07:24 +00:00
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:
@@ -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))
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user