diff --git a/data-prepper-api/src/main/java/org/opensearch/dataprepper/expression/ExpressionEvaluator.java b/data-prepper-api/src/main/java/org/opensearch/dataprepper/expression/ExpressionEvaluator.java index 084bf50452..464152121a 100644 --- a/data-prepper-api/src/main/java/org/opensearch/dataprepper/expression/ExpressionEvaluator.java +++ b/data-prepper-api/src/main/java/org/opensearch/dataprepper/expression/ExpressionEvaluator.java @@ -27,11 +27,17 @@ public interface ExpressionEvaluator { Object evaluate(final String statement, final Event context); default Boolean evaluateConditional(final String statement, final Event context) { - final Object result = evaluate(statement, context); - if (result instanceof Boolean) { - return (Boolean) result; - } else { - throw new ClassCastException("Unexpected expression return type of " + result.getClass()); + Object result; + try { + result = evaluate(statement, context); + if (result instanceof Boolean) { + return (Boolean) result; + } + throw new ClassCastException("Unexpected expression return value of " + result); + } catch (ExpressionParsingException e) { + throw e; + } catch (ExpressionEvaluationException e) { + return false; } } @@ -42,4 +48,4 @@ default Boolean evaluateConditional(final String statement, final Event context) List extractDynamicKeysFromFormatExpression(final String format); List extractDynamicExpressionsFromFormatExpression(final String format); -} \ No newline at end of file +} diff --git a/data-prepper-api/src/main/java/org/opensearch/dataprepper/expression/ExpressionParsingException.java b/data-prepper-api/src/main/java/org/opensearch/dataprepper/expression/ExpressionParsingException.java new file mode 100644 index 0000000000..62eda7109d --- /dev/null +++ b/data-prepper-api/src/main/java/org/opensearch/dataprepper/expression/ExpressionParsingException.java @@ -0,0 +1,17 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.dataprepper.expression; + +/** + * @since 2.11 + * Wrapper exception for any exception thrown while evaluating a statement + */ +public class ExpressionParsingException extends ExpressionEvaluationException { + public ExpressionParsingException(final String message, final Throwable cause) { + super(message, cause); + } +} + diff --git a/data-prepper-api/src/test/java/org/opensearch/dataprepper/expression/ExpressionEvaluatorTest.java b/data-prepper-api/src/test/java/org/opensearch/dataprepper/expression/ExpressionEvaluatorTest.java index bd33525db3..ed53ca4e3b 100644 --- a/data-prepper-api/src/test/java/org/opensearch/dataprepper/expression/ExpressionEvaluatorTest.java +++ b/data-prepper-api/src/test/java/org/opensearch/dataprepper/expression/ExpressionEvaluatorTest.java @@ -19,7 +19,29 @@ public class ExpressionEvaluatorTest { private ExpressionEvaluator expressionEvaluator; class TestExpressionEvaluator implements ExpressionEvaluator { + private final boolean throwsExpressionEvaluationException; + private final boolean throwsExpressionParsingException; + private final boolean returnNull; + public TestExpressionEvaluator() { + throwsExpressionEvaluationException = false; + throwsExpressionParsingException = false; + returnNull = false; + } + + public TestExpressionEvaluator(boolean throwsExpressionEvaluationException, boolean throwsExpressionParsingException, boolean returnNull) { + this.throwsExpressionEvaluationException = throwsExpressionEvaluationException; + this.throwsExpressionParsingException = throwsExpressionParsingException; + this.returnNull = returnNull; + } + public Object evaluate(final String statement, final Event event) { + if (throwsExpressionEvaluationException) { + throw new ExpressionEvaluationException("Expression Evaluation Exception", new RuntimeException("runtime exception")); + } else if (throwsExpressionParsingException) { + throw new ExpressionParsingException("Expression Parsing Exception", new RuntimeException("runtime exception")); + } else if (returnNull) { + return null; + } return event.get(statement, Object.class); } @@ -48,7 +70,30 @@ public List extractDynamicExpressionsFromFormatExpression(String format) public void testDefaultEvaluateConditional() { expressionEvaluator = new TestExpressionEvaluator(); assertThat(expressionEvaluator.evaluateConditional("/status", event("{\"status\":true}")), equalTo(true)); - + } + + @Test + public void testEvaluateReturningException() { + expressionEvaluator = new TestExpressionEvaluator(); + assertThrows(ClassCastException.class, () -> expressionEvaluator.evaluateConditional("/status", event("{\"nostatus\":true}"))); + } + + @Test + public void testThrowExpressionEvaluationException() { + expressionEvaluator = new TestExpressionEvaluator(true, false, false); + assertThat(expressionEvaluator.evaluateConditional("/status", event("{\"nostatus\":true}")), equalTo(false)); + } + + @Test + public void testThrowExpressionParsingException() { + expressionEvaluator = new TestExpressionEvaluator(false, true, false); + assertThrows(ExpressionParsingException.class, () -> expressionEvaluator.evaluateConditional("/status", event("{\"nostatus\":true}"))); + } + + @Test + public void testExpressionEvaluationReturnsNull() { + expressionEvaluator = new TestExpressionEvaluator(false, false, true); + assertThrows(ClassCastException.class, () -> expressionEvaluator.evaluateConditional("/status", event("{\"nostatus\":true}"))); } @Test diff --git a/data-prepper-api/src/test/java/org/opensearch/dataprepper/expression/ExpressionParsingExceptionTest.java b/data-prepper-api/src/test/java/org/opensearch/dataprepper/expression/ExpressionParsingExceptionTest.java new file mode 100644 index 0000000000..23129a11f9 --- /dev/null +++ b/data-prepper-api/src/test/java/org/opensearch/dataprepper/expression/ExpressionParsingExceptionTest.java @@ -0,0 +1,25 @@ +/* + * + * * Copyright OpenSearch Contributors + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package org.opensearch.dataprepper.expression; + +import org.junit.jupiter.api.Test; + +import java.util.UUID; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +class ExpressionParsingExceptionTest { + + @Test + void testExpressionParsingException() { + final ExpressionParsingException exception = new ExpressionParsingException(UUID.randomUUID().toString(), null); + assertThat(exception instanceof RuntimeException, is(true)); + } +} + diff --git a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/AddBinaryOperator.java b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/AddBinaryOperator.java index 50588b2e8a..a95e74a103 100644 --- a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/AddBinaryOperator.java +++ b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/AddBinaryOperator.java @@ -18,6 +18,12 @@ class AddBinaryOperator implements Operator { private final String displayName; private final Map, Map, BiFunction>> operandsToOperationMap; + + @Override + public boolean isBooleanOperator() { + return false; + } + public AddBinaryOperator(final int symbol, final Map, Map, BiFunction>> operandsToOperationMap) { this.symbol = symbol; @@ -41,6 +47,7 @@ public Object evaluate(final Object ... args) { checkArgument(args.length == 2, displayName + " requires operands length needs to be 2."); final Object leftValue = args[0]; final Object rightValue = args[1]; + checkArgument(leftValue != null && rightValue != null, displayName + " requires operands length needs to be non-null."); final Class leftValueClass = leftValue.getClass(); final Class rightValueClass = rightValue.getClass(); if (leftValue instanceof String && rightValue instanceof String) { diff --git a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/AndOperator.java b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/AndOperator.java index cb28ce6d0a..80f30aa9c7 100644 --- a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/AndOperator.java +++ b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/AndOperator.java @@ -18,6 +18,11 @@ class AndOperator implements Operator { private static final String DISPLAY_NAME = DataPrepperExpressionParser.VOCABULARY .getDisplayName(DataPrepperExpressionParser.AND); + @Override + public boolean isBooleanOperator() { + return true; + } + @Override public boolean shouldEvaluate(final RuleContext ctx) { return ctx.getRuleIndex() == DataPrepperExpressionParser.RULE_conditionalExpression; diff --git a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/ArithmeticBinaryOperator.java b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/ArithmeticBinaryOperator.java index e276a468ff..d830db3390 100644 --- a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/ArithmeticBinaryOperator.java +++ b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/ArithmeticBinaryOperator.java @@ -18,6 +18,11 @@ class ArithmeticBinaryOperator implements Operator { private final String displayName; private final Map, Map, BiFunction>> operandsToOperationMap; + @Override + public boolean isBooleanOperator() { + return false; + } + public ArithmeticBinaryOperator(final int symbol, final Map, Map, BiFunction>> operandsToOperationMap) { this.symbol = symbol; @@ -40,6 +45,7 @@ public Number evaluate(final Object ... args) { checkArgument(args.length == 2, displayName + " requires operands length needs to be 2."); final Object leftValue = args[0]; final Object rightValue = args[1]; + checkArgument(leftValue != null && rightValue != null, displayName + " requires operands length needs to be non-null."); final Class leftValueClass = leftValue.getClass(); final Class rightValueClass = rightValue.getClass(); if (!operandsToOperationMap.containsKey(leftValueClass)) { diff --git a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/ArithmeticSubtractOperator.java b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/ArithmeticSubtractOperator.java index dd21d067de..bf4ba684d0 100644 --- a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/ArithmeticSubtractOperator.java +++ b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/ArithmeticSubtractOperator.java @@ -29,6 +29,11 @@ public ArithmeticSubtractOperator(final int symbol, this.strategy = strategy; } + @Override + public boolean isBooleanOperator() { + return false; + } + @Override public int getNumberOfOperands(final RuleContext ctx) { if (ctx.getRuleIndex() == DataPrepperExpressionParser.RULE_arithmeticExpression) @@ -59,6 +64,7 @@ public Number evaluate(final Object ... args) { checkArgument(args.length == 2, displayName + " requires operands length needs to be 2."); final Object leftValue = args[0]; final Object rightValue = args[1]; + checkArgument(leftValue != null && rightValue != null, displayName + " requires operands length needs to be non-null."); final Class leftValueClass = leftValue.getClass(); final Class rightValueClass = rightValue.getClass(); if (!operandsToOperationMap.containsKey(leftValueClass)) { diff --git a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericEqualOperator.java b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericEqualOperator.java index 88cdecc3b5..bf9cc64596 100644 --- a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericEqualOperator.java +++ b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericEqualOperator.java @@ -20,6 +20,11 @@ public GenericEqualOperator( this.equalStrategy = equalStrategy; } + @Override + public boolean isBooleanOperator() { + return true; + } + @Override protected Boolean checkedEvaluate(final Object lhs, final Object rhs) { if (lhs == null || rhs == null) { diff --git a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluator.java b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluator.java index 791d954c23..9f899c4917 100644 --- a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluator.java +++ b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluator.java @@ -36,11 +36,15 @@ public GenericExpressionEvaluator(final Parser parser, final Evaluato */ @Override public Object evaluate(final String statement, final Event context) { + ParseTree parseTree = null; try { - final ParseTree parseTree = parser.parse(statement); - return evaluator.evaluate(parseTree, context); + parseTree = parser.parse(statement); + } catch (final Exception exception) { + throw new ExpressionParsingException("Unable to parse statement \"" + statement + "\"", exception); } - catch (final Exception exception) { + try { + return evaluator.evaluate(parseTree, context); + } catch (final Exception exception) { throw new ExpressionEvaluationException("Unable to evaluate statement \"" + statement + "\"", exception); } } diff --git a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericInSetOperator.java b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericInSetOperator.java index 989e6d5bdd..07522be3bc 100644 --- a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericInSetOperator.java +++ b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericInSetOperator.java @@ -24,6 +24,11 @@ public GenericInSetOperator(final int symbol, BiPredicate operat this.operation = operation; } + @Override + public boolean isBooleanOperator() { + return true; + } + @Override public boolean shouldEvaluate(final RuleContext ctx) { return ctx.getRuleIndex() == DataPrepperExpressionParser.RULE_setOperatorExpression; diff --git a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericNotOperator.java b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericNotOperator.java index d73eaa2047..e9dc4555f1 100644 --- a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericNotOperator.java +++ b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericNotOperator.java @@ -16,6 +16,11 @@ public GenericNotOperator(final int symbol, final int shouldEvaluateRuleIndex, f this.innerOperator = innerOperator; } + @Override + public boolean isBooleanOperator() { + return true; + } + @Override public int getNumberOfOperands(final RuleContext ctx) { return innerOperator.getNumberOfOperands(ctx); diff --git a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericRegexMatchOperator.java b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericRegexMatchOperator.java index b4d34dadc1..c2a4dbde5a 100644 --- a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericRegexMatchOperator.java +++ b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericRegexMatchOperator.java @@ -24,6 +24,11 @@ public GenericRegexMatchOperator(final int symbol, BiPredicate o this.operation = operation; } + @Override + public boolean isBooleanOperator() { + return true; + } + @Override public boolean shouldEvaluate(final RuleContext ctx) { return ctx.getRuleIndex() == DataPrepperExpressionParser.RULE_regexOperatorExpression; diff --git a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericTypeOfOperator.java b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericTypeOfOperator.java index b910183c5c..09552d218b 100644 --- a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericTypeOfOperator.java +++ b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/GenericTypeOfOperator.java @@ -23,6 +23,11 @@ public GenericTypeOfOperator(final int symbol, BiPredicate opera this.operation = operation; } + @Override + public boolean isBooleanOperator() { + return true; + } + @Override public boolean shouldEvaluate(final RuleContext ctx) { return ctx.getRuleIndex() == DataPrepperExpressionParser.RULE_typeOfOperatorExpression; diff --git a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/NotOperator.java b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/NotOperator.java index d244eebfa3..d220de1279 100644 --- a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/NotOperator.java +++ b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/NotOperator.java @@ -18,6 +18,11 @@ class NotOperator implements Operator { private static final String DISPLAY_NAME = DataPrepperExpressionParser.VOCABULARY .getDisplayName(DataPrepperExpressionParser.NOT); + @Override + public boolean isBooleanOperator() { + return true; + } + @Override public int getNumberOfOperands(final RuleContext ctx) { return 1; diff --git a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/NumericCompareOperator.java b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/NumericCompareOperator.java index a09ba5f2af..c85b116eee 100644 --- a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/NumericCompareOperator.java +++ b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/NumericCompareOperator.java @@ -25,6 +25,11 @@ public NumericCompareOperator(final int symbol, this.operandsToOperationMap = operandsToOperationMap; } + @Override + public boolean isBooleanOperator() { + return true; + } + @Override public boolean shouldEvaluate(final RuleContext ctx) { return ctx.getRuleIndex() == DataPrepperExpressionParser.RULE_relationalOperatorExpression; @@ -40,6 +45,7 @@ public Boolean evaluate(final Object ... args) { checkArgument(args.length == 2, displayName + " requires operands length needs to be 2."); final Object leftValue = args[0]; final Object rightValue = args[1]; + checkArgument(leftValue != null && rightValue != null, displayName + " requires operands length needs to be non-null."); final Class leftValueClass = leftValue.getClass(); final Class rightValueClass = rightValue.getClass(); if (!operandsToOperationMap.containsKey(leftValueClass)) { diff --git a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/Operator.java b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/Operator.java index 40bb7e3814..e2736a8f47 100644 --- a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/Operator.java +++ b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/Operator.java @@ -12,6 +12,8 @@ default int getNumberOfOperands(final RuleContext ctx) { return 2; } + boolean isBooleanOperator(); + boolean shouldEvaluate(final RuleContext ctx); int getSymbol(); diff --git a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/OrOperator.java b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/OrOperator.java index 35b21f496f..72d8f8adc0 100644 --- a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/OrOperator.java +++ b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/OrOperator.java @@ -18,6 +18,11 @@ class OrOperator implements Operator { private static final String DISPLAY_NAME = DataPrepperExpressionParser.VOCABULARY .getDisplayName(DataPrepperExpressionParser.OR); + @Override + public boolean isBooleanOperator() { + return true; + } + @Override public boolean shouldEvaluate(final RuleContext ctx) { return ctx.getRuleIndex() == DataPrepperExpressionParser.RULE_conditionalExpression; diff --git a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/ParseTreeEvaluator.java b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/ParseTreeEvaluator.java index 1d0acc9924..39a15989e7 100644 --- a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/ParseTreeEvaluator.java +++ b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/ParseTreeEvaluator.java @@ -37,7 +37,7 @@ public Object evaluate(ParseTree parseTree, Event event) { walker.walk(listener, parseTree); return listener.getResult(); } catch (final Exception e) { - LOG.error("Unable to evaluate event", e); + LOG.error(e.getMessage()); throw new ExpressionEvaluationException(e.getMessage(), e); } } diff --git a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/ParseTreeEvaluatorListener.java b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/ParseTreeEvaluatorListener.java index f3c5286b09..1592915990 100644 --- a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/ParseTreeEvaluatorListener.java +++ b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/ParseTreeEvaluatorListener.java @@ -123,8 +123,12 @@ public void exitEveryRule(ParserRuleContext ctx) { try { performSingleOperation(op, ctx); } catch (final Exception e) { - throw new ExpressionEvaluationException("Unable to evaluate the part of input statement: " + if (e instanceof IllegalArgumentException && op.isBooleanOperator()) { + operandStack.push(false); + } else { + throw new ExpressionEvaluationException("Unable to evaluate the part of input statement: " + getPartialStatementFromContext(ctx), e); + } } } } diff --git a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluatorTest.java b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluatorTest.java index b5685b8ed4..2a3419aa72 100644 --- a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluatorTest.java +++ b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluatorTest.java @@ -85,7 +85,7 @@ void testGivenParserThrowsExceptionThenExceptionThrown() { doThrow(new RuntimeException()).when(parser).parse(eq(statement)); - assertThrows(ExpressionEvaluationException.class, () -> statementEvaluator.evaluate(statement, null)); + assertThrows(ExpressionParsingException.class, () -> statementEvaluator.evaluate(statement, null)); verify(parser).parse(eq(statement)); verify(evaluator, times(0)).evaluate(any(), any()); @@ -100,7 +100,7 @@ void testGivenEvaluatorThrowsExceptionThenExceptionThrown() { doReturn(parseTree).when(parser).parse(eq(statement)); doThrow(new RuntimeException()).when(evaluator).evaluate(eq(parseTree), eq(event)); - assertThrows(ExpressionEvaluationException.class, () -> statementEvaluator.evaluateConditional(statement, event)); + assertThat(statementEvaluator.evaluateConditional(statement, event), equalTo(false)); verify(parser).parse(eq(statement)); verify(evaluator).evaluate(eq(parseTree), eq(event)); diff --git a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluator_ArithmeticIT.java b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluator_ArithmeticIT.java index e95a058b05..5975392461 100644 --- a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluator_ArithmeticIT.java +++ b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluator_ArithmeticIT.java @@ -108,6 +108,13 @@ void testArithmeticExpressionEvaluatorWithMultipleThreads(final String expressio } } + @ParameterizedTest + @MethodSource("exceptionExpressionSyntaxArguments") + void testArithmeticExpressionEvaluatorInvalidSyntax(final String expression, final Event event) { + final GenericExpressionEvaluator evaluator = applicationContext.getBean(GenericExpressionEvaluator.class); + assertThrows(ExpressionParsingException.class, () -> evaluator.evaluate(expression, event)); + } + @ParameterizedTest @MethodSource("exceptionExpressionArguments") void testArithmeticExpressionEvaluatorInvalidInput(final String expression, final Event event) { @@ -220,20 +227,30 @@ private static Stream invalidExpressionArguments() { ); } + private static Stream exceptionExpressionSyntaxArguments() { + Random random = new Random(); + int testStringLength = random.nextInt(10); + String testString = RandomStringUtils.randomAlphabetic(testStringLength); + return Stream.of( + Arguments.of("/status - ", event("{\"status\": 200, \"message\":\"msg\"}")), + Arguments.of("/status / ", event("{\"status\": 200, \"message\":\"msg\"}")), + Arguments.of(" * /status ", event("{\"status\": 200, \"message\":\"msg\"}")) + ); + } + private static Stream exceptionExpressionArguments() { Random random = new Random(); int testStringLength = random.nextInt(10); String testString = RandomStringUtils.randomAlphabetic(testStringLength); return Stream.of( + Arguments.of("/status + /message", event("{\"status\": 200, \"nomessage\":\"msg\"}")), + Arguments.of("/status - /message", event("{\"status\": 200, \"nomessage\":\"msg\"}")), // Can't mix Numbers and Strings when using operators Arguments.of("/status + /message", event("{\"status\": 200, \"message\":\"msg\"}")), Arguments.of("/status / /message", event("{\"status\": 200, \"message\":\"msg\"}")), Arguments.of("/message * /status", event("{\"status\": 200, \"message\":\"msg\"}")), Arguments.of("/message + /status", event("{\"status\": 200, \"message\":\"msg\"}")), Arguments.of("/status - /message", event("{\"status\": 200, \"message\":\"msg\"}")), - Arguments.of("/status - ", event("{\"status\": 200, \"message\":\"msg\"}")), - Arguments.of("/status / ", event("{\"status\": 200, \"message\":\"msg\"}")), - Arguments.of(" * /status ", event("{\"status\": 200, \"message\":\"msg\"}")), Arguments.of("/message - /status", event("{\"status\": 200, \"message\":\"msg\"}")), Arguments.of("-/message ", event("{\"status\": 200, \"message\":\"msg\"}")) ); diff --git a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluator_ConditionalIT.java b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluator_ConditionalIT.java index d4741c539a..f98546b4dd 100644 --- a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluator_ConditionalIT.java +++ b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluator_ConditionalIT.java @@ -34,8 +34,8 @@ import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.sameInstance; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.hamcrest.Matchers.equalTo; import static org.junit.jupiter.params.provider.Arguments.arguments; class GenericExpressionEvaluator_ConditionalIT { @@ -115,13 +115,21 @@ void testGenericExpressionEvaluatorWithMultipleThreads(final String expression, } @ParameterizedTest - @MethodSource("invalidExpressionArguments") + @MethodSource("invalidExpressionSyntaxArguments") void testGenericExpressionEvaluatorThrows(final String expression, final Event event) { final GenericExpressionEvaluator evaluator = applicationContext.getBean(GenericExpressionEvaluator.class); assertThrows(RuntimeException.class, () -> evaluator.evaluateConditional(expression, event)); } + @ParameterizedTest + @MethodSource("invalidExpressionArguments") + void testGenericExpressionEvaluatorWithInvalidData(final String expression, final Event event) { + final GenericExpressionEvaluator evaluator = applicationContext.getBean(GenericExpressionEvaluator.class); + + assertThat(evaluator.evaluateConditional(expression, event), equalTo(false)); + } + private static Stream validExpressionArguments() { final String key = "status_code"; final Long value = 200L; @@ -154,6 +162,9 @@ private static Stream validExpressionArguments() { arguments("/status_code == 200", event("{}"), false), arguments("/success == /status_code", event("{\"success\": true, \"status_code\": 200}"), false), arguments("/success != /status_code", event("{\"success\": true, \"status_code\": 200}"), true), + arguments("(/value == 10) or ((/status_code >= 300) and (/novalue == 15))", event("{\"status_code_not_present\": 200, \"value\" : 10}"), true), + arguments("(/status_code >= 300) or (/value == 10)", event("{\"status_code_not_present\": 200, \"value\" : 10}"), true), + arguments("not (/status_code >= 300)", event("{\"status_code_not_present\": 200}"), true), arguments("/part1@part2.part3 != 111", event("{\"success\": true, \"part1@part2.part3\":111, \"status_code\": 200}"), false), arguments("/part1.part2@part3 != 111", event("{\"success\": true, \"part1.part2@part3\":222, \"status_code\": 200}"), true), arguments("/pi == 3.14159", event("{\"pi\": 3.14159}"), true), @@ -259,8 +270,17 @@ private static Stream invalidExpressionArguments() { int testStringLength = random.nextInt(10); String testString = RandomStringUtils.randomAlphabetic(testStringLength); return Stream.of( - arguments("/missing", event("{}")), + arguments("not 5", event("{}")), + arguments("not null", event("{}")), + arguments("contains(\""+testTag2+"\")", tagEvent), + arguments("contains(/intField, /strField)", event("{\"intField\":1234,\"strField\":\"string\"}")), + arguments("/status_code >= 300", event("{\"status_code_not_present\": 200}")), + arguments("/status_code != null and /status_code >= 300", event("{\"status_code_not_present\": 200}")), + arguments("(/status_code >= 300) and (/value == 15)", event("{\"status_code2\": 200, \"value\" : 10}")), + arguments("/color in {\"blue\", 222.0, \"yellow\", \"green\"}", event("{\"color\": \"yellow\"}")), + arguments("length(\""+testString+"\") == "+testStringLength, event("{\"response\": \""+testString+"\"}")), arguments("/success < /status_code", event("{\"success\": true, \"status_code\": 200}")), + arguments("/status_code > 3", event("{\"success\": true, \"status_code_not_present\": 200}")), arguments("/success <= /status_code", event("{\"success\": true, \"status_code\": 200}")), arguments("/success > /status_code", event("{\"success\": true, \"status_code\": 200}")), arguments("/success >= /status_code", event("{\"success\": true, \"status_code\": 200}")), @@ -269,16 +289,37 @@ private static Stream invalidExpressionArguments() { arguments("/status_code < null", event("{\"success\": true, \"status_code\": 200}")), arguments("/status_code <= null", event("{\"success\": true, \"status_code\": 200}")), arguments("not /status_code", event("{\"status_code\": 200}")), - arguments("/status_code >= 200 and 3", event("{\"status_code\": 200}")), + arguments("cidrContains(/sourceIp)", event("{\"sourceIp\": \"192.0.2.3\"}")), + arguments("/status_code >= 200 and 3", event("{\"status_code\": 200}")) + ); + } + + + private static Stream invalidExpressionSyntaxArguments() { + Random random = new Random(); + + final String key = RandomStringUtils.randomAlphabetic(5); + final String value = RandomStringUtils.randomAlphabetic(10); + Map eventMap = Collections.singletonMap(key, value); + Event tagEvent = JacksonEvent.builder() + .withEventType("event") + .withData(eventMap) + .build(); + String testTag1 = RandomStringUtils.randomAlphabetic(6); + String testTag2 = RandomStringUtils.randomAlphabetic(7); + tagEvent.getMetadata().addTags(List.of(testTag1, testTag2)); + String testMetadataKey = RandomStringUtils.randomAlphabetic(5); + + int testStringLength = random.nextInt(10); + String testString = RandomStringUtils.randomAlphabetic(testStringLength); + return Stream.of( + arguments("/missing", event("{}")), arguments("", event("{}")), arguments("-false", event("{}")), - arguments("not 5", event("{}")), - arguments("not null", event("{}")), arguments("not/status_code", event("{\"status_code\": 200}")), arguments("trueand/status_code", event("{\"status_code\": 200}")), arguments("trueor/status_code", event("{\"status_code\": 200}")), arguments("length(\""+testString+") == "+testStringLength, event("{\"response\": \""+testString+"\"}")), - arguments("length(\""+testString+"\") == "+testStringLength, event("{\"response\": \""+testString+"\"}")), arguments("hasTags(10)", tagEvent), arguments("hasTags("+ testTag1+")", tagEvent), arguments("hasTags(\""+ testTag1+")", tagEvent), @@ -286,12 +327,9 @@ private static Stream invalidExpressionArguments() { arguments("hasTags(,\""+testTag2+"\")", tagEvent), arguments("hasTags(\""+testTag2+"\",)", tagEvent), arguments("contains(\""+testTag2+"\",)", tagEvent), - arguments("contains(\""+testTag2+"\")", tagEvent), - arguments("contains(/intField, /strField)", event("{\"intField\":1234,\"strField\":\"string\"}")), arguments("contains(1234, /strField)", event("{\"intField\":1234,\"strField\":\"string\"}")), arguments("contains(str, /strField)", event("{\"intField\":1234,\"strField\":\"string\"}")), arguments("contains(/strField, 1234)", event("{\"intField\":1234,\"strField\":\"string\"}")), - arguments("/color in {\"blue\", 222.0, \"yellow\", \"green\"}", event("{\"color\": \"yellow\"}")), arguments("/color in {\"blue, \"yellow\", \"green\"}", event("{\"color\": \"yellow\"}")), arguments("/color in {\"blue\", yellow\", \"green\"}", event("{\"color\": \"yellow\"}")), arguments("/color in {\", \"yellow\", \"green\"}", event("{\"color\": \"yellow\"}")), @@ -306,7 +344,6 @@ private static Stream invalidExpressionArguments() { arguments("getMetadata(10)", tagEvent), arguments("getMetadata("+ testMetadataKey+ ")", tagEvent), arguments("getMetadata(\""+ testMetadataKey+")", tagEvent), - arguments("cidrContains(/sourceIp)", event("{\"sourceIp\": \"192.0.2.3\"}")), arguments("cidrContains(/sourceIp,123)", event("{\"sourceIp\": \"192.0.2.3\"}")) ); } diff --git a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluator_ConditionalTest.java b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluator_ConditionalTest.java index e3bf6f35f2..2d229ecca8 100644 --- a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluator_ConditionalTest.java +++ b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluator_ConditionalTest.java @@ -16,6 +16,7 @@ import java.util.UUID; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; @@ -75,7 +76,7 @@ void testGivenParserThrowsExceptionThenExceptionThrown() { doThrow(new RuntimeException()).when(parser).parse(eq(statement)); - assertThrows(ExpressionEvaluationException.class, () -> statementEvaluator.evaluateConditional(statement, null)); + assertThrows(ExpressionParsingException.class, () -> statementEvaluator.evaluateConditional(statement, null)); verify(parser).parse(eq(statement)); verify(evaluator, times(0)).evaluate(any(), any()); @@ -90,7 +91,7 @@ void testGivenEvaluatorThrowsExceptionThenExceptionThrown() { doReturn(parseTree).when(parser).parse(eq(statement)); doThrow(new RuntimeException()).when(evaluator).evaluate(eq(parseTree), eq(event)); - assertThrows(ExpressionEvaluationException.class, () -> statementEvaluator.evaluateConditional(statement, event)); + assertThat(statementEvaluator.evaluateConditional(statement, event), equalTo(false)); verify(parser).parse(eq(statement)); verify(evaluator).evaluate(eq(parseTree), eq(event)); diff --git a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluator_MultiTypeIT.java b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluator_MultiTypeIT.java index 571c43ba92..06b3d7aa2f 100644 --- a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluator_MultiTypeIT.java +++ b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GenericExpressionEvaluator_MultiTypeIT.java @@ -111,6 +111,13 @@ void testMapExpressionEvaluatorWithMultipleThreads(final String expression, fina } } + @ParameterizedTest + @MethodSource("exceptionExpressionSyntaxArguments") + void testExpressionSyntaxEvaluatorCausesException(final String expression, final Event event) { + final GenericExpressionEvaluator evaluator = applicationContext.getBean(GenericExpressionEvaluator.class); + assertThrows(ExpressionParsingException.class, () -> evaluator.evaluate(expression, event)); + } + @ParameterizedTest @MethodSource("exceptionExpressionArguments") void testExpressionEvaluatorCausesException(final String expression, final Event event) { @@ -158,12 +165,19 @@ private static Stream validMapExpressionArguments() { ); } + private static Stream exceptionExpressionSyntaxArguments() { + return Stream.of( + Arguments.of("join()", event("{\"list\":[\"string\", 1, true]}")), + Arguments.of("contains()", event("{\"list\":[\"string\", 1, true]}")), + Arguments.of("startsWith()", event("{\"list\":[\"string\", 1, true]}")) + ); + } + private static Stream exceptionExpressionArguments() { return Stream.of( // Can't mix Numbers and Strings when using operators Arguments.of("/status + /message", event("{\"status\": 200, \"message\":\"msg\"}")), // Wrong number of arguments - Arguments.of("join()", event("{\"list\":[\"string\", 1, true]}")), Arguments.of("join(/list, \" \", \"third_arg\")", event("{\"list\":[\"string\", 1, true]}")) ); } diff --git a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeEvaluatorListenerTest.java b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeEvaluatorListenerTest.java index f0e1fdb9f4..047286f74a 100644 --- a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeEvaluatorListenerTest.java +++ b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeEvaluatorListenerTest.java @@ -11,6 +11,9 @@ import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.ParseTreeWalker; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.opensearch.dataprepper.expression.antlr.DataPrepperExpressionParser; import org.apache.commons.lang3.RandomStringUtils; @@ -19,6 +22,7 @@ import java.util.List; import java.util.Map; import java.util.Random; +import java.util.stream.Stream; import java.util.function.Function; import static org.hamcrest.CoreMatchers.equalTo; @@ -46,6 +50,12 @@ class ParseTreeEvaluatorListenerTest { operatorConfiguration.greaterThanOperator(), operatorConfiguration.greaterThanOrEqualOperator(), operatorConfiguration.lessThanOperator(), operatorConfiguration.lessThanOrEqualOperator(), operatorConfiguration.regexEqualOperator(), operatorConfiguration.regexNotEqualOperator(), + operatorConfiguration.typeOfOperator(), + operatorConfiguration.concatOperator(), + operatorConfiguration.addOperator(), + operatorConfiguration.subtractOperator(), + operatorConfiguration.multiplyOperator(), + operatorConfiguration.divideOperator(), new NotOperator() ); private final OperatorProvider operatorProvider = new OperatorProvider(operators); @@ -184,10 +194,10 @@ void testSimpleRelationalOperatorExpressionWithInValidLiteralType() { final String lessThanStatement = "1 < true"; final String lessThanOrEqualStatement = "1 <= true"; final Event testEvent = createTestEvent(new HashMap<>()); - assertThrows(ExpressionEvaluationException.class, () -> evaluateStatementOnEvent(greaterThanStatement, testEvent)); - assertThrows(ExpressionEvaluationException.class, () -> evaluateStatementOnEvent(greaterThanOrEqualStatement, testEvent)); - assertThrows(ExpressionEvaluationException.class, () -> evaluateStatementOnEvent(lessThanStatement, testEvent)); - assertThrows(ExpressionEvaluationException.class, () -> evaluateStatementOnEvent(lessThanOrEqualStatement, testEvent)); + assertThat(evaluateStatementOnEvent(greaterThanStatement, testEvent), is(false)); + assertThat(evaluateStatementOnEvent(greaterThanOrEqualStatement, testEvent), is(false)); + assertThat(evaluateStatementOnEvent(lessThanStatement, testEvent), is(false)); + assertThat(evaluateStatementOnEvent(lessThanOrEqualStatement, testEvent), is(false)); } @Test @@ -216,10 +226,10 @@ void testSimpleRelationalOperatorExpressionWithJsonPointerTypeInValidValueWithPo final String greaterThanOrEqualStatement = String.format(" /%s >= /%s", testKey, testKey); final String lessThanStatement = String.format(" /%s < %s", testKey, testValue); final String lessThanOrEqualStatement = String.format(" /%s <= /%s", testKey, testKey); - assertThrows(ExpressionEvaluationException.class, () -> evaluateStatementOnEvent(greaterThanStatement, testEvent)); - assertThrows(ExpressionEvaluationException.class, () -> evaluateStatementOnEvent(greaterThanOrEqualStatement, testEvent)); - assertThrows(ExpressionEvaluationException.class, () -> evaluateStatementOnEvent(lessThanStatement, testEvent)); - assertThrows(ExpressionEvaluationException.class, () -> evaluateStatementOnEvent(lessThanOrEqualStatement, testEvent)); + assertThat(evaluateStatementOnEvent(greaterThanStatement, testEvent), is(false)); + assertThat(evaluateStatementOnEvent(greaterThanOrEqualStatement, testEvent), is(false)); + assertThat(evaluateStatementOnEvent(lessThanStatement, testEvent), is(false)); + assertThat(evaluateStatementOnEvent(lessThanOrEqualStatement, testEvent), is(false)); } @Test @@ -236,8 +246,49 @@ void testSimpleConditionalOperatorExpressionWithInValidLiteralType() { final String andStatement = "1 and false"; final String orStatement = "true or 0"; final Event testEvent = createTestEvent(new HashMap<>()); - assertThrows(ExpressionEvaluationException.class, () -> evaluateStatementOnEvent(andStatement, testEvent)); - assertThrows(ExpressionEvaluationException.class, () -> evaluateStatementOnEvent(orStatement, testEvent)); + assertThat(evaluateStatementOnEvent(andStatement, testEvent), is(false)); + assertThat(evaluateStatementOnEvent(orStatement, testEvent), is(false)); + } + + @ParameterizedTest + @MethodSource("invalidExpressionArguments") + void testSimpleConditionalOperatorExpressionWithInValidExpression(final String statement) { + //final String statement = "((/field1 + 10) - (( 2 + /field2 ) + 5) - 10)"; + final Event testEvent = createTestEvent(new HashMap<>()); + assertThrows(ExpressionEvaluationException.class, () -> evaluateStatementOnEvent(statement, testEvent)); + } + + private static Stream invalidExpressionArguments() { + return Stream.of( + Arguments.of("(/field1 + 10) + ( 2 + /field2 )"), + Arguments.of("(/field1 * 10) * ( 2 * /field2 )"), + Arguments.of("(/field1 / 10) + ( 2 / /field2 )"), + Arguments.of("(/field1 - 10) - ( 2 - /field2 )") + ); + } + + @ParameterizedTest + @MethodSource("booleanExpressionsGeneratingExceptions") + void testSimpleConditionalOperatorExpressionWithMissingField(final String statement, final boolean expectedResult) { + final String testKey = "testKey"; + final int testValue = 1; + final Map data = Map.of(testKey, testValue); + final Event testEvent = createTestEvent(data); + assertThat(evaluateStatementOnEvent(statement, testEvent), is(expectedResult)); + } + + private static Stream booleanExpressionsGeneratingExceptions() { + return Stream.of( + Arguments.of( "(/field1 > 1) or (/field2 > 2)", false), + Arguments.of( "(/field1 < 1) or (/field2 < 2)", false), + Arguments.of( "(/testKey < \"two\") or (2 == 2)", true), + Arguments.of( "(/testKey < \"two\") or (2)", false), + Arguments.of( "(/testKey) or (2 == 2)", false), + Arguments.of( "not (/testKey)", false), + Arguments.of( "(/testKey < \"two\") and (2)", false), + Arguments.of( "(/testKey) and (2 == 2)", false), + Arguments.of( "(/testKey < \"two\") and (2 == 2)", false) + ); } @Test @@ -260,8 +311,8 @@ void testSimpleConditionalOperatorExpressionWithJsonPointerTypeInValidValue() { final Event testEvent = createTestEvent(data); final String andStatement = String.format("/%s and false", testKey); final String orStatement = String.format("/%s or false", testKey); - assertThrows(ExpressionEvaluationException.class, () -> evaluateStatementOnEvent(andStatement, testEvent)); - assertThrows(ExpressionEvaluationException.class, () -> evaluateStatementOnEvent(orStatement, testEvent)); + assertThat(evaluateStatementOnEvent(andStatement, testEvent), is(false)); + assertThat(evaluateStatementOnEvent(orStatement, testEvent), is(false)); } @Test @@ -275,7 +326,7 @@ void testSimpleNotOperatorExpressionWithValidLiteralType() { void testSimpleNotOperatorExpressionWithInValidLiteralType() { final String notStatement = "not 1"; final Event testEvent = createTestEvent(new HashMap<>()); - assertThrows(ExpressionEvaluationException.class, () -> evaluateStatementOnEvent(notStatement, testEvent)); + assertThat(evaluateStatementOnEvent(notStatement, testEvent), is(false)); } @Test @@ -295,7 +346,7 @@ void testSimpleNotOperatorExpressionWithJsonPointerTypeInValidValue() { final Map data = Map.of(testKey, testValue); final String notStatement = String.format("not /%s", testKey); final Event testEvent = createTestEvent(data); - assertThrows(ExpressionEvaluationException.class, () -> evaluateStatementOnEvent(notStatement, testEvent)); + assertThat(evaluateStatementOnEvent(notStatement, testEvent), is(false)); } @Test @@ -305,10 +356,10 @@ void testMultipleOperatorsExpressionNotPriorToRelational() { final String notPriorToGreaterThanOrEqualStatement = "not 1 >= 1"; final String notPriorToLessThanStatement = "not 2 < 1"; final String notPriorToLessThanOrEqualStatement = "not 1 <= 1"; - assertThrows(ExpressionEvaluationException.class, () -> evaluateStatementOnEvent(notPriorToGreaterThanStatement, testEvent)); - assertThrows(ExpressionEvaluationException.class, () -> evaluateStatementOnEvent(notPriorToGreaterThanOrEqualStatement, testEvent)); - assertThrows(ExpressionEvaluationException.class, () -> evaluateStatementOnEvent(notPriorToLessThanStatement, testEvent)); - assertThrows(ExpressionEvaluationException.class, () -> evaluateStatementOnEvent(notPriorToLessThanOrEqualStatement, testEvent)); + assertThat(evaluateStatementOnEvent(notPriorToGreaterThanStatement, testEvent), is(false)); + assertThat(evaluateStatementOnEvent(notPriorToGreaterThanOrEqualStatement, testEvent), is(false)); + assertThat(evaluateStatementOnEvent(notPriorToLessThanStatement, testEvent), is(false)); + assertThat(evaluateStatementOnEvent(notPriorToLessThanOrEqualStatement, testEvent), is(false)); } @Test diff --git a/data-prepper-plugins/mutate-event-processors/src/main/java/org/opensearch/dataprepper/plugins/processor/mutateevent/AddEntryProcessor.java b/data-prepper-plugins/mutate-event-processors/src/main/java/org/opensearch/dataprepper/plugins/processor/mutateevent/AddEntryProcessor.java index 321d4eebdc..50d020ee58 100644 --- a/data-prepper-plugins/mutate-event-processors/src/main/java/org/opensearch/dataprepper/plugins/processor/mutateevent/AddEntryProcessor.java +++ b/data-prepper-plugins/mutate-event-processors/src/main/java/org/opensearch/dataprepper/plugins/processor/mutateevent/AddEntryProcessor.java @@ -102,7 +102,6 @@ public Collection> doExecute(final Collection> recor .addArgument(entry.getValueExpression()) .addArgument(entry.getFormat()) .addArgument(entry.getValue()) - .setCause(e) .log(); } }