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  }