From 57168d307ac51edd8b499b5a3b5cd8b77cc74586 Mon Sep 17 00:00:00 2001 From: Sebastian Widmer Date: Thu, 23 Feb 2023 09:12:49 +0100 Subject: [PATCH] Expose link between organization and billing-entity as a Prometheus metric (#104) --- controller.go | 6 +++ controllers/org_billing_ref_link_metric.go | 53 +++++++++++++++++++ .../org_billing_ref_link_metric_test.go | 41 ++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 controllers/org_billing_ref_link_metric.go create mode 100644 controllers/org_billing_ref_link_metric_test.go diff --git a/controller.go b/controller.go index c286a4cc..2e6712bf 100644 --- a/controller.go +++ b/controller.go @@ -15,6 +15,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" + "sigs.k8s.io/controller-runtime/pkg/metrics" "sigs.k8s.io/controller-runtime/pkg/webhook" "github.com/spf13/cobra" @@ -107,6 +108,11 @@ func setupManager(usernamePrefix, rolePrefix string, memberRoles []string, beRef return nil, err } + metrics.Registry.MustRegister( + &controllers.OrgBillingRefLinkMetric{ + Client: mgr.GetClient(), + }) + ur := &controllers.UserReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), diff --git a/controllers/org_billing_ref_link_metric.go b/controllers/org_billing_ref_link_metric.go new file mode 100644 index 00000000..bdbc4eb4 --- /dev/null +++ b/controllers/org_billing_ref_link_metric.go @@ -0,0 +1,53 @@ +package controllers + +import ( + "context" + + "github.com/prometheus/client_golang/prometheus" + "sigs.k8s.io/controller-runtime/pkg/client" + + orgv1 "github.com/appuio/control-api/apis/organization/v1" +) + +//+kubebuilder:rbac:groups="rbac.appuio.io",resources=organizations,verbs=get;list;watch +//+kubebuilder:rbac:groups="organization.appuio.io",resources=organizations,verbs=get;list;watch + +var desc = prometheus.NewDesc( + "control_api_organization_billing_entity_ref", + "Link between an organization and a billing entity", + []string{"organization", "billing_entity"}, + nil, +) + +// OrgBillingRefLinkMetric is a Prometheus collector that exposes the link between an organization and a billing entity. +type OrgBillingRefLinkMetric struct { + client.Client +} + +var _ prometheus.Collector = &OrgBillingRefLinkMetric{} + +// Describe implements prometheus.Collector. +// Sends the static description of the metric to the provided channel. +func (o *OrgBillingRefLinkMetric) Describe(ch chan<- *prometheus.Desc) { + ch <- desc +} + +// Collect implements prometheus.Collector. +// Sends a metric for each organization and its billing entity to the provided channel. +func (o *OrgBillingRefLinkMetric) Collect(ch chan<- prometheus.Metric) { + orgs := &orgv1.OrganizationList{} + if err := o.List(context.Background(), orgs); err != nil { + ch <- prometheus.NewInvalidMetric(desc, err) + return + } + + for _, org := range orgs.Items { + ch <- prometheus.MustNewConstMetric( + desc, + prometheus.GaugeValue, + 1, + org.Name, + org.Spec.BillingEntityRef, + ) + } +} diff --git a/controllers/org_billing_ref_link_metric_test.go b/controllers/org_billing_ref_link_metric_test.go new file mode 100644 index 00000000..8be10b3c --- /dev/null +++ b/controllers/org_billing_ref_link_metric_test.go @@ -0,0 +1,41 @@ +package controllers_test + +import ( + "strings" + "testing" + + "github.com/prometheus/client_golang/prometheus/testutil" + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + orgv1 "github.com/appuio/control-api/apis/organization/v1" + "github.com/appuio/control-api/controllers" +) + +func TestOrgBillingRefLinkMetric(t *testing.T) { + c := prepareTest(t, &orgv1.Organization{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-org", + }, + Spec: orgv1.OrganizationSpec{ + BillingEntityRef: "test-billing-entity", + }, + }, &orgv1.Organization{ + ObjectMeta: metav1.ObjectMeta{ + Name: "blub-org", + }, + Spec: orgv1.OrganizationSpec{ + BillingEntityRef: "be-1734", + }, + }) + + require.NoError(t, + testutil.CollectAndCompare(&controllers.OrgBillingRefLinkMetric{c}, strings.NewReader(` +# HELP control_api_organization_billing_entity_ref Link between an organization and a billing entity +# TYPE control_api_organization_billing_entity_ref gauge +control_api_organization_billing_entity_ref{billing_entity="be-1734",organization="blub-org"} 1 +control_api_organization_billing_entity_ref{billing_entity="test-billing-entity",organization="test-org"} 1 +`), + "control_api_organization_billing_entity_ref"), + ) +}