diff --git a/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionLexer.g b/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionLexer.g index fb3958c0ad..d1b22e92c0 100644 --- a/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionLexer.g +++ b/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionLexer.g @@ -107,6 +107,7 @@ IP : 'ip'; UUID : 'UUID'; HOSTNAME : 'hostname'; // requires boolean arg: prefer FQDN NOW : 'now'; +THREAD : 'thread'; // 0 arg functions diff --git a/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionParser.g b/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionParser.g index 4d48ee093f..0c63c553ce 100644 --- a/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionParser.g +++ b/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionParser.g @@ -128,7 +128,7 @@ functionCall : functionRef -> ^(FUNCTION_CALL functionRef); booleanLiteral : TRUE | FALSE; -zeroArgStandaloneFunction : (IP | UUID | NOW | NEXT_INT | HOSTNAME | RANDOM) LPAREN! RPAREN!; +zeroArgStandaloneFunction : (IP | UUID | NOW | NEXT_INT | HOSTNAME | THREAD | RANDOM) LPAREN! RPAREN!; oneArgStandaloneFunction : ((TO_LITERAL | MATH | GET_STATE_VALUE)^ LPAREN! anyArg RPAREN!) | (HOSTNAME^ LPAREN! booleanLiteral RPAREN!); standaloneFunction : zeroArgStandaloneFunction | oneArgStandaloneFunction; diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/compile/ExpressionCompiler.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/compile/ExpressionCompiler.java index 4a4a204074..de4333c179 100644 --- a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/compile/ExpressionCompiler.java +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/compile/ExpressionCompiler.java @@ -91,6 +91,7 @@ import org.apache.nifi.attribute.expression.language.evaluation.functions.Substr import org.apache.nifi.attribute.expression.language.evaluation.functions.SubstringBeforeEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.SubstringBeforeLastEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.SubstringEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.functions.ThreadEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.ToLowerEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.ToRadixEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.ToStringEvaluator; @@ -199,6 +200,7 @@ import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpre import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.SUBSTRING_AFTER_LAST; import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.SUBSTRING_BEFORE; import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.SUBSTRING_BEFORE_LAST; +import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.THREAD; import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.TO_DATE; import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.TO_DECIMAL; import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.TO_LITERAL; @@ -1009,6 +1011,8 @@ public class ExpressionCompiler { throw new AttributeExpressionLanguageException(e); } } + case THREAD: + return addToken(new ThreadEvaluator(), "thread"); case HOSTNAME: { if (tree.getChildCount() == 0) { try { diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/ThreadEvaluator.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/ThreadEvaluator.java new file mode 100644 index 0000000000..4ebfbe518a --- /dev/null +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/ThreadEvaluator.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.attribute.expression.language.evaluation.functions; + +import java.util.Map; + +import org.apache.nifi.attribute.expression.language.evaluation.Evaluator; +import org.apache.nifi.attribute.expression.language.evaluation.QueryResult; +import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.StringQueryResult; + +public class ThreadEvaluator extends StringEvaluator { + + @Override + public QueryResult evaluate(final Map attributes) { + // See org.apache.nifi.engine.FlowEngine + return new StringQueryResult(Thread.currentThread().getName()); + } + + @Override + public Evaluator getSubjectEvaluator() { + return null; + } + +} diff --git a/nifi-commons/nifi-expression-language/src/test/java/org/apache/nifi/attribute/expression/language/TestQuery.java b/nifi-commons/nifi-expression-language/src/test/java/org/apache/nifi/attribute/expression/language/TestQuery.java index 5b368135eb..67e5b511db 100644 --- a/nifi-commons/nifi-expression-language/src/test/java/org/apache/nifi/attribute/expression/language/TestQuery.java +++ b/nifi-commons/nifi-expression-language/src/test/java/org/apache/nifi/attribute/expression/language/TestQuery.java @@ -1810,6 +1810,11 @@ public class TestQuery { verifyEquals("${literal(true):ifElse(false, 'b')}", attributes, "false"); } + @Test + public void testThread() { + final Map attributes = new HashMap<>(); + verifyEquals("${thread()}", attributes, "main"); + } private void verifyEquals(final String expression, final Map attributes, final Object expectedResult) { verifyEquals(expression,attributes, null, expectedResult); diff --git a/nifi-docs/src/main/asciidoc/expression-language-guide.adoc b/nifi-docs/src/main/asciidoc/expression-language-guide.adoc index 3ade4bba05..70b2802a81 100644 --- a/nifi-docs/src/main/asciidoc/expression-language-guide.adoc +++ b/nifi-docs/src/main/asciidoc/expression-language-guide.adoc @@ -2062,6 +2062,24 @@ names begin with the letter `a`. *Examples*: UpdateAttribute processor has stored the key "count" with value "20" in state. '${getStateValue("count")}` returns `20`. + + +[.function] +=== thread + +*Description*: [.description]#Returns the name of the thread used by the processor when evaluating the Expression. This can be useful + when using a processor with multiple concurrent tasks and where some data uniqueness is required.# + +*Subject Type*: [.subjectless]#No Subject# + +*Arguments*: No arguments + +*Return Type*: [.returnType]#String# + +*Examples*: `${thread()}` could return something like `Timer-Driven Process Thread-4`. + + + [[multi]] == Evaluating Multiple Attributes