github.com/argoproj/argo-cd/v3@v3.2.1/applicationset/metrics/metrics.go (about)

     1  package metrics
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/prometheus/client_golang/prometheus"
     7  	"k8s.io/apimachinery/pkg/labels"
     8  	"sigs.k8s.io/controller-runtime/pkg/metrics"
     9  
    10  	argoappv1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
    11  	applisters "github.com/argoproj/argo-cd/v3/pkg/client/listers/application/v1alpha1"
    12  	metricsutil "github.com/argoproj/argo-cd/v3/util/metrics"
    13  	"github.com/argoproj/argo-cd/v3/util/metrics/kubectl"
    14  )
    15  
    16  var (
    17  	descAppsetLabels        *prometheus.Desc
    18  	descAppsetDefaultLabels = []string{"namespace", "name"}
    19  	descAppsetInfo          = prometheus.NewDesc(
    20  		"argocd_appset_info",
    21  		"Information about applicationset",
    22  		append(descAppsetDefaultLabels, "resource_update_status"),
    23  		nil,
    24  	)
    25  
    26  	descAppsetGeneratedApps = prometheus.NewDesc(
    27  		"argocd_appset_owned_applications",
    28  		"Number of applications owned by the applicationset",
    29  		descAppsetDefaultLabels,
    30  		nil,
    31  	)
    32  )
    33  
    34  type ApplicationsetMetrics struct {
    35  	reconcileHistogram *prometheus.HistogramVec
    36  }
    37  
    38  type appsetCollector struct {
    39  	lister applisters.ApplicationSetLister
    40  	// appsClientSet appclientset.Interface
    41  	labels []string
    42  	filter func(appset *argoappv1.ApplicationSet) bool
    43  }
    44  
    45  func NewApplicationsetMetrics(appsetLister applisters.ApplicationSetLister, appsetLabels []string, appsetFilter func(appset *argoappv1.ApplicationSet) bool) ApplicationsetMetrics {
    46  	reconcileHistogram := prometheus.NewHistogramVec(
    47  		prometheus.HistogramOpts{
    48  			Name: "argocd_appset_reconcile",
    49  			Help: "Application reconciliation performance in seconds.",
    50  			// Buckets can be set later on after observing median time
    51  		},
    52  		descAppsetDefaultLabels,
    53  	)
    54  
    55  	appsetCollector := newAppsetCollector(appsetLister, appsetLabels, appsetFilter)
    56  
    57  	// Register collectors and metrics
    58  	metrics.Registry.MustRegister(reconcileHistogram)
    59  	metrics.Registry.MustRegister(appsetCollector)
    60  
    61  	kubectl.RegisterWithClientGo()
    62  	kubectl.RegisterWithPrometheus(metrics.Registry)
    63  
    64  	return ApplicationsetMetrics{
    65  		reconcileHistogram: reconcileHistogram,
    66  	}
    67  }
    68  
    69  func (m *ApplicationsetMetrics) ObserveReconcile(appset *argoappv1.ApplicationSet, duration time.Duration) {
    70  	m.reconcileHistogram.WithLabelValues(appset.Namespace, appset.Name).Observe(duration.Seconds())
    71  }
    72  
    73  func newAppsetCollector(lister applisters.ApplicationSetLister, labels []string, filter func(appset *argoappv1.ApplicationSet) bool) *appsetCollector {
    74  	descAppsetDefaultLabels = []string{"namespace", "name"}
    75  
    76  	if len(labels) > 0 {
    77  		descAppsetLabels = prometheus.NewDesc(
    78  			"argocd_appset_labels",
    79  			"Applicationset labels translated to Prometheus labels",
    80  			append(descAppsetDefaultLabels, metricsutil.NormalizeLabels("label", labels)...),
    81  			nil,
    82  		)
    83  	}
    84  
    85  	return &appsetCollector{
    86  		lister: lister,
    87  		labels: labels,
    88  		filter: filter,
    89  	}
    90  }
    91  
    92  // Describe implements the prometheus.Collector interface
    93  func (c *appsetCollector) Describe(ch chan<- *prometheus.Desc) {
    94  	ch <- descAppsetInfo
    95  	ch <- descAppsetGeneratedApps
    96  
    97  	if len(c.labels) > 0 {
    98  		ch <- descAppsetLabels
    99  	}
   100  }
   101  
   102  // Collect implements the prometheus.Collector interface
   103  func (c *appsetCollector) Collect(ch chan<- prometheus.Metric) {
   104  	appsets, _ := c.lister.List(labels.NewSelector())
   105  
   106  	for _, appset := range appsets {
   107  		if c.filter(appset) {
   108  			collectAppset(appset, c.labels, ch)
   109  		}
   110  	}
   111  }
   112  
   113  func collectAppset(appset *argoappv1.ApplicationSet, labelsToCollect []string, ch chan<- prometheus.Metric) {
   114  	labelValues := make([]string, 0)
   115  	commonLabelValues := []string{appset.Namespace, appset.Name}
   116  
   117  	for _, label := range labelsToCollect {
   118  		labelValues = append(labelValues, appset.GetLabels()[label])
   119  	}
   120  
   121  	resourceUpdateStatus := "Unknown"
   122  
   123  	for _, condition := range appset.Status.Conditions {
   124  		if condition.Type == argoappv1.ApplicationSetConditionResourcesUpToDate {
   125  			resourceUpdateStatus = condition.Reason
   126  		}
   127  	}
   128  
   129  	if len(labelsToCollect) > 0 {
   130  		ch <- prometheus.MustNewConstMetric(descAppsetLabels, prometheus.GaugeValue, 1, append(commonLabelValues, labelValues...)...)
   131  	}
   132  
   133  	ch <- prometheus.MustNewConstMetric(descAppsetInfo, prometheus.GaugeValue, 1, appset.Namespace, appset.Name, resourceUpdateStatus)
   134  	ch <- prometheus.MustNewConstMetric(descAppsetGeneratedApps, prometheus.GaugeValue, float64(len(appset.Status.Resources)), appset.Namespace, appset.Name)
   135  }