github.com/kyma-project/kyma-environment-broker@v0.0.1/internal/metrics/operations_collector.go (about)

     1  package metrics
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/kyma-project/kyma-environment-broker/internal"
     7  	"github.com/kyma-project/kyma-environment-broker/internal/broker"
     8  	"github.com/pivotal-cf/brokerapi/v8/domain"
     9  	"github.com/prometheus/client_golang/prometheus"
    10  	"github.com/sirupsen/logrus"
    11  )
    12  
    13  // OperationsStatsGetter provides metrics, which shows how many operations were done for the following plans:
    14  
    15  // - compass_keb_operations_{plan_name}_provisioning_failed_total
    16  // - compass_keb_operations_{plan_name}_provisioning_in_progress_total
    17  // - compass_keb_operations_{plan_name}_provisioning_succeeded_total
    18  // - compass_keb_operations_{plan_name}_deprovisioning_failed_total
    19  // - compass_keb_operations_{plan_name}_deprovisioning_in_progress_total
    20  // - compass_keb_operations_{plan_name}_deprovisioning_succeeded_total
    21  
    22  var (
    23  	supportedPlansIDs = []string{
    24  		broker.AzurePlanID,
    25  		broker.AzureLitePlanID,
    26  		broker.AWSPlanID,
    27  		broker.GCPPlanID,
    28  		broker.OpenStackPlanID,
    29  		broker.TrialPlanID,
    30  		broker.FreemiumPlanID,
    31  		broker.PreviewPlanName,
    32  	}
    33  )
    34  
    35  type OperationsStatsGetter interface {
    36  	GetOperationStatsByPlan() (map[string]internal.OperationStats, error)
    37  }
    38  
    39  type OperationStat struct {
    40  	failedProvisioning   *prometheus.Desc
    41  	failedDeprovisioning *prometheus.Desc
    42  
    43  	succeededProvisioning   *prometheus.Desc
    44  	succeededDeprovisioning *prometheus.Desc
    45  
    46  	inProgressProvisioning   *prometheus.Desc
    47  	inProgressDeprovisioning *prometheus.Desc
    48  }
    49  
    50  func (c *OperationStat) Describe(ch chan<- *prometheus.Desc) {
    51  	ch <- c.inProgressProvisioning
    52  	ch <- c.succeededProvisioning
    53  	ch <- c.failedProvisioning
    54  
    55  	ch <- c.inProgressDeprovisioning
    56  	ch <- c.succeededDeprovisioning
    57  	ch <- c.failedDeprovisioning
    58  }
    59  
    60  type OperationsCollector struct {
    61  	statsGetter OperationsStatsGetter
    62  
    63  	operationStats map[string]OperationStat
    64  }
    65  
    66  func NewOperationsCollector(statsGetter OperationsStatsGetter) *OperationsCollector {
    67  	opStats := make(map[string]OperationStat, len(supportedPlansIDs))
    68  
    69  	for _, p := range supportedPlansIDs {
    70  		opStats[p] = OperationStat{
    71  			inProgressProvisioning: prometheus.NewDesc(
    72  				fqName(internal.OperationTypeProvision, domain.InProgress),
    73  				"The number of provisioning operations in progress",
    74  				[]string{"plan_id"},
    75  				nil),
    76  			succeededProvisioning: prometheus.NewDesc(
    77  				fqName(internal.OperationTypeProvision, domain.Succeeded),
    78  				"The number of succeeded provisioning operations",
    79  				[]string{"plan_id"},
    80  				nil),
    81  			failedProvisioning: prometheus.NewDesc(
    82  				fqName(internal.OperationTypeProvision, domain.Failed),
    83  				"The number of failed provisioning operations",
    84  				[]string{"plan_id"},
    85  				nil),
    86  			inProgressDeprovisioning: prometheus.NewDesc(
    87  				fqName(internal.OperationTypeDeprovision, domain.InProgress),
    88  				"The number of deprovisioning operations in progress",
    89  				[]string{"plan_id"},
    90  				nil),
    91  			succeededDeprovisioning: prometheus.NewDesc(
    92  				fqName(internal.OperationTypeDeprovision, domain.Succeeded),
    93  				"The number of succeeded deprovisioning operations",
    94  				[]string{"plan_id"},
    95  				nil),
    96  			failedDeprovisioning: prometheus.NewDesc(
    97  				fqName(internal.OperationTypeDeprovision, domain.Failed),
    98  				"The number of failed deprovisioning operations",
    99  				[]string{"plan_id"},
   100  				nil),
   101  		}
   102  	}
   103  
   104  	return &OperationsCollector{
   105  		statsGetter:    statsGetter,
   106  		operationStats: opStats,
   107  	}
   108  }
   109  
   110  func fqName(operationType internal.OperationType, state domain.LastOperationState) string {
   111  	var opType string
   112  	switch operationType {
   113  	case internal.OperationTypeProvision:
   114  		opType = "provisioning"
   115  	case internal.OperationTypeDeprovision:
   116  		opType = "deprovisioning"
   117  	}
   118  
   119  	var st string
   120  	switch state {
   121  	case domain.Failed:
   122  		st = "failed"
   123  	case domain.Succeeded:
   124  		st = "succeeded"
   125  	case domain.InProgress:
   126  		st = "in_progress"
   127  	}
   128  	name := fmt.Sprintf("operations_%s_%s_total", opType, st)
   129  	return prometheus.BuildFQName(prometheusNamespace, prometheusSubsystem, name)
   130  }
   131  
   132  func (c *OperationsCollector) Describe(ch chan<- *prometheus.Desc) {
   133  	for _, op := range c.operationStats {
   134  		op.Describe(ch)
   135  	}
   136  }
   137  
   138  // Collect implements the prometheus.Collector interface.
   139  func (c *OperationsCollector) Collect(ch chan<- prometheus.Metric) {
   140  	stats, err := c.statsGetter.GetOperationStatsByPlan()
   141  	if err != nil {
   142  		return
   143  	}
   144  
   145  	for planID, ops := range c.operationStats {
   146  		collect(ch,
   147  			ops.inProgressProvisioning,
   148  			stats[planID].Provisioning[domain.InProgress],
   149  			planID,
   150  		)
   151  		collect(ch,
   152  			ops.succeededProvisioning,
   153  			stats[planID].Provisioning[domain.Succeeded],
   154  			planID,
   155  		)
   156  		collect(ch,
   157  			ops.failedProvisioning,
   158  			stats[planID].Provisioning[domain.Failed],
   159  			planID,
   160  		)
   161  		collect(ch,
   162  			ops.inProgressDeprovisioning,
   163  			stats[planID].Deprovisioning[domain.InProgress],
   164  			planID,
   165  		)
   166  		collect(ch,
   167  			ops.succeededDeprovisioning,
   168  			stats[planID].Deprovisioning[domain.Succeeded],
   169  			planID,
   170  		)
   171  		collect(ch,
   172  			ops.failedDeprovisioning,
   173  			stats[planID].Deprovisioning[domain.Failed],
   174  			planID,
   175  		)
   176  	}
   177  
   178  }
   179  
   180  func collect(ch chan<- prometheus.Metric, desc *prometheus.Desc, value int, labelValues ...string) {
   181  	m, err := prometheus.NewConstMetric(
   182  		desc,
   183  		prometheus.GaugeValue,
   184  		float64(value),
   185  		labelValues...)
   186  
   187  	if err != nil {
   188  		logrus.Errorf("unable to register metric %s", err.Error())
   189  		return
   190  	}
   191  	ch <- m
   192  }