Skip to content

Commit

Permalink
[incubator-kie-drools-6016] Emit a warning when an eval is improperly…
Browse files Browse the repository at this point in the history
… and unnecessarily used
  • Loading branch information
tkobayas committed Jul 12, 2024
1 parent ddb72c6 commit fd33fc1
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 1 deletion.
39 changes: 39 additions & 0 deletions drools-base/src/main/java/org/drools/base/rule/EvalCondition.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,18 @@
import org.drools.base.rule.accessor.CompiledInvoker;
import org.drools.base.rule.accessor.EvalExpression;
import org.drools.base.rule.accessor.Wireable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class EvalCondition extends ConditionalElement
implements
Externalizable,
Wireable {

private static final Logger LOG = LoggerFactory.getLogger(EvalCondition.class);

private static long warnLogCounter = 0;

private static final long serialVersionUID = 510l;

protected EvalExpression expression;
Expand Down Expand Up @@ -223,4 +230,36 @@ public void setCloned(List<EvalCondition> cloned) {
public String toString() {
return this.expression.toString();
}

public static void logWarnIfImproperEval(EvalCondition evalCondition, String evalExpression) {
if (warnLogCounter == 10) {
warnLogCounter++;
LOG.warn("More eval warnings will be suppressed...");
return;
} else if (warnLogCounter > 10) {
return; // avoid flooding the logs
}

if (evalExpression == null || evalExpression.isEmpty()) {
return; // cannot provide a meaningful warning
}

StringBuilder sb = new StringBuilder();
for (Declaration declaration : evalCondition.getRequiredDeclarations()) {
if (declaration.getPattern() != null) {
sb.append("'");
sb.append(declaration.getIdentifier());
sb.append("' comes from previous pattern '");
String className = declaration.getPattern().getObjectType().getClassName();
sb.append(className.substring(className.lastIndexOf('.') + 1));
sb.append("'. ");
}
}
if (!sb.isEmpty()) {
warnLogCounter++;
LOG.warn("In an eval expression [{}] : {}" +
"Consider placing the constraint in the pattern and removing the eval if possible," +
" as eval is not performance-efficient.", evalExpression, sb);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@
import org.kie.internal.builder.conf.PropertySpecificOption;

import static java.util.stream.Collectors.toList;
import static org.drools.base.rule.EvalCondition.logWarnIfImproperEval;
import static org.drools.base.rule.GroupElement.AND;
import static org.drools.base.rule.GroupElement.OR;
import static org.drools.compiler.rule.builder.RuleBuilder.buildTimer;
Expand Down Expand Up @@ -669,7 +670,9 @@ private void recursivelyAddConditions(RuleContext ctx, GroupElement group, Group
private EvalCondition buildEval(RuleContext ctx, EvalImpl eval) {
Declaration[] declarations = Stream.of( eval.getExpr().getVariables() ).map( ctx::getDeclaration ).toArray( Declaration[]::new );
EvalExpression evalExpr = new LambdaEvalExpression(declarations, eval.getExpr());
return new EvalCondition(evalExpr, declarations);
EvalCondition evalCondition = new EvalCondition(evalExpr, declarations);
logWarnIfImproperEval(evalCondition, eval.getExpr().predicateInformation().getStringConstraint());
return evalCondition;
}

private ConditionalBranch buildConditionalConsequence(RuleContext ctx, ConditionalNamedConsequenceImpl consequence) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.drools.base.rule.RuleConditionElement;
import org.drools.base.rule.accessor.DeclarationScopeResolver;

import static org.drools.base.rule.EvalCondition.logWarnIfImproperEval;
import static org.drools.compiler.rule.builder.PatternBuilder.buildAnalysis;
import static org.drools.compiler.rule.builder.PatternBuilder.createImplicitBindings;
import static org.drools.mvel.java.JavaRuleBuilderHelper.createVariableContext;
Expand Down Expand Up @@ -90,6 +91,7 @@ private RuleConditionElement buildEval(RuleBuildContext context, EvalDescr evalD
Arrays.sort(declarations, SortDeclarations.instance);

EvalCondition eval = EvalConditionFactory.Factory.get().createEvalCondition(declarations);
logWarnIfImproperEval(eval, (String) evalDescr.getContent());

Map<String, Object> vars = createVariableContext( className,
(String)evalDescr.getContent(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.drools.mvel.expr.MVELCompilationUnit;
import org.drools.mvel.expr.MVELEvalExpression;

import static org.drools.base.rule.EvalCondition.logWarnIfImproperEval;
import static org.drools.mvel.asm.AsmUtil.copyErrorLocation;

public class MVELEvalBuilder
Expand Down Expand Up @@ -99,6 +100,7 @@ public RuleConditionElement build(final RuleBuildContext context,
false,
MVELCompilationUnit.Scope.EXPRESSION );
final EvalCondition eval = EvalConditionFactory.Factory.get().createEvalCondition( previousDeclarations );
logWarnIfImproperEval(eval, (String) evalDescr.getContent());

MVELEvalExpression expr = new MVELEvalExpression( unit,
dialect.getId() );
Expand Down

0 comments on commit fd33fc1

Please sign in to comment.