Skip to content

Commit

Permalink
feat: Add Manifest Reconcile Duration Metric (#1321)
Browse files Browse the repository at this point in the history
* feat: Add Manifest Reconcile Duration Metric

* fix: lint

* fix: remove unnecessary call

* test: Add Metric Check to E2E Metrics Test

* fix: Lint Issue

* fix: Metric Check in E2E Metrics Test

* chore: Update Buckets for Metrics

* fix:Lint Issue

* fix: FDescribe
  • Loading branch information
LeelaChacha authored Mar 4, 2024
1 parent 386e15e commit 2b64c7b
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 10 deletions.
4 changes: 4 additions & 0 deletions internal/declarative/v2/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"time"

apicorev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
Expand Down Expand Up @@ -92,6 +93,9 @@ func newResourcesCondition(obj Object) apimetav1.Condition {

//nolint:funlen,cyclop,gocognit // Declarative pkg will be removed soon
func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
reconcileStart := time.Now()
defer r.Metrics.ObserveReconcileDuration(reconcileStart, req.NamespacedName.Name)

obj, ok := r.prototype.DeepCopyObject().(Object)
if !ok {
r.Metrics.RecordRequeueReason(metrics.ManifestTypeCast, queue.UnexpectedRequeue)
Expand Down
36 changes: 34 additions & 2 deletions internal/pkg/metrics/manifest.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
package metrics

import "github.com/kyma-project/lifecycle-manager/pkg/queue"
import (
"time"

"github.com/prometheus/client_golang/prometheus"
ctrlmetrics "sigs.k8s.io/controller-runtime/pkg/metrics"

"github.com/kyma-project/lifecycle-manager/pkg/queue"
)

type ManifestRequeueReason string

const (
MetricReconcileDuration string = "reconcile_duration_seconds"
MetricLabelModule string = "module_name"
ManifestTypeCast ManifestRequeueReason = "manifest_type_cast"
ManifestRetrieval ManifestRequeueReason = "manifest_retrieval"
ManifestInit ManifestRequeueReason = "manifest_initialize"
Expand All @@ -28,12 +37,35 @@ const (

type ManifestMetrics struct {
*SharedMetrics
reconcileDurationHistogram *prometheus.HistogramVec
}

func NewManifestMetrics(sharedMetrics *SharedMetrics) *ManifestMetrics {
return &ManifestMetrics{SharedMetrics: sharedMetrics}
metrics := &ManifestMetrics{
SharedMetrics: sharedMetrics,
reconcileDurationHistogram: prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: MetricReconcileDuration,
Help: "Histogram of reconcile duration for manifest reconciliation in seconds",
Buckets: []float64{
0.005, 0.01, 0.025, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.6,
0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5, 6, 7, 8, 9, 10, 15, 20,
25, 30, 40, 50, 60,
},
},
[]string{MetricLabelModule},
),
}
ctrlmetrics.Registry.MustRegister(metrics.reconcileDurationHistogram)
return metrics
}

func (k *ManifestMetrics) RecordRequeueReason(requeueReason ManifestRequeueReason, requeueType queue.RequeueType) {
k.requeueReasonCounter.WithLabelValues(string(requeueReason), string(requeueType)).Inc()
}

func (k *ManifestMetrics) ObserveReconcileDuration(reconcileStart time.Time, moduleName string) {
durationInSeconds := time.Since(reconcileStart).Seconds()
k.reconcileDurationHistogram.WithLabelValues(moduleName).
Observe(durationInSeconds)
}
28 changes: 20 additions & 8 deletions pkg/testutils/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"github.com/kyma-project/lifecycle-manager/internal/pkg/metrics"
)

const reMatchCount = `"} (\d+)`

var ErrMetricNotFound = errors.New("metric was not found")

func GetKymaStateMetricCount(ctx context.Context, kymaName, state string) (int, error) {
Expand All @@ -27,8 +29,7 @@ func GetKymaStateMetricCount(ctx context.Context, kymaName, state string) (int,
func getKymaStateMetricRegex(kymaName, state string) *regexp.Regexp {
return regexp.MustCompile(
metrics.MetricKymaState + `{instance_id="[^"]+",kyma_name="` + kymaName +
`",shoot="[^"]+",state="` + state +
`"} (\d+)`)
`",shoot="[^"]+",state="` + state + reMatchCount)
}

func AssertKymaStateMetricNotFound(ctx context.Context, kymaName, state string) error {
Expand All @@ -55,8 +56,7 @@ func GetRequeueReasonCount(ctx context.Context,
}
re := regexp.MustCompile(
metrics.MetricRequeueReason + `{requeue_reason="` + requeueReason +
`",requeue_type="` + requeueType +
`"}` + ` (\d+)`)
`",requeue_type="` + requeueType + reMatchCount)
return parseCount(re, bodyString)
}

Expand All @@ -69,12 +69,25 @@ func IsManifestRequeueReasonCountIncreased(ctx context.Context, requeueReason, r
}
re := regexp.MustCompile(
metrics.MetricRequeueReason + `{requeue_reason="` + requeueReason +
`",requeue_type="` + requeueType +
`"}` + ` (\d+)`)
`",requeue_type="` + requeueType + reMatchCount)
count, err := parseCount(re, bodyString)
return count >= 1, err
}

func IsManifestReconcileDurationCountNonZero(ctx context.Context, manifestName string) (bool,
error,
) {
bodyString, err := getMetricsBody(ctx)
if err != nil {
return false, err
}
re := regexp.MustCompile(
metrics.MetricReconcileDuration + `_count{` + metrics.MetricLabelModule +
`="` + manifestName + reMatchCount)
count, err := parseCount(re, bodyString)
return count > 0, err
}

func GetModuleStateMetricCount(ctx context.Context, kymaName, moduleName, state string) (int, error) {
bodyString, err := getMetricsBody(ctx)
if err != nil {
Expand All @@ -83,8 +96,7 @@ func GetModuleStateMetricCount(ctx context.Context, kymaName, moduleName, state
re := regexp.MustCompile(
metrics.MetricModuleState + `{instance_id="[^"]+",kyma_name="` + kymaName +
`",module_name="` + moduleName +
`",shoot="[^"]+",state="` + state +
`"} (\d+)`)
`",shoot="[^"]+",state="` + state + reMatchCount)
return parseCount(re, bodyString)
}

Expand Down
10 changes: 10 additions & 0 deletions tests/e2e/kyma_metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@ var _ = Describe("Manage Module Metrics", Ordered, func() {
Should(BeTrue())
})

It("Then Related Manifest Duration Metric Is Non Zero", func() {
manifest, err := GetManifest(ctx, controlPlaneClient, kyma.GetName(), kyma.GetNamespace(), module.Name)
Expect(err).ToNot(HaveOccurred())

Eventually(IsManifestReconcileDurationCountNonZero).
WithContext(ctx).
WithArguments(manifest.Name).
Should(BeTrue())
})

It("When Kyma Module is disabled", func() {
Eventually(DisableModule).
WithContext(ctx).
Expand Down

0 comments on commit 2b64c7b

Please sign in to comment.