github.com/kyma-project/kyma-environment-broker@v0.0.1/internal/metrics/operation_result.go (about) 1 package metrics 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/kyma-project/kyma-environment-broker/internal" 8 9 "github.com/kyma-project/kyma-environment-broker/internal/process" 10 "github.com/pivotal-cf/brokerapi/v8/domain" 11 "github.com/prometheus/client_golang/prometheus" 12 ) 13 14 const ( 15 prometheusNamespace = "compass" 16 prometheusSubsystem = "keb" 17 18 resultFailed float64 = 0 19 resultSucceeded float64 = 1 20 resultInProgress float64 = 2 21 resultPending float64 = 3 22 resultCanceling float64 = 4 23 resultCanceled float64 = 5 24 resultRetrying float64 = 6 25 resultUnimplemented float64 = 7 26 ) 27 28 type LastOperationState = domain.LastOperationState 29 30 const ( 31 Pending LastOperationState = "pending" 32 Canceling LastOperationState = "canceling" 33 Canceled LastOperationState = "canceled" 34 Retrying LastOperationState = "retrying" 35 ) 36 37 // OperationResultCollector provides the following metrics: 38 // - compass_keb_provisioning_result{"operation_id", "instance_id", "global_account_id", "plan_id"} 39 // - compass_keb_deprovisioning_result{"operation_id", "instance_id", "global_account_id", "plan_id"} 40 // - compass_keb_upgrade_result{"operation_id", "instance_id", "global_account_id", "plan_id"} 41 // These gauges show the status of the operation. 42 // The value of the gauge could be: 43 // 0 - Failed 44 // 1 - Succeeded 45 // 2 - In progress 46 // 3 - Pending 47 // 4 - Canceling 48 // 5 - Canceled 49 type OperationResultCollector struct { 50 provisioningResultGauge *prometheus.GaugeVec 51 deprovisioningResultGauge *prometheus.GaugeVec 52 upgradeKymaResultGauge *prometheus.GaugeVec 53 upgradeClusterResultGauge *prometheus.GaugeVec 54 } 55 56 func NewOperationResultCollector() *OperationResultCollector { 57 return &OperationResultCollector{ 58 provisioningResultGauge: prometheus.NewGaugeVec(prometheus.GaugeOpts{ 59 Namespace: prometheusNamespace, 60 Subsystem: prometheusSubsystem, 61 Name: "provisioning_result", 62 Help: "Result of the provisioning", 63 }, []string{"operation_id", "instance_id", "global_account_id", "plan_id", "error_category", "error_reason"}), 64 deprovisioningResultGauge: prometheus.NewGaugeVec(prometheus.GaugeOpts{ 65 Namespace: prometheusNamespace, 66 Subsystem: prometheusSubsystem, 67 Name: "deprovisioning_result", 68 Help: "Result of the deprovisioning", 69 }, []string{"operation_id", "instance_id", "global_account_id", "plan_id", "error_category", "error_reason"}), 70 upgradeKymaResultGauge: prometheus.NewGaugeVec(prometheus.GaugeOpts{ 71 Namespace: prometheusNamespace, 72 Subsystem: prometheusSubsystem, 73 Name: "upgrade_kyma_result", 74 Help: "Result of the kyma upgrade", 75 }, []string{"operation_id", "instance_id", "global_account_id", "plan_id"}), 76 upgradeClusterResultGauge: prometheus.NewGaugeVec(prometheus.GaugeOpts{ 77 Namespace: prometheusNamespace, 78 Subsystem: prometheusSubsystem, 79 Name: "upgrade_cluster_result", 80 Help: "Result of the cluster upgrade", 81 }, []string{"operation_id", "instance_id", "global_account_id", "plan_id"}), 82 } 83 } 84 85 func (c *OperationResultCollector) Describe(ch chan<- *prometheus.Desc) { 86 c.provisioningResultGauge.Describe(ch) 87 c.deprovisioningResultGauge.Describe(ch) 88 c.upgradeKymaResultGauge.Describe(ch) 89 c.upgradeClusterResultGauge.Describe(ch) 90 } 91 92 func (c *OperationResultCollector) Collect(ch chan<- prometheus.Metric) { 93 c.provisioningResultGauge.Collect(ch) 94 c.deprovisioningResultGauge.Collect(ch) 95 c.upgradeKymaResultGauge.Collect(ch) 96 c.upgradeClusterResultGauge.Collect(ch) 97 } 98 99 func (c *OperationResultCollector) OnUpgradeKymaStepProcessed(ctx context.Context, ev interface{}) error { 100 stepProcessed, ok := ev.(process.UpgradeKymaStepProcessed) 101 if !ok { 102 return fmt.Errorf("expected UpgradeKymaStepProcessed but got %+v", ev) 103 } 104 105 resultValue := c.mapResult(stepProcessed.Operation.State) 106 op := stepProcessed.Operation 107 pp := op.ProvisioningParameters 108 c.upgradeKymaResultGauge. 109 WithLabelValues(op.Operation.ID, op.InstanceID, pp.ErsContext.GlobalAccountID, pp.PlanID). 110 Set(resultValue) 111 112 return nil 113 } 114 115 func (c *OperationResultCollector) OnUpgradeClusterStepProcessed(ctx context.Context, ev interface{}) error { 116 stepProcessed, ok := ev.(process.UpgradeClusterStepProcessed) 117 if !ok { 118 return fmt.Errorf("expected UpgradeClusterStepProcessed but got %+v", ev) 119 } 120 121 resultValue := c.mapResult(stepProcessed.Operation.State) 122 op := stepProcessed.Operation 123 pp := op.ProvisioningParameters 124 c.upgradeClusterResultGauge. 125 WithLabelValues(op.Operation.ID, op.InstanceID, pp.ErsContext.GlobalAccountID, pp.PlanID). 126 Set(resultValue) 127 128 return nil 129 } 130 131 func (c *OperationResultCollector) OnOperationStepProcessed(ctx context.Context, ev interface{}) error { 132 e, ok := ev.(process.OperationStepProcessed) 133 if !ok { 134 return fmt.Errorf("expected OperationStepProcessed but got %+v", ev) 135 } 136 137 switch e.Operation.Type { 138 case internal.OperationTypeProvision: 139 return c.OnProvisioningStepProcessed(ctx, process.ProvisioningStepProcessed{ 140 StepProcessed: e.StepProcessed, 141 Operation: internal.ProvisioningOperation{Operation: e.Operation}, 142 }) 143 case internal.OperationTypeDeprovision: 144 return c.OnDeprovisioningStepProcessed(ctx, process.DeprovisioningStepProcessed{ 145 StepProcessed: e.StepProcessed, 146 Operation: internal.DeprovisioningOperation{Operation: e.Operation}, 147 }) 148 default: 149 return fmt.Errorf("expected OperationStep of types [%s, %s] but got %+v", internal.OperationTypeProvision, internal.OperationTypeDeprovision, e.Operation.Type) 150 } 151 } 152 153 func (c *OperationResultCollector) OnProvisioningSucceeded(ctx context.Context, ev interface{}) error { 154 provisioningSucceeded, ok := ev.(process.ProvisioningSucceeded) 155 if !ok { 156 return fmt.Errorf("expected ProvisioningSucceeded but got %+v", ev) 157 } 158 op := provisioningSucceeded.Operation 159 pp := op.ProvisioningParameters 160 c.provisioningResultGauge.WithLabelValues( 161 op.ID, op.InstanceID, pp.ErsContext.GlobalAccountID, pp.PlanID, "", ""). 162 Set(resultSucceeded) 163 164 return nil 165 } 166 167 func (c *OperationResultCollector) OnProvisioningStepProcessed(ctx context.Context, ev interface{}) error { 168 stepProcessed, ok := ev.(process.ProvisioningStepProcessed) 169 if !ok { 170 return fmt.Errorf("expected ProvisioningStepProcessed but got %+v", ev) 171 } 172 173 resultValue := c.mapResult(stepProcessed.Operation.State) 174 op := stepProcessed.Operation 175 pp := op.ProvisioningParameters 176 err := op.LastError 177 c.provisioningResultGauge. 178 WithLabelValues( 179 op.ID, 180 op.InstanceID, 181 pp.ErsContext.GlobalAccountID, 182 pp.PlanID, 183 string(err.Component()), 184 string(err.Reason())).Set(resultValue) 185 186 return nil 187 } 188 189 func (c *OperationResultCollector) OnDeprovisioningStepProcessed(ctx context.Context, ev interface{}) error { 190 stepProcessed, ok := ev.(process.DeprovisioningStepProcessed) 191 if !ok { 192 return fmt.Errorf("expected DeprovisioningStepProcessed but got %+v", ev) 193 } 194 195 resultValue := c.mapResult(stepProcessed.Operation.State) 196 op := stepProcessed.Operation 197 pp := op.ProvisioningParameters 198 err := op.LastError 199 c.deprovisioningResultGauge. 200 WithLabelValues( 201 op.ID, 202 op.InstanceID, 203 pp.ErsContext.GlobalAccountID, 204 pp.PlanID, 205 string(err.Component()), 206 string(err.Reason())).Set(resultValue) 207 return nil 208 } 209 210 func (c *OperationResultCollector) mapResult(state domain.LastOperationState) float64 { 211 resultValue := resultUnimplemented 212 switch state { 213 case domain.InProgress: 214 resultValue = resultInProgress 215 case domain.Succeeded: 216 resultValue = resultSucceeded 217 case domain.Failed: 218 resultValue = resultFailed 219 case Pending: 220 resultValue = resultPending 221 case Canceling: 222 resultValue = resultCanceling 223 case Canceled: 224 resultValue = resultCanceled 225 case Retrying: 226 resultValue = resultRetrying 227 } 228 229 return resultValue 230 } 231 232 func (c *OperationResultCollector) OnOperationSucceeded(ctx context.Context, ev interface{}) error { 233 operationSucceeded, ok := ev.(process.OperationSucceeded) 234 if !ok { 235 return fmt.Errorf("expected OperationSucceeded but got %+v", ev) 236 } 237 238 if operationSucceeded.Operation.Type == internal.OperationTypeProvision { 239 provisioningOperation := process.ProvisioningSucceeded{ 240 Operation: internal.ProvisioningOperation{Operation: operationSucceeded.Operation}, 241 } 242 err := c.OnProvisioningSucceeded(ctx, provisioningOperation) 243 if err != nil { 244 return err 245 } 246 } else { 247 return fmt.Errorf("expected OperationStep of type %s but got %+v", internal.OperationTypeProvision, operationSucceeded.Operation.Type) 248 } 249 250 return nil 251 }