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  }