Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(metrics): provide metrics for tenant quotas #1094

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions controllers/tenant/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/reconcile"

capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2"
"github.com/projectcapsule/capsule/pkg/metrics"
)

type Manager struct {
Expand Down Expand Up @@ -48,6 +49,10 @@ func (r Manager) Reconcile(ctx context.Context, request ctrl.Request) (result ct
if apierrors.IsNotFound(err) {
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
metrics.TenantResourceUsage.DeletePartialMatch(map[string]string{"tenant": request.Name})
metrics.TenantResourceLimit.DeletePartialMatch(map[string]string{"tenant": request.Name})

return reconcile.Result{}, nil
}

Expand Down
26 changes: 26 additions & 0 deletions controllers/tenant/resourcequotas.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (

capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2"
"github.com/projectcapsule/capsule/pkg/api"
"github.com/projectcapsule/capsule/pkg/metrics"
"github.com/projectcapsule/capsule/pkg/utils"
)

Expand Down Expand Up @@ -51,6 +52,18 @@ func (r *Manager) syncResourceQuotas(ctx context.Context, tenant *capsulev1beta2
if typeLabel, err = utils.GetTypeLabel(&corev1.ResourceQuota{}); err != nil {
return err
}

// Remove prior metrics, to avoid cleaning up for metrics of deleted ResourceQuotas
metrics.TenantResourceUsage.DeletePartialMatch(map[string]string{"tenant": tenant.Name})
metrics.TenantResourceLimit.DeletePartialMatch(map[string]string{"tenant": tenant.Name})

// Expose the namespace quota and usage as metrics for the tenant
metrics.TenantResourceUsage.WithLabelValues(tenant.Name, "namespaces", "").Set(float64(tenant.Status.Size))

if tenant.Spec.NamespaceOptions != nil && tenant.Spec.NamespaceOptions.Quota != nil {
metrics.TenantResourceLimit.WithLabelValues(tenant.Name, "namespaces", "").Set(float64(*tenant.Spec.NamespaceOptions.Quota))
}

//nolint:nestif
if tenant.Spec.ResourceQuota.Scope == api.ResourceQuotaScopeTenant {
group := new(errgroup.Group)
Expand Down Expand Up @@ -102,6 +115,19 @@ func (r *Manager) syncResourceQuotas(ctx context.Context, tenant *capsulev1beta2

r.Log.Info("Computed " + name.String() + " quota for the whole Tenant is " + quantity.String())

// Expose usage and limit metrics for the resource (name) of the ResourceQuota (index)
metrics.TenantResourceUsage.WithLabelValues(
tenant.Name,
name.String(),
strconv.Itoa(index),
).Set(float64(quantity.MilliValue()) / 1000)

metrics.TenantResourceLimit.WithLabelValues(
tenant.Name,
name.String(),
strconv.Itoa(index),
).Set(float64(hardQuota.MilliValue()) / 1000)

switch quantity.Cmp(resourceQuota.Hard[name]) {
case 0:
// The Tenant is matching exactly the Quota:
Expand Down
30 changes: 30 additions & 0 deletions pkg/metrics/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2020-2023 Project Capsule Authors.
// SPDX-License-Identifier: Apache-2.0

package metrics

import (
"github.com/prometheus/client_golang/prometheus"
"sigs.k8s.io/controller-runtime/pkg/metrics"
)

var (
metricsPrefix = "capsule_"

TenantResourceUsage = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Name: metricsPrefix + "tenant_resource_usage",
Help: "Current resource usage for a given resource in a tenant",
}, []string{"tenant", "resource", "resourcequotaindex"})

TenantResourceLimit = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Name: metricsPrefix + "tenant_resource_limit",
Help: "Current resource limit for a given resource in a tenant",
}, []string{"tenant", "resource", "resourcequotaindex"})
)

func init() {
metrics.Registry.MustRegister(
TenantResourceUsage,
TenantResourceLimit,
)
}
Loading