// run starts an analysis which runs the query at the given interval, until the context is done.
// It returns an error when the number of failures exceeds the the failureLimit.
run starts an analysis which runs the query at the given interval, until the context is done.
It returns an error when the number of failures exceeds the the failureLimit.
// run starts an analysis which runs the query at the given interval until the context is done . // It returns an error when the number of failures exceeds the the failureLimit .
func (a *metricsAnalyzer) run(ctx context.Context) error {
	ticker := time.NewTicker(a.cfg.Interval.Duration())
	defer ticker.Stop()
	failureCount := 0
	for {
		select {
		case <-ticker.C:
			var (
				expected bool
				err      error
			)
			switch a.cfg.Strategy {
			case config.AnalysisStrategyThreshold:
				expected, err = a.analyzeWithThreshold(ctx)
			case config.AnalysisStrategyPrevious:
				var firstDeploy bool
				expected, firstDeploy, err = a.analyzeWithPrevious(ctx)
				if firstDeploy {
					a.logPersister.Infof("[%s] PreviousAnalysis cannot be executed because this seems to be the first deployment, so it is considered as a success", a.id)
					return nil
				}
			case config.AnalysisStrategyCanaryBaseline:
				expected, err = a.analyzeWithCanaryBaseline(ctx)
			case config.AnalysisStrategyCanaryPrimary:
				expected, err = a.analyzeWithCanaryPrimary(ctx)
			default:
				return fmt.Errorf("unknown strategy %q given", a.cfg.Strategy)
			}
			if errors.Is(err, context.DeadlineExceeded) && ctx.Err() == context.DeadlineExceeded {
				return nil
			}
			if errors.Is(err, metrics.ErrNoDataFound) && a.cfg.SkipOnNoData {
				a.logPersister.Infof("[%s] The query result evaluation was skipped because \"skipOnNoData\" is true though no data returned. Reason: %v", a.id, err)
				continue
			}
			if err != nil {
				a.logPersister.Errorf("[%s] Unexpected error: %v", a.id, err)
			}
			if expected {
				a.logPersister.Successf("[%s] The query result is expected one", a.id)
				continue
			}
			failureCount++
			if failureCount > a.cfg.FailureLimit {
				return fmt.Errorf("analysis '%s' failed because the failure number exceeded the failure limit (%d)", a.id, a.cfg.FailureLimit)
			}
		case <-ctx.Done():
			return nil
		}
	}
}
func ( a * metricsAnalyzer ) run ( ctx context . Context ) error { ticker := time . NewTicker ( a . cfg . Interval . Duration ( ) ) defer ticker . Stop ( ) failureCount := 0 for { select { case <- ticker . C : var ( expected bool err error ) switch a . cfg . Strategy { case config . AnalysisStrategyThreshold : expected , err = a . analyzeWithThreshold ( ctx ) case config . AnalysisStrategyPrevious : var firstDeploy bool expected , firstDeploy , err = a . analyzeWithPrevious ( ctx ) if firstDeploy { a . logPersister . Infof ( " " , a . id ) return nil } case config . AnalysisStrategyCanaryBaseline : expected , err = a . analyzeWithCanaryBaseline ( ctx ) case config . AnalysisStrategyCanaryPrimary : expected , err = a . analyzeWithCanaryPrimary ( ctx ) default : return fmt . Errorf ( " " , a . cfg . Strategy ) } if errors . Is ( err , context . DeadlineExceeded ) && ctx . Err ( ) == context . DeadlineExceeded { return nil } if errors . Is ( err , metrics . ErrNoDataFound ) && a . cfg . SkipOnNoData { a . logPersister . Infof ( " \" \" " , a . id , err ) continue } if err != nil { a . logPersister . Errorf ( " " , a . id , err ) } if expected { a . logPersister . Successf ( " " , a . id ) continue } failureCount ++ if failureCount > a . cfg . FailureLimit { return fmt . Errorf ( " " , a . id , a . cfg . FailureLimit ) } case <- ctx . Done ( ) : return nil } } }
run starts an analysis which runs the query at the given interval, until the context is done.
run starts an analysis which runs the query at the given interval until the context is done .
// Ignore parent's context deadline exceeded error, and return immediately.