Skip to content

Commit a07e3cc

Browse files
authored
Introduce Experimental Metrics (#2435)
This commit introduces a series of metrics that are only recorded when OLM is built with the experimental_metrics build tag. The metrics introduced in this commit includes namespace/name information of the request being reconciled by a series of controllers. These experimental metrics are enabled by default in the e2e-local target defined in the project's Makefile. Signed-off-by: Alexander Greene <[email protected]>
1 parent e50fa36 commit a07e3cc

7 files changed

+95
-1
lines changed

Makefile

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ SHELL := /bin/bash
1212
ORG := github.com/operator-framework
1313
PKG := $(ORG)/operator-lifecycle-manager
1414
MOD_FLAGS := $(shell (go version | grep -q -E "1\.1[1-9]") && echo -mod=vendor)
15+
BUILD_TAGS := "json1"
1516
CMDS := $(shell go list $(MOD_FLAGS) ./cmd/...)
1617
TCMDS := $(shell go list $(MOD_FLAGS) ./test/e2e/...)
1718
MOCKGEN := ./scripts/update_mockgen.sh
@@ -101,7 +102,7 @@ bin/cpb: FORCE
101102

102103
$(CMDS): version_flags=-ldflags "-X $(PKG)/pkg/version.GitCommit=$(GIT_COMMIT) -X $(PKG)/pkg/version.OLMVersion=`cat OLM_VERSION`"
103104
$(CMDS):
104-
$(arch_flags) go $(build_cmd) $(MOD_FLAGS) $(version_flags) -tags "json1" -o bin/$(shell basename $@) $@
105+
$(arch_flags) go $(build_cmd) $(MOD_FLAGS) $(version_flags) -tags $(BUILD_TAGS) -o bin/$(shell basename $@) $@
105106

106107
build: clean $(CMDS)
107108

@@ -143,6 +144,7 @@ e2e:
143144

144145
# See workflows/e2e-tests.yml See test/e2e/README.md for details.
145146
.PHONY: e2e-local
147+
e2e-local: BUILD_TAGS="json1 experimental_metrics"
146148
e2e-local: extra_args=-kind.images=../test/e2e-local.image.tar
147149
e2e-local: run=bin/e2e-local.test
148150
e2e-local: bin/e2e-local.test test/e2e-local.image.tar

pkg/controller/operators/adoption_controller.go

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
operatorsv2 "github.com/operator-framework/api/pkg/operators/v2"
3131
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/decorators"
3232
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil"
33+
"github.com/operator-framework/operator-lifecycle-manager/pkg/metrics"
3334
)
3435

3536
// AdoptionReconciler automagically associates Operator components with their respective operator resource.
@@ -113,6 +114,7 @@ func (r *AdoptionReconciler) ReconcileSubscription(ctx context.Context, req ctrl
113114
// Set up a convenient log object so we don't have to type request over and over again
114115
log := r.log.WithValues("request", req)
115116
log.V(1).Info("reconciling subscription")
117+
metrics.EmitAdoptionSubscriptionReconcile(req.Namespace, req.Name)
116118

117119
// Fetch the Subscription from the cache
118120
in := &operatorsv1alpha1.Subscription{}
@@ -175,6 +177,7 @@ func (r *AdoptionReconciler) ReconcileClusterServiceVersion(ctx context.Context,
175177
// Set up a convenient log object so we don't have to type request over and over again
176178
log := r.log.WithValues("request", req)
177179
log.V(1).Info("reconciling csv")
180+
metrics.EmitAdoptionCSVReconcile(req.Namespace, req.Name)
178181

179182
// Fetch the CSV from the cache
180183
in := &operatorsv1alpha1.ClusterServiceVersion{}

pkg/controller/operators/operator_controller.go

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
2929
operatorsv2 "github.com/operator-framework/api/pkg/operators/v2"
3030
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/decorators"
31+
"github.com/operator-framework/operator-lifecycle-manager/pkg/metrics"
3132
)
3233

3334
var (
@@ -118,6 +119,7 @@ func (r *OperatorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
118119
// Set up a convenient log object so we don't have to type request over and over again
119120
log := r.log.WithValues("request", req)
120121
log.V(1).Info("reconciling operator")
122+
metrics.EmitOperatorReconcile(req.Namespace, req.Name)
121123

122124
// Get the Operator
123125
create := false

pkg/controller/operators/operatorcondition_controller.go

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
2323
operatorsv2 "github.com/operator-framework/api/pkg/operators/v2"
2424
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil"
25+
"github.com/operator-framework/operator-lifecycle-manager/pkg/metrics"
2526
)
2627

2728
const (
@@ -94,6 +95,7 @@ func (r *OperatorConditionReconciler) Reconcile(ctx context.Context, req ctrl.Re
9495
// Set up a convenient log object so we don't have to type request over and over again
9596
log := r.log.WithValues("request", req)
9697
log.V(2).Info("reconciling operatorcondition")
98+
metrics.EmitOperatorConditionReconcile(req.Namespace, req.Name)
9799

98100
operatorCondition := &operatorsv2.OperatorCondition{}
99101
err := r.Client.Get(context.TODO(), req.NamespacedName, operatorCondition)

pkg/controller/operators/operatorconditiongenerator_controller.go

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
2121
operatorsv2 "github.com/operator-framework/api/pkg/operators/v2"
2222
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil"
23+
"github.com/operator-framework/operator-lifecycle-manager/pkg/metrics"
2324
)
2425

2526
// OperatorConditionGeneratorReconciler reconciles a ClusterServiceVersion object and creates an OperatorCondition.
@@ -90,6 +91,7 @@ var _ reconcile.Reconciler = &OperatorConditionGeneratorReconciler{}
9091
func (r *OperatorConditionGeneratorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
9192
// Set up a convenient log object so we don't have to type request over and over again
9293
log := r.log.WithValues("request", req)
94+
metrics.EmitOperatorConditionGeneratorReconcile(req.Namespace, req.Name)
9395

9496
in := &operatorsv1alpha1.ClusterServiceVersion{}
9597
err := r.Client.Get(context.TODO(), req.NamespacedName, in)
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package metrics
2+
3+
import "github.com/prometheus/client_golang/prometheus"
4+
5+
const (
6+
// Controller names
7+
operatorController = "operator"
8+
adoptionCSVController = "adoption_csv"
9+
adoptionSubscriptionController = "adoption_subscription"
10+
operatorConditionController = "operator_condition"
11+
operatorConditionGeneratorController = "operator_condition_generator"
12+
)
13+
14+
var (
15+
reconcileMetrics = map[string]*prometheus.CounterVec{}
16+
)
17+
18+
func EmitOperatorReconcile(namespace, name string) {
19+
emitReconcile(operatorController, namespace, name)
20+
}
21+
22+
func EmitAdoptionCSVReconcile(namespace, name string) {
23+
emitReconcile(adoptionCSVController, namespace, name)
24+
}
25+
26+
func EmitAdoptionSubscriptionReconcile(namespace, name string) {
27+
emitReconcile(adoptionSubscriptionController, namespace, name)
28+
}
29+
30+
func EmitOperatorConditionReconcile(namespace, name string) {
31+
emitReconcile(operatorConditionController, namespace, name)
32+
}
33+
34+
func EmitOperatorConditionGeneratorReconcile(namespace, name string) {
35+
emitReconcile(operatorConditionGeneratorController, namespace, name)
36+
}
37+
38+
func emitReconcile(controllerName, namespace, name string) {
39+
if counter, ok := reconcileMetrics[controllerName]; ok {
40+
counter.WithLabelValues(namespace, name).Inc()
41+
}
42+
}

pkg/metrics/experimental_register.go

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//go:build experimental_metrics
2+
// +build experimental_metrics
3+
4+
package metrics
5+
6+
import (
7+
"fmt"
8+
"strings"
9+
10+
"github.com/prometheus/client_golang/prometheus"
11+
)
12+
13+
func init() {
14+
// Register experimental metrics
15+
reconcileMetrics = reconcileCounters(operatorController, adoptionCSVController, adoptionSubscriptionController, operatorConditionController, operatorConditionGeneratorController)
16+
registerReconcileMetrics()
17+
}
18+
19+
func reconcileCounters(reconcilerNames ...string) map[string]*prometheus.CounterVec {
20+
result := map[string]*prometheus.CounterVec{}
21+
for _, s := range reconcilerNames {
22+
result[s] = createReconcileCounterVec(s)
23+
}
24+
return result
25+
}
26+
27+
func createReconcileCounterVec(name string) *prometheus.CounterVec {
28+
return prometheus.NewCounterVec(
29+
prometheus.CounterOpts{
30+
Name: "controller_reconcile_" + name,
31+
Help: fmt.Sprintf("Count of reconcile events by the %s controller", strings.Replace(name, "_", " ", -1)),
32+
},
33+
[]string{NamespaceLabel, NameLabel},
34+
)
35+
}
36+
37+
func registerReconcileMetrics() {
38+
for _, v := range reconcileMetrics {
39+
prometheus.MustRegister(v)
40+
}
41+
}

0 commit comments

Comments
 (0)