diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/execute/AbstractExecution.java b/geode-core/src/main/java/org/apache/geode/internal/cache/execute/AbstractExecution.java
index 73c02c405545..ef74ada2d5fd 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/execute/AbstractExecution.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/execute/AbstractExecution.java
@@ -22,9 +22,12 @@
import java.util.concurrent.TimeUnit;
import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.MarkerManager;
import org.apache.geode.InternalGemFireException;
import org.apache.geode.SystemFailure;
+import org.apache.geode.annotations.Immutable;
import org.apache.geode.annotations.internal.MakeNotStatic;
import org.apache.geode.cache.LowMemoryException;
import org.apache.geode.cache.TransactionException;
@@ -55,6 +58,9 @@
*/
public abstract class AbstractExecution implements InternalExecution {
private static final Logger logger = LogService.getLogger();
+ @Immutable
+ private static final Marker functionExceptionMarker =
+ MarkerManager.getMarker("FUNCTION_EXCEPTION_MARKER");
public static final int DEFAULT_CLIENT_FUNCTION_TIMEOUT = 0;
private static final String CLIENT_FUNCTION_TIMEOUT_SYSTEM_PROPERTY =
@@ -504,7 +510,8 @@ private void handleException(Throwable functionException, final Function fn,
((InternalResultSender) sender).setException(functionException);
}
} else {
- logger.warn("Exception occurred on local node while executing Function:",
+ logger.warn(functionException instanceof FunctionException ? functionExceptionMarker : null,
+ "Exception occurred on local node while executing Function:",
functionException);
}
}
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/execute/DistributedRegionFunctionResultSender.java b/geode-core/src/main/java/org/apache/geode/internal/cache/execute/DistributedRegionFunctionResultSender.java
index 5ab445b20ae1..afd2083e5b8e 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/execute/DistributedRegionFunctionResultSender.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/execute/DistributedRegionFunctionResultSender.java
@@ -15,7 +15,10 @@
package org.apache.geode.internal.cache.execute;
import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.MarkerManager;
+import org.apache.geode.annotations.Immutable;
import org.apache.geode.cache.execute.Function;
import org.apache.geode.cache.execute.FunctionException;
import org.apache.geode.cache.execute.ResultCollector;
@@ -29,6 +32,9 @@
public class DistributedRegionFunctionResultSender implements InternalResultSender {
private static final Logger logger = LogService.getLogger();
+ @Immutable
+ private static final Marker functionExceptionMarker =
+ MarkerManager.getMarker("FUNCTION_EXCEPTION_MARKER");
DistributedRegionFunctionStreamingMessage msg = null;
@@ -224,7 +230,8 @@ public void setException(Throwable exception) {
} else {
((LocalResultCollector) rc).setException(exception);
// this.lastResult(exception);
- logger.info("Unexpected exception during function execution on local node Distributed Region",
+ logger.info(exception instanceof FunctionException ? functionExceptionMarker : null,
+ "Unexpected exception during function execution on local node Distributed Region",
exception);
}
rc.endResults();
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/execute/MemberFunctionResultSender.java b/geode-core/src/main/java/org/apache/geode/internal/cache/execute/MemberFunctionResultSender.java
index 64de9a36c5e7..eb2c15fde071 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/execute/MemberFunctionResultSender.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/execute/MemberFunctionResultSender.java
@@ -16,7 +16,10 @@
package org.apache.geode.internal.cache.execute;
import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.MarkerManager;
+import org.apache.geode.annotations.Immutable;
import org.apache.geode.cache.execute.Function;
import org.apache.geode.cache.execute.FunctionException;
import org.apache.geode.cache.execute.ResultCollector;
@@ -31,6 +34,9 @@
public class MemberFunctionResultSender implements InternalResultSender {
private static final Logger logger = LogService.getLogger();
+ @Immutable
+ private static final Marker functionExceptionMarker =
+ MarkerManager.getMarker("FUNCTION_EXCEPTION_MARKER");
MemberFunctionStreamingMessage msg = null;
@@ -232,7 +238,8 @@ public void sendException(Throwable exception) {
public void setException(Throwable exception) {
((LocalResultCollector) rc).setException(exception);
// this.lastResult(exception);
- logger.info("Unexpected exception during function execution local member",
+ logger.info(exception instanceof FunctionException ? functionExceptionMarker : null,
+ "Unexpected exception during function execution local member",
exception);
rc.endResults();
localLastResultReceived = true;
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/execute/PartitionedRegionFunctionResultSender.java b/geode-core/src/main/java/org/apache/geode/internal/cache/execute/PartitionedRegionFunctionResultSender.java
index 69a0450294a7..3e2fd5d1fcd6 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/execute/PartitionedRegionFunctionResultSender.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/execute/PartitionedRegionFunctionResultSender.java
@@ -17,7 +17,10 @@
import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.MarkerManager;
+import org.apache.geode.annotations.Immutable;
import org.apache.geode.cache.execute.Function;
import org.apache.geode.cache.execute.FunctionException;
import org.apache.geode.cache.execute.ResultCollector;
@@ -42,6 +45,9 @@
public class PartitionedRegionFunctionResultSender implements InternalResultSender {
private static final Logger logger = LogService.getLogger();
+ @Immutable
+ private static final Marker functionExceptionMarker =
+ MarkerManager.getMarker("FUNCTION_EXCEPTION_MARKER");
PartitionedRegionFunctionStreamingMessage msg = null;
@@ -390,7 +396,8 @@ public void setException(Throwable exception) {
serverSender.setException(exception);
} else {
((LocalResultCollector) rc).setException(exception);
- logger.info("Unexpected exception during function execution on local node Partitioned Region",
+ logger.info(exception instanceof FunctionException ? functionExceptionMarker : null,
+ "Unexpected exception during function execution on local node Partitioned Region",
exception);
}
rc.endResults();
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/execute/ServerToClientFunctionResultSender.java b/geode-core/src/main/java/org/apache/geode/internal/cache/execute/ServerToClientFunctionResultSender.java
index 8f49951fb90c..decd8db5eeb1 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/execute/ServerToClientFunctionResultSender.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/execute/ServerToClientFunctionResultSender.java
@@ -20,7 +20,10 @@
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.MarkerManager;
+import org.apache.geode.annotations.Immutable;
import org.apache.geode.cache.execute.Function;
import org.apache.geode.cache.execute.FunctionException;
import org.apache.geode.cache.execute.ResultSender;
@@ -37,6 +40,9 @@
public class ServerToClientFunctionResultSender implements ResultSender {
private static final Logger logger = LogService.getLogger();
+ @Immutable
+ private static final Marker functionExceptionMarker =
+ MarkerManager.getMarker("FUNCTION_EXCEPTION_MARKER");
protected ChunkedMessage msg = null;
@@ -321,9 +327,9 @@ public synchronized void setException(Throwable exception) {
}
String exceptionMessage = exception.getMessage() != null ? exception.getMessage()
: "Exception occurred during function execution";
- logger.warn(String.format("Exception on server while executing function : %s",
- fn),
- exception);
+ logger.warn(exception instanceof FunctionException ? functionExceptionMarker : null,
+ "Exception on server while executing function : {}", fn, exception);
+
if (logger.isDebugEnabled()) {
logger.debug("ServerToClientFunctionResultSender sending Function Exception : ");
}
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/BaseCommand.java b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/BaseCommand.java
index 9566723f7435..dc109901bbc6 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/BaseCommand.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/BaseCommand.java
@@ -34,6 +34,8 @@
import java.util.regex.Pattern;
import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.MarkerManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -88,6 +90,9 @@
public abstract class BaseCommand implements Command {
protected static final Logger logger = LogService.getLogger();
+ @Immutable
+ protected static final Marker functionExceptionMarker =
+ MarkerManager.getMarker("FUNCTION_EXCEPTION_MARKER");
@Immutable
private static final byte[] OK_BYTES = new byte[] {0};
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteFunction70.java b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteFunction70.java
index 53795fb1896c..cc11c0e130f8 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteFunction70.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteFunction70.java
@@ -431,6 +431,10 @@ private void executeFunctionLocally(final Function fn, final FunctionContext cx,
if (logger.isDebugEnabled()) {
logger.debug("Exception on server while executing function: {}", fn, e);
}
+ } catch (FunctionException e) {
+ stats.endFunctionExecutionWithException(startExecution, fn.hasResult());
+ logger.warn(functionExceptionMarker, "Exception on server while executing function: {}",
+ fn, e);
} catch (Exception e) {
stats.endFunctionExecutionWithException(startExecution, fn.hasResult());
logger.warn("Exception on server while executing function: {}", fn, e);
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteRegionFunction66.java b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteRegionFunction66.java
index 80f6cfb636d2..ffe701674475 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteRegionFunction66.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteRegionFunction66.java
@@ -220,9 +220,9 @@ public void cmdExecute(final @NotNull Message clientMessage,
resultSender.setException(fe);
} else {
if (setLastResultReceived(resultSender)) {
- logger.warn(String.format("Exception on server while executing function : %s",
- function),
- fe);
+ logger.warn(functionExceptionMarker,
+ "Exception on server while executing function : {}",
+ function, fe);
sendException(hasResult, clientMessage, message, serverConnection, fe);
}
}
diff --git a/geode-docs/developing/function_exec/function_execution.html.md.erb b/geode-docs/developing/function_exec/function_execution.html.md.erb
index 9542daab1390..82289ad73ead 100644
--- a/geode-docs/developing/function_exec/function_execution.html.md.erb
+++ b/geode-docs/developing/function_exec/function_execution.html.md.erb
@@ -57,7 +57,7 @@ See [Authorization of Function Execution](../../managing/security/implementing_a
- For partitioned regions, the `PartitionRegionHelper` provides access to additional information and data for the region. For single regions, use `getLocalDataForContext`. For colocated regions, use `getLocalColocatedRegions`.
**Note:**
When you use `PartitionRegionHelper.getLocalDataForContext`, `putIfAbsent` may not return expected results if you are working on local data set instead of the region.
- 4. To propagate an error condition or exception back to the caller of the function, throw a FunctionException from the `execute` method. <%=vars.product_name%> transmits the exception back to the caller as if it had been thrown on the calling side. See the Java API documentation for [FunctionException](/releases/latest/javadoc/org/apache/geode/cache/execute/FunctionException.html) for more information.
+ 4. To propagate an error condition or exception back to the caller of the function, throw a FunctionException from the `execute` method. <%=vars.product_name%> transmits the exception back to the caller as if it had been thrown on the calling side. See the Java API documentation for [FunctionException](/releases/latest/javadoc/org/apache/geode/cache/execute/FunctionException.html) for more information. Note, FunctionException logging on server side can be disabled by the Log4j filter for marker FUNCTION\_EXCEPTION\_MARKER. See [Advanced Users—Configuring Log4j 2 for <%=vars.product_name%>](../../managing/logging/configuring_log4j2.html) for more details.
Example function code:
diff --git a/geode-docs/managing/logging/configuring_log4j2.html.md.erb b/geode-docs/managing/logging/configuring_log4j2.html.md.erb
index 460af7992f4e..ad0bc5923cd9 100644
--- a/geode-docs/managing/logging/configuring_log4j2.html.md.erb
+++ b/geode-docs/managing/logging/configuring_log4j2.html.md.erb
@@ -64,6 +64,11 @@ Custom Log4j 2 configuration in <%=vars.product_name%> comes with some caveats a
You can enable the GEODE\_VERBOSE log statements by changing `onMatch="DENY"` to `onMatch="ACCEPT"`. Typically, it's more useful to simply enable DEBUG or TRACE on certain classes or packages instead of for the entire <%=vars.product_name%> product. However, this setting can be used for internal debugging purposes if all other debugging methods fail.
- The usage of filters can have an impact on performance. <%=vars.product_name%> has some logging optimizations that are deactivated when filters are used (except for the GEODE_VERBOSE marker mentioned previously).
+- The FUNCTION\_EXCEPTION\_MARKER marker (Log4J2 Marker) can be used to disable FunctionException logs on server side during function execution. For example <%=vars.product_name%> `log4j2.xml` filter disables FunctionException logs with this line:
+
+ ``` pre
+
+ ```
- Geode's custom Log4j 2 Appenders can be used in a custom log4j2.xml. This requires:
diff --git a/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/functions/UserFunctionExecution.java b/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/functions/UserFunctionExecution.java
index d3bdd1d242f9..321058617350 100644
--- a/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/functions/UserFunctionExecution.java
+++ b/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/functions/UserFunctionExecution.java
@@ -28,13 +28,17 @@
import java.util.stream.Collectors;
import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.MarkerManager;
import org.apache.shiro.subject.Subject;
+import org.apache.geode.annotations.Immutable;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.execute.Execution;
import org.apache.geode.cache.execute.Function;
import org.apache.geode.cache.execute.FunctionContext;
+import org.apache.geode.cache.execute.FunctionException;
import org.apache.geode.cache.execute.FunctionService;
import org.apache.geode.cache.execute.ResultCollector;
import org.apache.geode.cache.query.RegionNotFoundException;
@@ -55,6 +59,10 @@
public class UserFunctionExecution implements InternalFunction