This is an automated email from the ASF dual-hosted git repository. joscorbe pushed a commit to branch OAK-11997 in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
commit 480cf45fa909373b0812d26d93143d0f497a5ee0 Author: Jose Cordero <[email protected]> AuthorDate: Fri Oct 24 11:39:14 2025 +0200 OAK-11997: Add OSGi config to log slow Mongo queries. --- .../oak/plugins/document/Configuration.java | 8 +++ .../plugins/document/DocumentNodeStoreService.java | 7 +++ .../mongo/MongoDocumentNodeStoreBuilderBase.java | 19 +++++++ .../DocumentNodeStoreServiceConfigurationTest.java | 59 ++++++++++++++++++++++ 4 files changed, 93 insertions(+) diff --git a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Configuration.java b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Configuration.java index a23685f402..9e3d5d798d 100644 --- a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Configuration.java +++ b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Configuration.java @@ -39,6 +39,7 @@ import static org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreServic import static org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreService.DEFAULT_FULL_GC_ENABLED; import static org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreService.DEFAULT_EMBEDDED_VERIFICATION_ENABLED; import static org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreService.DEFAULT_FULL_GC_GENERATION; +import static org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreService.DEFAULT_MONGO_QUERY_WARNING_THRESHOLD_MILLIS; import static org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreService.DEFAULT_PERFLOGGER_INFO_MILLIS; import static org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreService.DEFAULT_THROTTLING_ENABLED; import static org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreService.DEFAULT_FULL_GC_MODE; @@ -516,4 +517,11 @@ import static org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreServic "merging the changes in case of a conflict. The Default value is " + DEFAULT_AVOID_EXCLUSIVE_MERGE_LOCK + " Note that this value can be overridden via framework property 'oak.documentstore.avoidExclusiveMergeLock'") boolean avoidExclusiveMergeLock() default DEFAULT_AVOID_EXCLUSIVE_MERGE_LOCK; + + @AttributeDefinition( + name = "MongoDB Query Warning Threshold (in millis)", + description = "Threshold in milliseconds for logging warnings when MongoDB queries take longer than expected. " + + "A value of 0 disables query time warnings. Default is 0 (disabled). " + + "Note that this value can be overridden via framework property 'oak.mongo.queryWarningThresholdMillis'") + long mongoQueryWarningThresholdMillis() default DEFAULT_MONGO_QUERY_WARNING_THRESHOLD_MILLIS; } diff --git a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java index c263934da5..0426d7b2ae 100644 --- a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java +++ b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java @@ -231,6 +231,12 @@ public class DocumentNodeStoreService { /** OAK-11246 : default millis for perflogger info */ static final long DEFAULT_PERFLOGGER_INFO_MILLIS = Long.MAX_VALUE; + + /** + * Default threshold in milliseconds for logging MongoDB query warnings. + * A value of 0 disables query time warnings. + */ + static final long DEFAULT_MONGO_QUERY_WARNING_THRESHOLD_MILLIS = 0; /** * Feature toggle name to enable the prev-no-prop cache. @@ -392,6 +398,7 @@ public class DocumentNodeStoreService { builder.setMongoWaitQueueTimeoutMillis(config.mongoWaitQueueTimeoutMillis()); builder.setMongoReadTimeoutMillis(config.mongoReadTimeoutMillis()); builder.setMongoMinHeartbeatFrequencyMillis(config.mongoMinHeartbeatFrequencyMillis()); + builder.setMongoQueryWarningThresholdMillis(config.mongoQueryWarningThresholdMillis()); builder.setMongoDB(uri, db, config.blobCacheSize()); builder.setCollectionCompressionType(config.collectionCompressionType()); mkBuilder = builder; diff --git a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentNodeStoreBuilderBase.java b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentNodeStoreBuilderBase.java index fd0003c59e..73afe1e1ca 100644 --- a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentNodeStoreBuilderBase.java +++ b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentNodeStoreBuilderBase.java @@ -48,6 +48,7 @@ public abstract class MongoDocumentNodeStoreBuilderBase<T extends MongoDocumentN private MongoStatus mongoStatus; private long maxReplicationLagMillis = TimeUnit.HOURS.toMillis(6); private boolean clientSessionDisabled = false; + private long queryWarningThresholdMillis = 0; private Integer leaseSocketTimeout; private String uri; private String name; @@ -224,6 +225,24 @@ public abstract class MongoDocumentNodeStoreBuilderBase<T extends MongoDocumentN return thisBuilder(); } + /** + * Sets the threshold for logging warnings when MongoDB queries exceed this duration. + * + * @param thresholdMillis the threshold in milliseconds. A value of 0 disables warnings. + * @return this builder. + */ + public T setMongoQueryWarningThresholdMillis(long thresholdMillis) { + this.queryWarningThresholdMillis = thresholdMillis; + return thisBuilder(); + } + + /** + * @return the query warning threshold in milliseconds. + */ + long getQueryWarningThresholdMillis() { + return queryWarningThresholdMillis; + } + /** * @return the lease socket timeout in milliseconds. If none is set, then * zero is returned. diff --git a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreServiceConfigurationTest.java b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreServiceConfigurationTest.java index 2dc014678e..4955d7fe92 100644 --- a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreServiceConfigurationTest.java +++ b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreServiceConfigurationTest.java @@ -468,6 +468,65 @@ public class DocumentNodeStoreServiceConfigurationTest { assertEquals(15000, config.mongoHeartbeatFrequencyMillis()); } + @Test + public void mongoQueryWarningThresholdDefault() throws IOException { + Configuration config = createConfiguration(); + + // Verify default value is 0 (disabled) + assertEquals("Default query warning threshold should be 0 (disabled)", + 0L, config.mongoQueryWarningThresholdMillis()); + } + + @Test + public void mongoQueryWarningThresholdCustomValue() throws IOException { + // Set custom threshold value (30000 milliseconds = 30 seconds) + addConfigurationEntry(configuration, "mongoQueryWarningThresholdMillis", 30000L); + + Configuration config = createConfiguration(); + + // Verify the custom value is read correctly + assertEquals("Custom query warning threshold should be applied", + 30000L, config.mongoQueryWarningThresholdMillis()); + } + + @Test + public void mongoQueryWarningThresholdFromPreset() throws IOException { + // Set threshold value in preset (45000 milliseconds = 45 seconds) + addConfigurationEntry(preset, "mongoQueryWarningThresholdMillis", 45000L); + + Configuration config = createConfiguration(); + + // Verify the preset value is read correctly + assertEquals("Query warning threshold from preset should be applied", + 45000L, config.mongoQueryWarningThresholdMillis()); + } + + @Test + public void mongoQueryWarningThresholdOverridePreset() throws IOException { + // Set threshold in both preset and configuration + // Configuration should take precedence + addConfigurationEntry(preset, "mongoQueryWarningThresholdMillis", 45000L); + addConfigurationEntry(configuration, "mongoQueryWarningThresholdMillis", 60000L); + + Configuration config = createConfiguration(); + + // Verify the configuration value overrides preset + assertEquals("Configuration should override preset for query warning threshold", + 60000L, config.mongoQueryWarningThresholdMillis()); + } + + @Test + public void mongoQueryWarningThresholdDisabled() throws IOException { + // Explicitly set threshold to 0 to disable warnings + addConfigurationEntry(configuration, "mongoQueryWarningThresholdMillis", 0L); + + Configuration config = createConfiguration(); + + // Verify warnings are disabled + assertEquals("Query warning threshold of 0 should disable warnings", + 0L, config.mongoQueryWarningThresholdMillis()); + } + private Configuration createConfiguration() throws IOException { return DocumentNodeStoreServiceConfiguration.create( context.componentContext(), configAdmin,
