in core/flow/rule_manager.go [404:466]
func generateStatFor(rule *Rule) (*standaloneStatistic, error) {
if !rule.needStatistic() {
return nopStat, nil
}
intervalInMs := rule.StatIntervalInMs
var retStat standaloneStatistic
var resNode *stat.ResourceNode
if rule.RelationStrategy == AssociatedResource {
// use associated statistic
resNode = stat.GetOrCreateResourceNode(rule.RefResource, base.ResTypeCommon)
} else {
resNode = stat.GetOrCreateResourceNode(rule.Resource, base.ResTypeCommon)
}
if intervalInMs == 0 || intervalInMs == config.MetricStatisticIntervalMs() {
// default case, use the resource's default statistic
readStat := resNode.DefaultMetric()
retStat.reuseResourceStat = true
retStat.readOnlyMetric = readStat
retStat.writeOnlyMetric = nil
return &retStat, nil
}
sampleCount := uint32(0)
//calculate the sample count
if intervalInMs > config.GlobalStatisticIntervalMsTotal() {
sampleCount = 1
} else if intervalInMs < config.GlobalStatisticBucketLengthInMs() {
sampleCount = 1
} else {
if intervalInMs%config.GlobalStatisticBucketLengthInMs() == 0 {
sampleCount = intervalInMs / config.GlobalStatisticBucketLengthInMs()
} else {
sampleCount = 1
}
}
err := base.CheckValidityForReuseStatistic(sampleCount, intervalInMs, config.GlobalStatisticSampleCountTotal(), config.GlobalStatisticIntervalMsTotal())
if err == nil {
// global statistic reusable
readStat, e := resNode.GenerateReadStat(sampleCount, intervalInMs)
if e != nil {
return nil, e
}
retStat.reuseResourceStat = true
retStat.readOnlyMetric = readStat
retStat.writeOnlyMetric = nil
return &retStat, nil
} else if err == base.GlobalStatisticNonReusableError {
logging.Info("[FlowRuleManager] Flow rule couldn't reuse global statistic and will generate independent statistic", "rule", rule)
retStat.reuseResourceStat = false
realLeapArray := sbase.NewBucketLeapArray(sampleCount, intervalInMs)
metricStat, e := sbase.NewSlidingWindowMetric(sampleCount, intervalInMs, realLeapArray)
if e != nil {
return nil, errors.Errorf("fail to generate statistic for warm up rule: %+v, err: %+v", rule, e)
}
retStat.readOnlyMetric = metricStat
retStat.writeOnlyMetric = realLeapArray
return &retStat, nil
}
return nil, errors.Wrapf(err, "fail to new standalone statistic because of invalid StatIntervalInMs in flow.Rule, StatIntervalInMs: %d", intervalInMs)
}