From 53672a4240c48c197d2a5608a9f60f0ded39730c Mon Sep 17 00:00:00 2001 From: davis-haba Date: Tue, 20 Sep 2022 11:31:38 -0700 Subject: [PATCH 1/2] Add metric reporting to ExpansionTemplate controller Signed-off-by: davis-haba --- .../expansion/expansion_controller.go | 23 +++++- pkg/controller/expansion/stats_reporter.go | 70 +++++++++++++++++++ 2 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 pkg/controller/expansion/stats_reporter.go diff --git a/pkg/controller/expansion/expansion_controller.go b/pkg/controller/expansion/expansion_controller.go index 5f0858e62f6..6a1d0cf6aa0 100644 --- a/pkg/controller/expansion/expansion_controller.go +++ b/pkg/controller/expansion/expansion_controller.go @@ -15,6 +15,7 @@ import ( "github.com/open-policy-agent/gatekeeper/pkg/watch" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/handler" @@ -61,12 +62,18 @@ func (a *Adder) InjectProviderCache(_ *externaldata.ProviderCache) {} type Reconciler struct { client.Client - system *expansion.System - scheme *runtime.Scheme + system *expansion.System + scheme *runtime.Scheme + registry *etRegistry } func newReconciler(mgr manager.Manager, system *expansion.System) *Reconciler { - return &Reconciler{Client: mgr.GetClient(), system: system, scheme: mgr.GetScheme()} + return &Reconciler{ + Client: mgr.GetClient(), + system: system, + scheme: mgr.GetScheme(), + registry: newRegistry(), + } } func add(mgr manager.Manager, r reconcile.Reconciler) error { @@ -97,6 +104,10 @@ func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) ( if err := r.scheme.Convert(te, unversionedTE, nil); err != nil { return reconcile.Result{}, err } + nsName := types.NamespacedName{ + Namespace: unversionedTE.GetNamespace(), + Name: unversionedTE.GetName(), + } if deleted { // unversionedTE will be an empty struct. We set the metadata name, which is // used as a key to delete it from the expansion system @@ -105,11 +116,17 @@ func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) ( return reconcile.Result{}, err } log.Info("removed template expansion", "template name", unversionedTE.ObjectMeta.Name) + r.registry.remove(nsName) } else { if err := r.system.UpsertTemplate(unversionedTE); err != nil { return reconcile.Result{}, err } log.Info("upserted template expansion", "template name", unversionedTE.ObjectMeta.Name) + r.registry.add(nsName) + } + + if err := r.registry.report(ctx); err != nil { + log.Error(err, "error reporting template expansion metrics", "namespacedName", nsName) } return reconcile.Result{}, nil diff --git a/pkg/controller/expansion/stats_reporter.go b/pkg/controller/expansion/stats_reporter.go new file mode 100644 index 00000000000..91bf1c45076 --- /dev/null +++ b/pkg/controller/expansion/stats_reporter.go @@ -0,0 +1,70 @@ +package expansion + +import ( + "context" + + "github.com/open-policy-agent/gatekeeper/pkg/metrics" + "go.opencensus.io/stats" + "go.opencensus.io/stats/view" + "k8s.io/apimachinery/pkg/types" +) + +const ( + etMetricName = "expansion_templates" + etDesc = "Number of observed expansion templates" +) + +var ( + etM = stats.Int64(etMetricName, etDesc, stats.UnitDimensionless) + + views = []*view.View{ + { + Name: etMetricName, + Measure: etM, + Description: etDesc, + Aggregation: view.LastValue(), + }, + } +) + +func init() { + if err := register(); err != nil { + panic(err) + } +} + +func register() error { + return view.Register(views...) +} + +func newRegistry() *etRegistry { + return &etRegistry{cache: make(map[types.NamespacedName]bool)} +} + +type etRegistry struct { + cache map[types.NamespacedName]bool + dirty bool +} + +func (r *etRegistry) add(key types.NamespacedName) { + r.cache[key] = true + r.dirty = true +} + +func (r *etRegistry) remove(key types.NamespacedName) { + delete(r.cache, key) + r.dirty = true +} + +func (r *etRegistry) report(ctx context.Context) error { + if !r.dirty { + return nil + } + + if err := metrics.Record(ctx, etM.M(int64(len(r.cache)))); err != nil { + r.dirty = false + return err + } + + return nil +} From b199495d87022e9fed3e5cd1865cc29316febed9 Mon Sep 17 00:00:00 2001 From: davis-haba Date: Tue, 27 Sep 2022 13:33:16 -0700 Subject: [PATCH 2/2] Update metrics docs with gatekeeper_expansion_templates metric Signed-off-by: davis-haba --- website/docs/metrics.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/website/docs/metrics.md b/website/docs/metrics.md index 7ac08a3646d..720241fa60d 100644 --- a/website/docs/metrics.md +++ b/website/docs/metrics.md @@ -51,6 +51,14 @@ Below are the list of metrics provided by Gatekeeper: Aggregation: `Distribution` +## Expansion Template + +- Name: `gatekeeper_expansion_templates` + + Description: `Number of observed expansion templates` + + Aggregation: `LastValue` + ## Webhook - Name: `gatekeeper_validation_request_count`