github.com/kyma-project/kyma-environment-broker@v0.0.1/internal/metrics/operation_duration.go (about) 1 package metrics 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/kyma-project/kyma-environment-broker/internal" 8 "github.com/kyma-project/kyma-environment-broker/internal/process" 9 10 "github.com/pivotal-cf/brokerapi/v8/domain" 11 "github.com/prometheus/client_golang/prometheus" 12 ) 13 14 // OperationDurationCollector provides histograms which describes the time of provisioning/deprovisioning operations: 15 // - compass_keb_provisioning_duration_minutes 16 // - compass_keb_deprovisioning_duration_minutes 17 type OperationDurationCollector struct { 18 provisioningHistogram *prometheus.HistogramVec 19 deprovisioningHistogram *prometheus.HistogramVec 20 } 21 22 func NewOperationDurationCollector() *OperationDurationCollector { 23 return &OperationDurationCollector{ 24 provisioningHistogram: prometheus.NewHistogramVec(prometheus.HistogramOpts{ 25 Namespace: prometheusNamespace, 26 Subsystem: prometheusSubsystem, 27 Name: "provisioning_duration_minutes", 28 Help: "The time of the provisioning process", 29 Buckets: prometheus.LinearBuckets(20, 2, 40), 30 }, []string{"operation_id", "instance_id", "global_account_id", "plan_id"}), 31 deprovisioningHistogram: prometheus.NewHistogramVec(prometheus.HistogramOpts{ 32 Namespace: prometheusNamespace, 33 Subsystem: prometheusSubsystem, 34 Name: "deprovisioning_duration_minutes", 35 Help: "The time of the deprovisioning process", 36 Buckets: prometheus.LinearBuckets(1, 1, 30), 37 }, []string{"operation_id", "instance_id", "global_account_id", "plan_id"}), 38 } 39 } 40 41 func (c *OperationDurationCollector) Describe(ch chan<- *prometheus.Desc) { 42 c.provisioningHistogram.Describe(ch) 43 c.deprovisioningHistogram.Describe(ch) 44 } 45 46 func (c *OperationDurationCollector) Collect(ch chan<- prometheus.Metric) { 47 c.provisioningHistogram.Collect(ch) 48 c.deprovisioningHistogram.Collect(ch) 49 } 50 51 func (c *OperationDurationCollector) OnProvisioningSucceeded(ctx context.Context, ev interface{}) error { 52 provision, ok := ev.(process.ProvisioningSucceeded) 53 if !ok { 54 return fmt.Errorf("expected process.ProvisioningSucceeded but got %+v", ev) 55 } 56 57 op := provision.Operation 58 pp := op.ProvisioningParameters 59 minutes := op.UpdatedAt.Sub(op.CreatedAt).Minutes() 60 c.provisioningHistogram. 61 WithLabelValues(op.ID, op.InstanceID, pp.ErsContext.GlobalAccountID, pp.PlanID).Observe(minutes) 62 63 return nil 64 } 65 66 func (c *OperationDurationCollector) OnDeprovisioningStepProcessed(ctx context.Context, ev interface{}) error { 67 stepProcessed, ok := ev.(process.DeprovisioningStepProcessed) 68 if !ok { 69 return fmt.Errorf("expected process.DeprovisioningStepProcessed but got %+v", ev) 70 } 71 72 op := stepProcessed.Operation 73 pp := op.ProvisioningParameters 74 if stepProcessed.OldOperation.State == domain.InProgress && op.State == domain.Succeeded { 75 minutes := op.UpdatedAt.Sub(op.CreatedAt).Minutes() 76 c.deprovisioningHistogram. 77 WithLabelValues(op.ID, op.InstanceID, pp.ErsContext.GlobalAccountID, pp.PlanID).Observe(minutes) 78 } 79 80 return nil 81 } 82 83 func (c *OperationDurationCollector) OnOperationStepProcessed(ctx context.Context, ev interface{}) error { 84 stepProcessed, ok := ev.(process.OperationStepProcessed) 85 if !ok { 86 return fmt.Errorf("expected process.OperationStepProcessed in OnOperationStepProcessed but got %+v", ev) 87 } 88 89 if stepProcessed.Operation.Type == internal.OperationTypeDeprovision { 90 dsp := process.DeprovisioningStepProcessed{ 91 StepProcessed: stepProcessed.StepProcessed, 92 OldOperation: internal.DeprovisioningOperation{Operation: stepProcessed.OldOperation}, 93 Operation: internal.DeprovisioningOperation{Operation: stepProcessed.Operation}, 94 } 95 err := c.OnDeprovisioningStepProcessed(ctx, dsp) 96 if err != nil { 97 return fmt.Errorf("failed to handle OnDeprovisioningStepProcessed in OnOperationStepProcessed: %w", err) 98 } 99 } 100 return nil 101 } 102 103 func (c *OperationDurationCollector) OnOperationSucceeded(ctx context.Context, ev interface{}) error { 104 operationSucceeded, ok := ev.(process.OperationSucceeded) 105 if !ok { 106 return fmt.Errorf("expected OperationSucceeded but got %+v", ev) 107 } 108 109 switch operationSucceeded.Operation.Type { 110 case internal.OperationTypeProvision: 111 provisioningOperation := process.ProvisioningSucceeded{ 112 Operation: internal.ProvisioningOperation{Operation: operationSucceeded.Operation}, 113 } 114 err := c.OnProvisioningSucceeded(ctx, provisioningOperation) 115 if err != nil { 116 return err 117 } 118 case internal.OperationTypeDeprovision: 119 op := operationSucceeded.Operation 120 pp := operationSucceeded.Operation.ProvisioningParameters 121 minutes := op.UpdatedAt.Sub(op.CreatedAt).Minutes() 122 c.deprovisioningHistogram.WithLabelValues(op.ID, op.InstanceID, pp.ErsContext.GlobalAccountID, pp.PlanID).Observe(minutes) 123 default: 124 return fmt.Errorf("unsupported OperationStep %+v for OnOperationSucceeded handler", operationSucceeded.Operation.Type) 125 } 126 127 return nil 128 }