github.com/kyma-project/kyma-environment-broker@v0.0.1/internal/metrics/step_result.go (about) 1 package metrics 2 3 import ( 4 "context" 5 "fmt" 6 "time" 7 8 "github.com/kyma-project/kyma-environment-broker/internal" 9 10 "github.com/kyma-project/kyma-environment-broker/internal/process" 11 "github.com/pivotal-cf/brokerapi/v8/domain" 12 "github.com/prometheus/client_golang/prometheus" 13 ) 14 15 // StepResultCollector provides the following metrics: 16 // - compass_keb_provisioning_step_result{"operation_id", "instance_id", "step_name", "global_account_id", "plan_id"} 17 // - compass_keb_deprovisioning_step_result{"operation_id", "instance_id", "step_name", "global_account_id", "plan_id"} 18 // These gauges show the status of the operation step. 19 // The value of the gauge could be: 20 // 0 - Failed 21 // 1 - Succeeded 22 // 2 - In progress 23 type StepResultCollector struct { 24 provisioningResultGauge *prometheus.GaugeVec 25 deprovisioningResultGauge *prometheus.GaugeVec 26 } 27 28 func NewStepResultCollector() *StepResultCollector { 29 return &StepResultCollector{ 30 provisioningResultGauge: prometheus.NewGaugeVec(prometheus.GaugeOpts{ 31 Namespace: prometheusNamespace, 32 Subsystem: prometheusSubsystem, 33 Name: "provisioning_step_result", 34 Help: "Result of the provisioning step", 35 }, []string{"operation_id", "instance_id", "step_name", "global_account_id", "plan_id"}), 36 deprovisioningResultGauge: prometheus.NewGaugeVec(prometheus.GaugeOpts{ 37 Namespace: prometheusNamespace, 38 Subsystem: prometheusSubsystem, 39 Name: "deprovisioning_step_result", 40 Help: "Result of the deprovisioning step", 41 }, []string{"operation_id", "instance_id", "step_name", "global_account_id", "plan_id"}), 42 } 43 } 44 45 func (c *StepResultCollector) Describe(ch chan<- *prometheus.Desc) { 46 c.provisioningResultGauge.Describe(ch) 47 c.deprovisioningResultGauge.Describe(ch) 48 } 49 50 func (c *StepResultCollector) Collect(ch chan<- prometheus.Metric) { 51 c.provisioningResultGauge.Collect(ch) 52 c.deprovisioningResultGauge.Collect(ch) 53 } 54 55 func (c *StepResultCollector) OnProvisioningStepProcessed(ctx context.Context, ev interface{}) error { 56 stepProcessed, ok := ev.(process.ProvisioningStepProcessed) 57 if !ok { 58 return fmt.Errorf("expected ProvisioningStepProcessed but got %+v", ev) 59 } 60 61 var resultValue float64 62 switch { 63 case stepProcessed.Operation.State == domain.Succeeded: 64 resultValue = resultSucceeded 65 case stepProcessed.When > 0 && stepProcessed.Error == nil: 66 resultValue = resultInProgress 67 case stepProcessed.When == 0 && stepProcessed.Error == nil: 68 resultValue = resultSucceeded 69 case stepProcessed.Error != nil: 70 resultValue = resultFailed 71 } 72 op := stepProcessed.Operation 73 pp := op.ProvisioningParameters 74 c.provisioningResultGauge.WithLabelValues( 75 op.ID, 76 op.InstanceID, 77 stepProcessed.StepName, 78 pp.ErsContext.GlobalAccountID, 79 pp.PlanID).Set(resultValue) 80 81 return nil 82 } 83 84 func (c *StepResultCollector) OnDeprovisioningStepProcessed(ctx context.Context, ev interface{}) error { 85 stepProcessed, ok := ev.(process.DeprovisioningStepProcessed) 86 if !ok { 87 return fmt.Errorf("expected DeprovisioningStepProcessed but got %+v", ev) 88 } 89 90 var resultValue float64 91 switch { 92 case stepProcessed.When > 0 && stepProcessed.Error == nil: 93 resultValue = resultInProgress 94 case stepProcessed.When == 0 && stepProcessed.Error == nil: 95 resultValue = resultSucceeded 96 case stepProcessed.Error != nil: 97 resultValue = resultFailed 98 } 99 100 // Create_Runtime step always returns operation, 1 second, nil if everything is ok 101 // this code is a workaround and should be removed when the step engine is refactored 102 if stepProcessed.StepName == "Create_Runtime" && stepProcessed.When == time.Second { 103 resultValue = resultSucceeded 104 } 105 106 op := stepProcessed.Operation 107 pp := op.ProvisioningParameters 108 c.deprovisioningResultGauge.WithLabelValues( 109 op.ID, 110 op.InstanceID, 111 stepProcessed.StepName, 112 pp.ErsContext.GlobalAccountID, 113 pp.PlanID).Set(resultValue) 114 return nil 115 } 116 117 func (c *StepResultCollector) OnOperationStepProcessed(ctx context.Context, ev interface{}) error { 118 stepProcessed, ok := ev.(process.OperationStepProcessed) 119 if !ok { 120 return fmt.Errorf("expected OperationStepProcessed but got %+v", ev) 121 } 122 123 switch { 124 case stepProcessed.Operation.Type == internal.OperationTypeProvision: 125 provisioningStepProcessed := process.ProvisioningStepProcessed{ 126 Operation: internal.ProvisioningOperation{Operation: stepProcessed.Operation}, 127 StepProcessed: stepProcessed.StepProcessed, 128 } 129 err := c.OnProvisioningStepProcessed(ctx, provisioningStepProcessed) 130 if err != nil { 131 return err 132 } 133 case stepProcessed.Operation.Type == internal.OperationTypeDeprovision: 134 deprovisioningStepProcessed := process.DeprovisioningStepProcessed{ 135 Operation: internal.DeprovisioningOperation{Operation: stepProcessed.Operation}, 136 StepProcessed: stepProcessed.StepProcessed, 137 } 138 err := c.OnDeprovisioningStepProcessed(ctx, deprovisioningStepProcessed) 139 if err != nil { 140 return err 141 } 142 default: 143 return fmt.Errorf("expected OperationStep of types [%s, %s] but got %+v", internal.OperationTypeProvision, internal.OperationTypeDeprovision, stepProcessed.Operation.Type) 144 } 145 146 return nil 147 }