Repository: networknt/json-schema-validator
Pull request #1054 (2024-06-09 03:45:32)

Optimize logging by creating a debug flag
This creates a `debugEnabled` flag in `ExecutionConfig` that is checked to determine if the debug logs should be generated. This is a performance optimization as it was noticed during profiling that since this `debug` function runs very frequently during validation execution the time taken just to determine if the logger is enabled is significant.

codecov-commenter: ## [Codecov](https://app.codecov.io/gh/networknt/json-schema-validator/pull/1054?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=networknt) Report
Attention: Patch coverage is `79.68750%` with `13 lines` in your changes missing coverage. Please review.
> Project coverage is 78.60%. Comparing base [(`48ca3c2`)](https://app.codecov.io/gh/networknt/json-schema-validator/commit/48ca3c22995e32797e9defdb8b77869f0d15caf3?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=networknt) to head [(`81dbbc7`)](https://app.codecov.io/gh/networknt/json-schema-validator/commit/81dbbc7528d85198305a060b6f48973980624fa8?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=networknt).
> Report is 21 commits behind head on master.

| [Files](https://app.codecov.io/gh/networknt/json-schema-validator/pull/1054?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=networknt) | Patch % | Lines |
|---|---|---|
| [...n/java/com/networknt/schema/BaseJsonValidator.java](https://app.codecov.io/gh/networknt/json-schema-validator/pull/1054?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Fcom%2Fnetworknt%2Fschema%2FBaseJsonValidator.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=networknt#diff-c3JjL21haW4vamF2YS9jb20vbmV0d29ya250L3NjaGVtYS9CYXNlSnNvblZhbGlkYXRvci5qYXZh) | 0.00% | [9 Missing and 1 partial :warning: ](https://app.codecov.io/gh/networknt/json-schema-validator/pull/1054?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=networknt) |
| [...ain/java/com/networknt/schema/ExecutionConfig.java](https://app.codecov.io/gh/networknt/json-schema-validator/pull/1054?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Fcom%2Fnetworknt%2Fschema%2FExecutionConfig.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=networknt#diff-c3JjL21haW4vamF2YS9jb20vbmV0d29ya250L3NjaGVtYS9FeGVjdXRpb25Db25maWcuamF2YQ==) | 50.00% | [2 Missing :warning: ](https://app.codecov.io/gh/networknt/json-schema-validator/pull/1054?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=networknt) |
| [...java/com/networknt/schema/DynamicRefValidator.java](https://app.codecov.io/gh/networknt/json-schema-validator/pull/1054?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Fcom%2Fnetworknt%2Fschema%2FDynamicRefValidator.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=networknt#diff-c3JjL21haW4vamF2YS9jb20vbmV0d29ya250L3NjaGVtYS9EeW5hbWljUmVmVmFsaWRhdG9yLmphdmE=) | 50.00% | [1 Missing :warning: ](https://app.codecov.io/gh/networknt/json-schema-validator/pull/1054?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=networknt) |

:exclamation: Your organization needs to install the [Codecov GitHub app](https://github.com/apps/codecov/installations/select_target) to enable full functionality.

<details><summary>Additional details and impacted files</summary>


```diff
@@             Coverage Diff              @@
##             master    #1054      +/-   ##
============================================
- Coverage     78.90%   78.60%   -0.30%     
- Complexity     1965     2034      +69     
============================================
  Files           172      191      +19     
  Lines          6352     6609     +257     
  Branches       1255     1260       +5     
============================================
+ Hits           5012     5195     +183     
- Misses          867      938      +71     
- Partials        473      476       +3     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/networknt/json-schema-validator/pull/1054?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=networknt).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=networknt).


Patch:
diff --git a/README.md b/README.md
index 6e0323d..8c6c090 100644
--- a/README.md
+++ b/README.md
@@ -510,6 +510,7 @@ The following is sample output from the Hierarchical format.
 | `locale`                       | The locale to use for generating messages in the `ValidationMessage`. Note that this value is copied from `SchemaValidatorsConfig` for each execution.                                                                            | `Locale.getDefault()`
 | `failFast`                     | Whether to return failure immediately when an assertion is generated. Note that this value is copied from `SchemaValidatorsConfig` for each execution but is automatically set to `true` for the Boolean and Flag output formats. | `false`
 | `formatAssertionsEnabled`      | The default is to generate format assertions from Draft 4 to Draft 7 and to only generate annotations from Draft 2019-09. Setting to `true` or `false` will override the default behavior.                                        | `null`
+| `debugEnabled`                 | Controls whether debug logging is enabled for logging the node information when processing. Note that this will generate a lot of logs that will affect performance.                                                              | `false`
 
 ### Schema Validators Configuration
 
diff --git a/src/main/java/com/networknt/schema/AdditionalPropertiesValidator.java b/src/main/java/com/networknt/schema/AdditionalPropertiesValidator.java
index 01fb252..d2c21f9 100644
--- a/src/main/java/com/networknt/schema/AdditionalPropertiesValidator.java
+++ b/src/main/java/com/networknt/schema/AdditionalPropertiesValidator.java
@@ -88,7 +88,7 @@ public class AdditionalPropertiesValidator extends BaseJsonValidator {
 
     protected Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode,
             JsonNodePath instanceLocation, boolean walk) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
         if (!node.isObject()) {
             // ignore no object
             return Collections.emptySet();
diff --git a/src/main/java/com/networknt/schema/AllOfValidator.java b/src/main/java/com/networknt/schema/AllOfValidator.java
index 2d0e09d..884930c 100644
--- a/src/main/java/com/networknt/schema/AllOfValidator.java
+++ b/src/main/java/com/networknt/schema/AllOfValidator.java
@@ -56,7 +56,7 @@ public class AllOfValidator extends BaseJsonValidator {
     }
 
     protected Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation, boolean walk) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         SetView<ValidationMessage> childSchemaErrors = null;
 
diff --git a/src/main/java/com/networknt/schema/AnyOfValidator.java b/src/main/java/com/networknt/schema/AnyOfValidator.java
index ba31050..5e9773b 100644
--- a/src/main/java/com/networknt/schema/AnyOfValidator.java
+++ b/src/main/java/com/networknt/schema/AnyOfValidator.java
@@ -60,7 +60,7 @@ public class AnyOfValidator extends BaseJsonValidator {
 
     protected Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode,
             JsonNodePath instanceLocation, boolean walk) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         if (this.validationContext.getConfig().isOpenAPI3StyleDiscriminators()) {
             executionContext.enterDiscriminatorContext(new DiscriminatorContext(), instanceLocation);
diff --git a/src/main/java/com/networknt/schema/BaseJsonValidator.java b/src/main/java/com/networknt/schema/BaseJsonValidator.java
index eebcd9c..9576e6e 100644
--- a/src/main/java/com/networknt/schema/BaseJsonValidator.java
+++ b/src/main/java/com/networknt/schema/BaseJsonValidator.java
@@ -96,8 +96,23 @@ public abstract class BaseJsonValidator extends ValidationMessageHandler impleme
         return Math.abs(n1 - n2) < 1e-12;
     }
 
-    protected static void debug(Logger logger, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        logger.debug("validate( {}, {}, {})", node, rootNode, instanceLocation);
+    public static void debug(Logger logger, ExecutionContext executionContext, JsonNode node, JsonNode rootNode,
+            JsonNodePath instanceLocation) {
+        //logger.debug("validate( {}, {}, {})", node, rootNode, instanceLocation);
+        // The below is equivalent to the above but as there are more than 2 arguments
+        // the var-arg method is used and an array needs to be allocated even if debug
+        // is not enabled
+        if (executionContext.getExecutionConfig().isDebugEnabled() && logger.isDebugEnabled()) {
+            StringBuilder builder = new StringBuilder();
+            builder.append("validate( ");
+            builder.append(node.toString());
+            builder.append(", ");
+            builder.append(rootNode.toString());
+            builder.append(", ");
+            builder.append(instanceLocation.toString());
+            builder.append(")");
+            logger.debug(builder.toString());
+        }
     }
 
     /**
diff --git a/src/main/java/com/networknt/schema/CachedSupplier.java b/src/main/java/com/networknt/schema/CachedSupplier.java
index 109f36c..4411bdd 100644
--- a/src/main/java/com/networknt/schema/CachedSupplier.java
+++ b/src/main/java/com/networknt/schema/CachedSupplier.java
@@ -23,8 +23,8 @@ import java.util.function.Supplier;
  * @param <T> the type cached
  */
 public class CachedSupplier<T> implements Supplier<T> {
-    private final Supplier<T> delegate;
-    private T cache = null;
+    private volatile Supplier<T> delegate;
+    private volatile T cache = null;
 
     public CachedSupplier(Supplier<T> delegate) {
         this.delegate = delegate;
@@ -32,10 +32,16 @@ public class CachedSupplier<T> implements Supplier<T> {
 
     @Override
     public T get() {
-        if (cache == null) {
-            cache = delegate.get();
+        if (this.delegate == null) {
+            return this.cache;
         }
-        return cache;
-    }
 
+        synchronized(this) {
+            if (this.delegate != null) {
+                this.cache = this.delegate.get();
+                this.delegate = null;
+            }
+        }
+        return this.cache;
+    }
 }
diff --git a/src/main/java/com/networknt/schema/ConstValidator.java b/src/main/java/com/networknt/schema/ConstValidator.java
index 291144b..4d5e92d 100644
--- a/src/main/java/com/networknt/schema/ConstValidator.java
+++ b/src/main/java/com/networknt/schema/ConstValidator.java
@@ -34,7 +34,7 @@ public class ConstValidator extends BaseJsonValidator implements JsonValidator {
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         if (schemaNode.isNumber() && node.isNumber()) {
             if (schemaNode.decimalValue().compareTo(node.decimalValue()) != 0) {
diff --git a/src/main/java/com/networknt/schema/ContainsValidator.java b/src/main/java/com/networknt/schema/ContainsValidator.java
index 1ef0199..adcdcde 100644
--- a/src/main/java/com/networknt/schema/ContainsValidator.java
+++ b/src/main/java/com/networknt/schema/ContainsValidator.java
@@ -72,7 +72,7 @@ public class ContainsValidator extends BaseJsonValidator {
 
     @Override
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         // ignores non-arrays
         Set<ValidationMessage> results = null;
diff --git a/src/main/java/com/networknt/schema/ContentEncodingValidator.java b/src/main/java/com/networknt/schema/ContentEncodingValidator.java
index 11e79ea..6f2bbbb 100644
--- a/src/main/java/com/networknt/schema/ContentEncodingValidator.java
+++ b/src/main/java/com/networknt/schema/ContentEncodingValidator.java
@@ -66,7 +66,7 @@ public class ContentEncodingValidator extends BaseJsonValidator {
     @Override
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode,
             JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         // Ignore non-strings
         JsonType nodeType = TypeFactory.getValueNodeType(node, this.validationContext.getConfig());
diff --git a/src/main/java/com/networknt/schema/ContentMediaTypeValidator.java b/src/main/java/com/networknt/schema/ContentMediaTypeValidator.java
index f4dd194..28e435b 100644
--- a/src/main/java/com/networknt/schema/ContentMediaTypeValidator.java
+++ b/src/main/java/com/networknt/schema/ContentMediaTypeValidator.java
@@ -90,7 +90,7 @@ public class ContentMediaTypeValidator extends BaseJsonValidator {
     @Override
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode,
             JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         // Ignore non-strings
         JsonType nodeType = TypeFactory.getValueNodeType(node, this.validationContext.getConfig());
diff --git a/src/main/java/com/networknt/schema/DependenciesValidator.java b/src/main/java/com/networknt/schema/DependenciesValidator.java
index 596e77a..72b6c78 100644
--- a/src/main/java/com/networknt/schema/DependenciesValidator.java
+++ b/src/main/java/com/networknt/schema/DependenciesValidator.java
@@ -63,7 +63,7 @@ public class DependenciesValidator extends BaseJsonValidator implements JsonVali
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         Set<ValidationMessage> errors = null;
 
diff --git a/src/main/java/com/networknt/schema/DependentRequired.java b/src/main/java/com/networknt/schema/DependentRequired.java
index 8350726..8c7110f 100644
--- a/src/main/java/com/networknt/schema/DependentRequired.java
+++ b/src/main/java/com/networknt/schema/DependentRequired.java
@@ -47,7 +47,7 @@ public class DependentRequired extends BaseJsonValidator implements JsonValidato
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         Set<ValidationMessage> errors = new LinkedHashSet<ValidationMessage>();
 
diff --git a/src/main/java/com/networknt/schema/DependentSchemas.java b/src/main/java/com/networknt/schema/DependentSchemas.java
index 5ab4fe7..589a8e5 100644
--- a/src/main/java/com/networknt/schema/DependentSchemas.java
+++ b/src/main/java/com/networknt/schema/DependentSchemas.java
@@ -51,7 +51,7 @@ public class DependentSchemas extends BaseJsonValidator {
 
     protected Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode,
             JsonNodePath instanceLocation, boolean walk) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         Set<ValidationMessage> errors = null;
         for (Iterator<String> it = node.fieldNames(); it.hasNext(); ) {
diff --git a/src/main/java/com/networknt/schema/DynamicRefValidator.java b/src/main/java/com/networknt/schema/DynamicRefValidator.java
index ea4da48..10ce601 100644
--- a/src/main/java/com/networknt/schema/DynamicRefValidator.java
+++ b/src/main/java/com/networknt/schema/DynamicRefValidator.java
@@ -93,7 +93,7 @@ public class DynamicRefValidator extends BaseJsonValidator {
 
     @Override
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
         JsonSchema refSchema = this.schema.getSchema();
         if (refSchema == null) {
             ValidationMessage validationMessage = message().type(ValidatorTypeCode.DYNAMIC_REF.getValue())
@@ -107,7 +107,7 @@ public class DynamicRefValidator extends BaseJsonValidator {
 
     @Override
     public Set<ValidationMessage> walk(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation, boolean shouldValidateSchema) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
         // This is important because if we use same JsonSchemaFactory for creating multiple JSONSchema instances,
         // these schemas will be cached along with config. We have to replace the config for cached $ref references
         // with the latest config. Reset the config.
diff --git a/src/main/java/com/networknt/schema/EnumValidator.java b/src/main/java/com/networknt/schema/EnumValidator.java
index 582666d..7c77241 100644
--- a/src/main/java/com/networknt/schema/EnumValidator.java
+++ b/src/main/java/com/networknt/schema/EnumValidator.java
@@ -82,7 +82,7 @@ public class EnumValidator extends BaseJsonValidator implements JsonValidator {
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         if (node.isNumber()) {
             node = processNumberNode(node);
diff --git a/src/main/java/com/networknt/schema/ExclusiveMaximumValidator.java b/src/main/java/com/networknt/schema/ExclusiveMaximumValidator.java
index 35db8dd..0460481 100644
--- a/src/main/java/com/networknt/schema/ExclusiveMaximumValidator.java
+++ b/src/main/java/com/networknt/schema/ExclusiveMaximumValidator.java
@@ -98,7 +98,7 @@ public class ExclusiveMaximumValidator extends BaseJsonValidator {
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         if (!JsonNodeUtil.isNumber(node, validationContext.getConfig())) {
             // maximum only applies to numbers
diff --git a/src/main/java/com/networknt/schema/ExclusiveMinimumValidator.java b/src/main/java/com/networknt/schema/ExclusiveMinimumValidator.java
index ab2568f..aea9c36 100644
--- a/src/main/java/com/networknt/schema/ExclusiveMinimumValidator.java
+++ b/src/main/java/com/networknt/schema/ExclusiveMinimumValidator.java
@@ -105,7 +105,7 @@ public class ExclusiveMinimumValidator extends BaseJsonValidator {
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         if (!JsonNodeUtil.isNumber(node, this.validationContext.getConfig())) {
             // minimum only applies to numbers
diff --git a/src/main/java/com/networknt/schema/ExecutionConfig.java b/src/main/java/com/networknt/schema/ExecutionConfig.java
index 516241d..e4f83ee 100644
--- a/src/main/java/com/networknt/schema/ExecutionConfig.java
+++ b/src/main/java/com/networknt/schema/ExecutionConfig.java
@@ -54,7 +54,16 @@ public class ExecutionConfig {
      * Determine if the validation execution can fail fast.
      */
     private boolean failFast = false;
-    
+
+    /**
+     * Determine if debugging features such that logging are switched on.
+     * <p>
+     * This is turned off by default. This is present because the library attempts
+     * to log debug logs at each validation node and the logger evaluation on
+     * whether the logger is turned on is impacting performance.
+     */
+    private boolean debugEnabled = false;
+
     /**
      * Gets the locale to use for formatting messages.
      * 
@@ -180,4 +189,21 @@ public class ExecutionConfig {
                 "annotationCollectionFilter must not be null");
     }
 
+    /**
+     * Gets if debugging features such as logging is switched on.
+     *
+     * @return true if debug is enabled
+     */
+    public boolean isDebugEnabled() {
+        return debugEnabled;
+    }
+
+    /**
+     * Sets if debugging features such as logging is switched on.
+     *
+     * @param debugEnabled true to enable debug
+     */
+    public void setDebugEnabled(boolean debugEnabled) {
+        this.debugEnabled = debugEnabled;
+    }
 }
diff --git a/src/main/java/com/networknt/schema/FalseValidator.java b/src/main/java/com/networknt/schema/FalseValidator.java
index 8018a76..8032e3e 100644
--- a/src/main/java/com/networknt/schema/FalseValidator.java
+++ b/src/main/java/com/networknt/schema/FalseValidator.java
@@ -36,7 +36,7 @@ public class FalseValidator extends BaseJsonValidator implements JsonValidator {
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
         // For the false validator, it is always not valid
         return Collections.singleton(message().instanceNode(node).instanceLocation(instanceLocation)
                 .locale(executionContext.getExecutionConfig().getLocale())
diff --git a/src/main/java/com/networknt/schema/FormatValidator.java b/src/main/java/com/networknt/schema/FormatValidator.java
index 9665762..7177f3f 100644
--- a/src/main/java/com/networknt/schema/FormatValidator.java
+++ b/src/main/java/com/networknt/schema/FormatValidator.java
@@ -59,7 +59,7 @@ public class FormatValidator extends BaseFormatJsonValidator implements JsonVali
     }
     
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
         /*
          * Annotations must be collected even if the format is unknown according to the specification.
          */
diff --git a/src/main/java/com/networknt/schema/IfValidator.java b/src/main/java/com/networknt/schema/IfValidator.java
index efb49ed..13ed4e8 100644
--- a/src/main/java/com/networknt/schema/IfValidator.java
+++ b/src/main/java/com/networknt/schema/IfValidator.java
@@ -65,7 +65,7 @@ public class IfValidator extends BaseJsonValidator {
 
     @Override
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         boolean ifConditionPassed = false;
 
diff --git a/src/main/java/com/networknt/schema/ItemsValidator.java b/src/main/java/com/networknt/schema/ItemsValidator.java
index 7912ebd..4407f91 100644
--- a/src/main/java/com/networknt/schema/ItemsValidator.java
+++ b/src/main/java/com/networknt/schema/ItemsValidator.java
@@ -87,7 +87,7 @@ public class ItemsValidator extends BaseJsonValidator {
 
     @Override
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         if (!node.isArray() && !this.validationContext.getConfig().isTypeLoose()) {
             // ignores non-arrays
diff --git a/src/main/java/com/networknt/schema/ItemsValidator202012.java b/src/main/java/com/networknt/schema/ItemsValidator202012.java
index 9edcb37..d8efd1a 100644
--- a/src/main/java/com/networknt/schema/ItemsValidator202012.java
+++ b/src/main/java/com/networknt/schema/ItemsValidator202012.java
@@ -65,7 +65,7 @@ public class ItemsValidator202012 extends BaseJsonValidator {
     @Override
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode,
             JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         // ignores non-arrays
         if (node.isArray()) {
diff --git a/src/main/java/com/networknt/schema/MaxItemsValidator.java b/src/main/java/com/networknt/schema/MaxItemsValidator.java
index b8ee041..57b0c02 100644
--- a/src/main/java/com/networknt/schema/MaxItemsValidator.java
+++ b/src/main/java/com/networknt/schema/MaxItemsValidator.java
@@ -40,7 +40,7 @@ public class MaxItemsValidator extends BaseJsonValidator implements JsonValidato
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         if (node.isArray()) {
             if (node.size() > max) {
diff --git a/src/main/java/com/networknt/schema/MaxLengthValidator.java b/src/main/java/com/networknt/schema/MaxLengthValidator.java
index 08882ed..e304478 100644
--- a/src/main/java/com/networknt/schema/MaxLengthValidator.java
+++ b/src/main/java/com/networknt/schema/MaxLengthValidator.java
@@ -40,7 +40,7 @@ public class MaxLengthValidator extends BaseJsonValidator implements JsonValidat
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         JsonType nodeType = TypeFactory.getValueNodeType(node, this.validationContext.getConfig());
         if (nodeType != JsonType.STRING) {
diff --git a/src/main/java/com/networknt/schema/MaxPropertiesValidator.java b/src/main/java/com/networknt/schema/MaxPropertiesValidator.java
index 0d33b12..f6e5872 100644
--- a/src/main/java/com/networknt/schema/MaxPropertiesValidator.java
+++ b/src/main/java/com/networknt/schema/MaxPropertiesValidator.java
@@ -42,7 +42,7 @@ public class MaxPropertiesValidator extends BaseJsonValidator implements JsonVal
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         if (node.isObject()) {
             if (node.size() > max) {
diff --git a/src/main/java/com/networknt/schema/MaximumValidator.java b/src/main/java/com/networknt/schema/MaximumValidator.java
index 03a7c9c..261fa47 100644
--- a/src/main/java/com/networknt/schema/MaximumValidator.java
+++ b/src/main/java/com/networknt/schema/MaximumValidator.java
@@ -108,7 +108,7 @@ public class MaximumValidator extends BaseJsonValidator {
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         if (!JsonNodeUtil.isNumber(node, this.validationContext.getConfig())) {
             // maximum only applies to numbers
diff --git a/src/main/java/com/networknt/schema/MinItemsValidator.java b/src/main/java/com/networknt/schema/MinItemsValidator.java
index 83db6ec..52f927b 100644
--- a/src/main/java/com/networknt/schema/MinItemsValidator.java
+++ b/src/main/java/com/networknt/schema/MinItemsValidator.java
@@ -39,7 +39,7 @@ public class MinItemsValidator extends BaseJsonValidator implements JsonValidato
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         if (node.isArray()) {
             if (node.size() < min) {
diff --git a/src/main/java/com/networknt/schema/MinLengthValidator.java b/src/main/java/com/networknt/schema/MinLengthValidator.java
index c82b8ec..1161ba2 100644
--- a/src/main/java/com/networknt/schema/MinLengthValidator.java
+++ b/src/main/java/com/networknt/schema/MinLengthValidator.java
@@ -40,7 +40,7 @@ public class MinLengthValidator extends BaseJsonValidator implements JsonValidat
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         JsonType nodeType = TypeFactory.getValueNodeType(node, this.validationContext.getConfig());
         if (nodeType != JsonType.STRING) {
diff --git a/src/main/java/com/networknt/schema/MinPropertiesValidator.java b/src/main/java/com/networknt/schema/MinPropertiesValidator.java
index 1ff5664..2867a08 100644
--- a/src/main/java/com/networknt/schema/MinPropertiesValidator.java
+++ b/src/main/java/com/networknt/schema/MinPropertiesValidator.java
@@ -42,7 +42,7 @@ public class MinPropertiesValidator extends BaseJsonValidator implements JsonVal
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         if (node.isObject()) {
             if (node.size() < min) {
diff --git a/src/main/java/com/networknt/schema/MinimumValidator.java b/src/main/java/com/networknt/schema/MinimumValidator.java
index 8b2e5e7..3f35948 100644
--- a/src/main/java/com/networknt/schema/MinimumValidator.java
+++ b/src/main/java/com/networknt/schema/MinimumValidator.java
@@ -115,7 +115,7 @@ public class MinimumValidator extends BaseJsonValidator {
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         if (!JsonNodeUtil.isNumber(node, this.validationContext.getConfig())) {
             // minimum only applies to numbers
diff --git a/src/main/java/com/networknt/schema/MultipleOfValidator.java b/src/main/java/com/networknt/schema/MultipleOfValidator.java
index 95b57ce..bcd29d2 100644
--- a/src/main/java/com/networknt/schema/MultipleOfValidator.java
+++ b/src/main/java/com/networknt/schema/MultipleOfValidator.java
@@ -42,7 +42,7 @@ public class MultipleOfValidator extends BaseJsonValidator implements JsonValida
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode,
             JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
         if (this.divisor != null) {
             BigDecimal dividend = getDividend(node);
             if (dividend != null) {
diff --git a/src/main/java/com/networknt/schema/NotAllowedValidator.java b/src/main/java/com/networknt/schema/NotAllowedValidator.java
index 3d9952b..401729d 100644
--- a/src/main/java/com/networknt/schema/NotAllowedValidator.java
+++ b/src/main/java/com/networknt/schema/NotAllowedValidator.java
@@ -41,7 +41,7 @@ public class NotAllowedValidator extends BaseJsonValidator implements JsonValida
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         Set<ValidationMessage> errors = null;
 
diff --git a/src/main/java/com/networknt/schema/NotValidator.java b/src/main/java/com/networknt/schema/NotValidator.java
index 8ca348b..e943a51 100644
--- a/src/main/java/com/networknt/schema/NotValidator.java
+++ b/src/main/java/com/networknt/schema/NotValidator.java
@@ -45,7 +45,7 @@ public class NotValidator extends BaseJsonValidator {
     protected Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode,
             JsonNodePath instanceLocation, boolean walk) {
         Set<ValidationMessage> errors = null;
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         // Save flag as nested schema evaluation shouldn't trigger fail fast
         boolean failFast = executionContext.isFailFast();
diff --git a/src/main/java/com/networknt/schema/OneOfValidator.java b/src/main/java/com/networknt/schema/OneOfValidator.java
index 2e5df8c..c78df98 100644
--- a/src/main/java/com/networknt/schema/OneOfValidator.java
+++ b/src/main/java/com/networknt/schema/OneOfValidator.java
@@ -61,7 +61,7 @@ public class OneOfValidator extends BaseJsonValidator {
             JsonNodePath instanceLocation, boolean walk) {
         Set<ValidationMessage> errors = null;
 
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
         int numberOfValidSchema = 0;
         int index = 0;
         SetView<ValidationMessage> childErrors = null;
diff --git a/src/main/java/com/networknt/schema/PatternPropertiesValidator.java b/src/main/java/com/networknt/schema/PatternPropertiesValidator.java
index 797558a..94cb16c 100644
--- a/src/main/java/com/networknt/schema/PatternPropertiesValidator.java
+++ b/src/main/java/com/networknt/schema/PatternPropertiesValidator.java
@@ -50,7 +50,7 @@ public class PatternPropertiesValidator extends BaseJsonValidator {
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         if (!node.isObject()) {
             return Collections.emptySet();
diff --git a/src/main/java/com/networknt/schema/PatternValidator.java b/src/main/java/com/networknt/schema/PatternValidator.java
index db6f32e..5605b8f 100644
--- a/src/main/java/com/networknt/schema/PatternValidator.java
+++ b/src/main/java/com/networknt/schema/PatternValidator.java
@@ -49,7 +49,7 @@ public class PatternValidator extends BaseJsonValidator {
 
     @Override
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         JsonType nodeType = TypeFactory.getValueNodeType(node, this.validationContext.getConfig());
         if (nodeType != JsonType.STRING) {
diff --git a/src/main/java/com/networknt/schema/PrefixItemsValidator.java b/src/main/java/com/networknt/schema/PrefixItemsValidator.java
index ccda858..a1db79a 100644
--- a/src/main/java/com/networknt/schema/PrefixItemsValidator.java
+++ b/src/main/java/com/networknt/schema/PrefixItemsValidator.java
@@ -60,7 +60,7 @@ public class PrefixItemsValidator extends BaseJsonValidator {
 
     @Override
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
         // ignores non-arrays
         if (node.isArray()) {
             SetView<ValidationMessage> errors = null;
diff --git a/src/main/java/com/networknt/schema/PropertiesValidator.java b/src/main/java/com/networknt/schema/PropertiesValidator.java
index 92267c0..36bcab8 100644
--- a/src/main/java/com/networknt/schema/PropertiesValidator.java
+++ b/src/main/java/com/networknt/schema/PropertiesValidator.java
@@ -63,7 +63,7 @@ public class PropertiesValidator extends BaseJsonValidator {
 
     protected Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode,
             JsonNodePath instanceLocation, boolean walk) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         SetView<ValidationMessage> errors = null;
 
diff --git a/src/main/java/com/networknt/schema/PropertyNamesValidator.java b/src/main/java/com/networknt/schema/PropertyNamesValidator.java
index 6edc145..3d895f0 100644
--- a/src/main/java/com/networknt/schema/PropertyNamesValidator.java
+++ b/src/main/java/com/networknt/schema/PropertyNamesValidator.java
@@ -35,7 +35,7 @@ public class PropertyNamesValidator extends BaseJsonValidator implements JsonVal
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         Set<ValidationMessage> errors = null;
         for (Iterator<String> it = node.fieldNames(); it.hasNext(); ) {
diff --git a/src/main/java/com/networknt/schema/ReadOnlyValidator.java b/src/main/java/com/networknt/schema/ReadOnlyValidator.java
index 9ea33ea..c7b0b9a 100644
--- a/src/main/java/com/networknt/schema/ReadOnlyValidator.java
+++ b/src/main/java/com/networknt/schema/ReadOnlyValidator.java
@@ -41,7 +41,7 @@ public class ReadOnlyValidator extends BaseJsonValidator {
 
     @Override
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
         if (this.readOnly) {
             return Collections.singleton(message().instanceNode(node).instanceLocation(instanceLocation)
                     .locale(executionContext.getExecutionConfig().getLocale())
diff --git a/src/main/java/com/networknt/schema/RecursiveRefValidator.java b/src/main/java/com/networknt/schema/RecursiveRefValidator.java
index 73a72ce..ad8f009 100644
--- a/src/main/java/com/networknt/schema/RecursiveRefValidator.java
+++ b/src/main/java/com/networknt/schema/RecursiveRefValidator.java
@@ -90,7 +90,7 @@ public class RecursiveRefValidator extends BaseJsonValidator {
     
     @Override
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
         JsonSchema refSchema = this.schema.getSchema();
         if (refSchema == null) {
             ValidationMessage validationMessage = message().type(ValidatorTypeCode.RECURSIVE_REF.getValue())
@@ -104,7 +104,7 @@ public class RecursiveRefValidator extends BaseJsonValidator {
 
     @Override
     public Set<ValidationMessage> walk(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation, boolean shouldValidateSchema) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
         // This is important because if we use same JsonSchemaFactory for creating multiple JSONSchema instances,
         // these schemas will be cached along with config. We have to replace the config for cached $ref references
         // with the latest config. Reset the config.
diff --git a/src/main/java/com/networknt/schema/RefValidator.java b/src/main/java/com/networknt/schema/RefValidator.java
index f7df836..823e43c 100644
--- a/src/main/java/com/networknt/schema/RefValidator.java
+++ b/src/main/java/com/networknt/schema/RefValidator.java
@@ -177,7 +177,7 @@ public class RefValidator extends BaseJsonValidator {
 
     @Override
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
         JsonSchema refSchema = this.schema.getSchema();
         if (refSchema == null) {
             ValidationMessage validationMessage = message().type(ValidatorTypeCode.REF.getValue())
@@ -191,7 +191,7 @@ public class RefValidator extends BaseJsonValidator {
 
     @Override
     public Set<ValidationMessage> walk(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation, boolean shouldValidateSchema) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
         // This is important because if we use same JsonSchemaFactory for creating multiple JSONSchema instances,
         // these schemas will be cached along with config. We have to replace the config for cached $ref references
         // with the latest config. Reset the config.
diff --git a/src/main/java/com/networknt/schema/RequiredValidator.java b/src/main/java/com/networknt/schema/RequiredValidator.java
index 1b6b816..1e084c1 100644
--- a/src/main/java/com/networknt/schema/RequiredValidator.java
+++ b/src/main/java/com/networknt/schema/RequiredValidator.java
@@ -40,7 +40,7 @@ public class RequiredValidator extends BaseJsonValidator implements JsonValidato
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         if (!node.isObject()) {
             return Collections.emptySet();
diff --git a/src/main/java/com/networknt/schema/TrueValidator.java b/src/main/java/com/networknt/schema/TrueValidator.java
index 0c003d9..380ed5d 100644
--- a/src/main/java/com/networknt/schema/TrueValidator.java
+++ b/src/main/java/com/networknt/schema/TrueValidator.java
@@ -33,7 +33,7 @@ public class TrueValidator extends BaseJsonValidator implements JsonValidator {
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
         // For the true validator, it is always valid which means there is no ValidationMessage.
         return Collections.emptySet();
     }
diff --git a/src/main/java/com/networknt/schema/TypeValidator.java b/src/main/java/com/networknt/schema/TypeValidator.java
index 245f690..2cadb1b 100644
--- a/src/main/java/com/networknt/schema/TypeValidator.java
+++ b/src/main/java/com/networknt/schema/TypeValidator.java
@@ -52,7 +52,7 @@ public class TypeValidator extends BaseJsonValidator {
 
     @Override
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         if (this.schemaType == JsonType.UNION) {
             return this.unionTypeValidator.validate(executionContext, node, rootNode, instanceLocation);
diff --git a/src/main/java/com/networknt/schema/UnevaluatedItemsValidator.java b/src/main/java/com/networknt/schema/UnevaluatedItemsValidator.java
index a01273f..49419f2 100644
--- a/src/main/java/com/networknt/schema/UnevaluatedItemsValidator.java
+++ b/src/main/java/com/networknt/schema/UnevaluatedItemsValidator.java
@@ -59,7 +59,7 @@ public class UnevaluatedItemsValidator extends BaseJsonValidator {
             return Collections.emptySet();
         }
 
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
         /*
          * Keywords renamed in 2020-12
          * 
diff --git a/src/main/java/com/networknt/schema/UnevaluatedPropertiesValidator.java b/src/main/java/com/networknt/schema/UnevaluatedPropertiesValidator.java
index 61b6ced..e40b242 100644
--- a/src/main/java/com/networknt/schema/UnevaluatedPropertiesValidator.java
+++ b/src/main/java/com/networknt/schema/UnevaluatedPropertiesValidator.java
@@ -50,7 +50,7 @@ public class UnevaluatedPropertiesValidator extends BaseJsonValidator {
             return Collections.emptySet();
         }
 
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
         // Get all the valid adjacent annotations
         Predicate<JsonNodeAnnotation> validEvaluationPathFilter = a -> {
             return executionContext.getResults().isValid(instanceLocation, a.getEvaluationPath());
diff --git a/src/main/java/com/networknt/schema/UnionTypeValidator.java b/src/main/java/com/networknt/schema/UnionTypeValidator.java
index c051ea3..184a119 100644
--- a/src/main/java/com/networknt/schema/UnionTypeValidator.java
+++ b/src/main/java/com/networknt/schema/UnionTypeValidator.java
@@ -65,7 +65,7 @@ public class UnionTypeValidator extends BaseJsonValidator implements JsonValidat
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         JsonType nodeType = TypeFactory.getValueNodeType(node, validationContext.getConfig());
 
diff --git a/src/main/java/com/networknt/schema/UniqueItemsValidator.java b/src/main/java/com/networknt/schema/UniqueItemsValidator.java
index a061b97..2740d40 100644
--- a/src/main/java/com/networknt/schema/UniqueItemsValidator.java
+++ b/src/main/java/com/networknt/schema/UniqueItemsValidator.java
@@ -42,7 +42,7 @@ public class UniqueItemsValidator extends BaseJsonValidator implements JsonValid
     }
 
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
 
         if (unique) {
             Set<JsonNode> set = new HashSet<JsonNode>();
diff --git a/src/main/java/com/networknt/schema/WriteOnlyValidator.java b/src/main/java/com/networknt/schema/WriteOnlyValidator.java
index e13da5a..c441e6b 100644
--- a/src/main/java/com/networknt/schema/WriteOnlyValidator.java
+++ b/src/main/java/com/networknt/schema/WriteOnlyValidator.java
@@ -25,7 +25,7 @@ public class WriteOnlyValidator extends BaseJsonValidator {
 
     @Override
     public Set<ValidationMessage> validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation) {
-        debug(logger, node, rootNode, instanceLocation);
+        debug(logger, executionContext, node, rootNode, instanceLocation);
         if (this.writeOnly) {
             return Collections.singleton(message().instanceNode(node).instanceLocation(instanceLocation)
                     .locale(executionContext.getExecutionConfig().getLocale())


Test patch:
diff --git a/src/test/java/com/networknt/schema/CachedSupplierTest.java b/src/test/java/com/networknt/schema/CachedSupplierTest.java
new file mode 100644
index 0000000..f0b8cfa
--- /dev/null
+++ b/src/test/java/com/networknt/schema/CachedSupplierTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2024 the original author or authors.
+ *
+ * Licensed 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 com.networknt.schema;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * Test for CachedSupplier.
+ */
+class CachedSupplierTest {
+    @Test
+    void nullValue() {
+        CachedSupplier<String> supplier = new CachedSupplier<>(null);
+        assertNull(supplier.get());
+    }
+
+    @Test
+    void concurrency() throws Exception {
+        AtomicInteger value = new AtomicInteger(0);
+        
+        CachedSupplier<Integer> supplier = new CachedSupplier<>(() -> {
+            return value.addAndGet(1);
+        });
+        Exception[] instance = new Exception[1];
+        CountDownLatch latch = new CountDownLatch(1);
+        List<Thread> threads = new ArrayList<>();
+        for (int i = 0; i < 50; ++i) {
+            Runnable runner = new Runnable() {
+                public void run() {
+                    try {
+                        latch.await();
+                    } catch (InterruptedException e) {
+                        throw new RuntimeException(e);
+                    }
+                    try {
+                        int result = supplier.get();
+                        assertEquals(1, result);
+                    } catch(Exception e) {
+                        synchronized(instance) {
+                            instance[0] = e;
+                        }
+                    }
+                }
+            };
+            Thread thread = new Thread(runner, "Thread" + i);
+            thread.start();
+            threads.add(thread);
+        }
+        latch.countDown(); // Release the latch for threads to run concurrently
+        threads.forEach(t -> {
+            try {
+                t.join();
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+        });
+        if (instance[0] != null) {
+            throw instance[0];
+        }
+        assertEquals(1, value.get());
+    }
+}