Add caching for condition evaluation

This commit is contained in:
Holger Obermaier 2022-02-16 13:59:32 +01:00
parent 248c815a1c
commit b44e226496

View File

@ -66,6 +66,7 @@ var language gval.Language = gval.NewLanguage(
gval.Full(), gval.Full(),
metricCacheLanguage, metricCacheLanguage,
) )
var evaluables map[string]gval.Evaluable = make(map[string]gval.Evaluable)
func (c *metricAggregator) Init(output chan lp.CCMetric) error { func (c *metricAggregator) Init(output chan lp.CCMetric) error {
c.output = output c.output = output
@ -288,66 +289,41 @@ func (c *metricAggregator) AddFunction(name string, function func(args ...interf
} }
func EvalBoolCondition(condition string, params map[string]interface{}) (bool, error) { func EvalBoolCondition(condition string, params map[string]interface{}) (bool, error) {
var evaluable gval.Evaluable
var ok bool
if evaluable, ok = evaluables[condition]; !ok {
newcond := newcond :=
strings.ReplaceAll( strings.ReplaceAll(
strings.ReplaceAll( strings.ReplaceAll(
condition, "'", "\""), "%", "\\") condition, "'", "\""), "%", "\\")
value, err := gval.Evaluate(newcond, params, language) var err error
evaluable, err = language.NewEvaluable(newcond)
if err != nil { if err != nil {
return false, err return false, err
} }
endResult := false evaluables[condition] = evaluable
err = nil
switch r := value.(type) {
case bool:
endResult = r
case float64:
endResult = r != 0.0
case float32:
endResult = r != 0.0
case int:
endResult = r != 0
case int64:
endResult = r != 0
case int32:
endResult = r != 0
default:
err = fmt.Errorf("cannot evaluate '%s' to bool", newcond)
} }
return endResult, err value, err := evaluable.EvalBool(context.Background(), params)
return value, err
} }
func EvalFloat64Condition(condition string, params map[string]interface{}) (float64, error) { func EvalFloat64Condition(condition string, params map[string]interface{}) (float64, error) {
var endResult float64 = math.NaN() var evaluable gval.Evaluable
newcond := strings.ReplaceAll(condition, "'", "\"") var ok bool
newcond = strings.ReplaceAll(newcond, "%", "\\") if evaluable, ok = evaluables[condition]; !ok {
value, err := gval.Evaluate(newcond, params, language) newcond :=
strings.ReplaceAll(
strings.ReplaceAll(
condition, "'", "\""), "%", "\\")
var err error
evaluable, err = language.NewEvaluable(newcond)
if err != nil { if err != nil {
cclog.ComponentDebug("MetricRouter", condition, " = ", err.Error()) return math.NaN(), err
return endResult, err
} }
err = nil evaluables[condition] = evaluable
switch r := value.(type) {
case bool:
if r {
endResult = 1.0
} else {
endResult = 0.0
} }
case float64: value, err := evaluable.EvalFloat64(context.Background(), params)
endResult = r return value, err
case float32:
endResult = float64(r)
case int:
endResult = float64(r)
case int64:
endResult = float64(r)
case int32:
endResult = float64(r)
default:
err = fmt.Errorf("cannot evaluate '%s' to float64", newcond)
}
return endResult, err
} }
func NewAggregator(output chan lp.CCMetric) (MetricAggregator, error) { func NewAggregator(output chan lp.CCMetric) (MetricAggregator, error) {