You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pc...@apache.org on 2024/03/19 15:52:23 UTC

(camel-k) branch main updated: [chore] improve metrics for integration (#5154)

This is an automated email from the ASF dual-hosted git repository.

pcongiusti pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git


The following commit(s) were added to refs/heads/main by this push:
     new 39ab1bc19 [chore] improve metrics for integration (#5154)
39ab1bc19 is described below

commit 39ab1bc19d8638ec593a762430c0461dd70ed8c4
Author: LuLo <fl...@icloud.com>
AuthorDate: Tue Mar 19 16:52:17 2024 +0100

    [chore] improve metrics for integration (#5154)
    
    * [chore] improve metrics for integration
    
    improve metrics for integrations, record a vector with integration_name and state
    
    * [chore] add tests
    
    * chore: change test dependency
    
    * solve go.mod conflict
    
    * chore: change test library and fix lint
---
 .../integration/integration_controller.go          |  2 +
 pkg/controller/integration/metrics.go              | 49 +++++++++----
 pkg/controller/integration/metrics_test.go         | 82 ++++++++++++++++++++++
 3 files changed, 121 insertions(+), 12 deletions(-)

diff --git a/pkg/controller/integration/integration_controller.go b/pkg/controller/integration/integration_controller.go
index d2b848752..a73179246 100644
--- a/pkg/controller/integration/integration_controller.go
+++ b/pkg/controller/integration/integration_controller.go
@@ -20,6 +20,7 @@ package integration
 import (
 	"context"
 	"fmt"
+
 	"reflect"
 	"time"
 
@@ -95,6 +96,7 @@ func integrationUpdateFunc(old *v1.Integration, it *v1.Integration) bool {
 		timeToFirstReadiness.Observe(duration.Seconds())
 	}
 
+	updateIntegrationPhase(it.Name, string(it.Status.Phase))
 	// If traits have changed, the reconciliation loop must kick in as
 	// traits may have impact
 	sameTraits, err := trait.IntegrationsHaveSameTraits(old, it)
diff --git a/pkg/controller/integration/metrics.go b/pkg/controller/integration/metrics.go
index 46eb3f2ce..f235a0bc2 100644
--- a/pkg/controller/integration/metrics.go
+++ b/pkg/controller/integration/metrics.go
@@ -18,6 +18,7 @@ limitations under the License.
 package integration
 
 import (
+	"strings"
 	"time"
 
 	"sigs.k8s.io/controller-runtime/pkg/metrics"
@@ -25,21 +26,45 @@ import (
 	"github.com/prometheus/client_golang/prometheus"
 )
 
-var timeToFirstReadiness = prometheus.NewHistogram(
-	prometheus.HistogramOpts{
-		Name: "camel_k_integration_first_readiness_seconds",
-		Help: "Camel K integration time to first readiness",
-		Buckets: []float64{
-			5 * time.Second.Seconds(),
-			10 * time.Second.Seconds(),
-			30 * time.Second.Seconds(),
-			1 * time.Minute.Seconds(),
-			2 * time.Minute.Seconds(),
+var (
+	timeToFirstReadiness = prometheus.NewHistogram(
+		prometheus.HistogramOpts{
+			Name: "camel_k_integration_first_readiness_seconds",
+			Help: "Camel K integration time to first readiness",
+			Buckets: []float64{
+				5 * time.Second.Seconds(),
+				10 * time.Second.Seconds(),
+				30 * time.Second.Seconds(),
+				1 * time.Minute.Seconds(),
+				2 * time.Minute.Seconds(),
+			},
 		},
-	},
+	)
+
+	integration = prometheus.NewCounterVec(
+		prometheus.CounterOpts{
+			Name: "camel_k_integration_phase_total",
+			Help: "Number of integration processed",
+		}, []string{
+			"phase",
+			"id",
+		},
+	)
 )
 
 func init() {
 	// Register custom metrics with the global prometheus registry
-	metrics.Registry.MustRegister(timeToFirstReadiness)
+	metrics.Registry.MustRegister(timeToFirstReadiness, integration)
+}
+
+func updateIntegrationPhase(iID string, p string) {
+	phase := strings.ReplaceAll(strings.ToLower(p), " ", "_")
+
+	if phase != "" && iID != "" {
+		labels := prometheus.Labels{
+			"id":    iID,
+			"phase": phase,
+		}
+		integration.With(labels).Inc()
+	}
 }
diff --git a/pkg/controller/integration/metrics_test.go b/pkg/controller/integration/metrics_test.go
new file mode 100644
index 000000000..5fce7b832
--- /dev/null
+++ b/pkg/controller/integration/metrics_test.go
@@ -0,0 +1,82 @@
+package integration
+
+import (
+	"github.com/prometheus/client_golang/prometheus"
+	dto "github.com/prometheus/client_model/go"
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+// getMetricValue returns the sum of the Counter metrics associated with the Collector
+// e.g. the metric for a non-vector, or the sum of the metrics for vector labels.
+// If the metric is a Histogram then number of samples is used.
+func getMetricValue(col prometheus.Collector) float64 {
+	var total float64
+	collect(col, func(m *dto.Metric) {
+		if h := m.GetHistogram(); h != nil {
+			total += float64(h.GetSampleCount())
+		} else {
+			total += m.GetCounter().GetValue()
+		}
+	})
+	return total
+}
+
+// collect calls the function for each metric associated with the Collector
+func collect(col prometheus.Collector, do func(*dto.Metric)) {
+	c := make(chan prometheus.Metric)
+	go func(c chan prometheus.Metric) {
+		col.Collect(c)
+		close(c)
+	}(c)
+	for x := range c { // eg range across distinct label vector values
+		m := dto.Metric{}
+		_ = x.Write(&m)
+		do(&m)
+	}
+}
+
+func Test_updateIntegrationPhase(t *testing.T) {
+	type args struct {
+		iId      string
+		p        string
+		expected float64
+	}
+	tests := []struct {
+		name string
+		args args
+	}{
+		{
+			name: "test should fail with empty id", args: args{
+				iId:      "",
+				p:        "running",
+				expected: 0,
+			},
+		},
+		{
+			name: "test should fail with empty phase", args: args{
+				iId:      "int-1",
+				p:        "",
+				expected: 0,
+			},
+		},
+		{
+			name: "test should pass and increase the counter", args: args{
+				iId:      "int-1",
+				p:        "running",
+				expected: 1,
+			},
+		},
+	}
+	for _, tt := range tests {
+		//		integration.Reset()
+		t.Run(tt.name, func(t *testing.T) {
+			updateIntegrationPhase(tt.args.iId, tt.args.p)
+			labels := map[string]string{"phase": tt.args.p, "id": tt.args.iId}
+			if i, err := integration.GetMetricWith(labels); err == nil {
+				val := getMetricValue(i)
+				assert.Equal(t, val, tt.args.expected)
+			}
+		})
+	}
+}