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 }