Author: thomasm
Date: Fri Jan 25 09:29:39 2019
New Revision: 1852102

URL: http://svn.apache.org/viewvc?rev=1852102&view=rev
Log:
OAK-7904 Exporting query duration per index metrics with Sling Metrics / 
DropWizard

Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexPlan.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettings.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
    
jackrabbit/oak/trunk/oak-query-spi/src/main/java/org/apache/jackrabbit/oak/spi/query/QueryIndex.java
    
jackrabbit/oak/trunk/oak-query-spi/src/main/java/org/apache/jackrabbit/oak/spi/query/package-info.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java?rev=1852102&r1=1852101&r2=1852102&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java
 Fri Jan 25 09:29:39 2019
@@ -228,6 +228,12 @@ class PropertyIndex implements QueryInde
     public String getIndexName() {
         return PROPERTY;
     }
+    
+    @Override
+    public String getIndexName(Filter filter, NodeState root) {
+        PropertyIndexPlan plan = getPlan(root, filter);
+        return plan == null ? null : plan.getName();
+    }
 
     @Override
     public double getCost(Filter filter, NodeState root) {

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexPlan.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexPlan.java?rev=1852102&r1=1852101&r2=1852102&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexPlan.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexPlan.java
 Fri Jan 25 09:29:39 2019
@@ -27,11 +27,9 @@ import static org.apache.jackrabbit.oak.
 import java.util.List;
 import java.util.Set;
 
-import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.plugins.index.Cursors;
 import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
-import 
org.apache.jackrabbit.oak.plugins.index.property.strategy.ContentMirrorStoreStrategy;
 import 
org.apache.jackrabbit.oak.plugins.index.property.strategy.IndexStoreStrategy;
 import org.apache.jackrabbit.oak.spi.filter.PathFilter;
 import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettings.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettings.java?rev=1852102&r1=1852101&r2=1852102&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettings.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettings.java
 Fri Jan 25 09:29:39 2019
@@ -152,7 +152,7 @@ public class QueryEngineSettings impleme
         return queryStats;
     }
 
-    StatisticsProvider getStatisticsProvider() {
+    public StatisticsProvider getStatisticsProvider() {
         return statisticsProvider;
     }
 

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java?rev=1852102&r1=1852101&r2=1852102&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
 Fri Jan 25 09:29:39 2019
@@ -29,6 +29,7 @@ import static org.apache.jackrabbit.oak.
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.PropertyValue;
@@ -53,6 +54,8 @@ import org.apache.jackrabbit.oak.spi.que
 import org.apache.jackrabbit.oak.spi.query.QueryIndex.AdvancedQueryIndex;
 import org.apache.jackrabbit.oak.spi.query.QueryIndex.IndexPlan;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.stats.StatsOptions;
+import org.apache.jackrabbit.oak.stats.TimerStats;
 import org.jetbrains.annotations.NotNull;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -66,6 +69,13 @@ import com.google.common.collect.Iterabl
 public class SelectorImpl extends SourceImpl {
     private static final Logger LOG = 
LoggerFactory.getLogger(SelectorImpl.class);
     
+    private static final Boolean TIMER_DISABLED = 
Boolean.getBoolean("oak.query.timerDisabled");
+    
+    // The sample rate. Must be a power of 2.
+    private static final Long TIMER_SAMPLE_RATE = 
Long.getLong("oak.query.timerSampleRate", 0x100);
+    
+    private static long timerSampleCounter;
+    
     // TODO possibly support using multiple indexes (using index intersection 
/ index merge)
     private SelectorExecutionPlan plan;
     
@@ -150,13 +160,16 @@ public class SelectorImpl extends Source
      * These constraints are collected during the prepare phase.
      */
     private final List<ConstraintImpl> selectorConstraints = newArrayList();
-
+    
     private Cursor cursor;
     private IndexRow currentRow;
     private int scanCount;
     
     private Tree lastTree;
     private String lastPath;
+    
+    private String planIndexName;
+    private TimerStats timerDuration;
 
     public SelectorImpl(NodeTypeInfo nodeTypeInfo, String selectorName) {
         this.nodeTypeInfo = checkNotNull(nodeTypeInfo);
@@ -243,6 +256,8 @@ public class SelectorImpl extends Source
     @Override
     public void unprepare() {
         plan = null;
+        planIndexName = null;
+        timerDuration = null;
         selectorConstraints.clear();
         isParent = false;
         joinCondition = null;
@@ -308,24 +323,70 @@ public class SelectorImpl extends Source
             isParent = true;
         }
     }
-
+    
     @Override
     public void execute(NodeState rootState) {
+        long start = startTimer();
+        try {
+            executeInternal(rootState);
+        } finally {
+            stopTimer(start, true);
+        }
+    }
+    
+    private void executeInternal(NodeState rootState) {
         QueryIndex index = plan.getIndex();
+        timerDuration = null;
         if (index == null) {
             cursor = Cursors.newPathCursor(new ArrayList<String>(), 
query.getSettings());
+            planIndexName = "traverse";
             return;
         }
         IndexPlan p = plan.getIndexPlan();
         if (p != null) {
+            planIndexName = p.getPlanName();
             p.setFilter(createFilter(false));
             AdvancedQueryIndex adv = (AdvancedQueryIndex) index;
             cursor = adv.query(p, rootState);
         } else {
-            cursor = index.query(createFilter(false), rootState);
+            FilterImpl f = createFilter(false);
+            planIndexName = index.getIndexName(f, rootState);
+            cursor = index.query(f, rootState);
+        }
+    }
+    
+    private long startTimer() {
+        if (TIMER_DISABLED) {
+            return -1;
+        }
+        return System.nanoTime();
+    }
+    
+    private void stopTimer(long start, boolean execute) {
+        if (start == -1) {
+            return;
+        }
+        long timeNanos = System.nanoTime() - start;
+        if (timeNanos > 1000000) {
+            // always measure slow events (slower than 1 ms)
+            measure(timeNanos);
+        } else if ((timerSampleCounter++ & (TIMER_SAMPLE_RATE - 1)) == 0) {
+            // only measure each xth fast event, but multiply by x, so on
+            // average measured times are correct
+            measure(timeNanos * TIMER_SAMPLE_RATE);
         }
     }
 
+    private void measure(long timeNanos) {
+        TimerStats t = timerDuration;
+        if (t == null) {
+            // reuse the timer (in the normal case)
+            t = timerDuration = query.getSettings().getStatisticsProvider().
+                getTimer("QUERY_DURATION_" + planIndexName, 
StatsOptions.METRICS_ONLY);
+        }
+        t.update(timeNanos, TimeUnit.NANOSECONDS);
+    }
+
     @Override
     public String getPlan(NodeState rootState) {
         StringBuilder buff = new StringBuilder();
@@ -431,6 +492,15 @@ public class SelectorImpl extends Source
 
     @Override
     public boolean next() {
+        long start = startTimer();
+        try {
+            return nextInternal();
+        } finally {
+            stopTimer(start, true);
+        }
+    }
+    
+    private boolean nextInternal() {
         while (cursor != null && cursor.hasNext()) {
             scanCount++;
             query.getQueryExecutionStats().scan(1, scanCount);

Modified: 
jackrabbit/oak/trunk/oak-query-spi/src/main/java/org/apache/jackrabbit/oak/spi/query/QueryIndex.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-query-spi/src/main/java/org/apache/jackrabbit/oak/spi/query/QueryIndex.java?rev=1852102&r1=1852101&r2=1852102&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-query-spi/src/main/java/org/apache/jackrabbit/oak/spi/query/QueryIndex.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-query-spi/src/main/java/org/apache/jackrabbit/oak/spi/query/QueryIndex.java
 Fri Jan 25 09:29:39 2019
@@ -118,13 +118,23 @@ public interface QueryIndex {
     String getPlan(Filter filter, NodeState rootState);
 
     /**
-     * Get the unique index name.
+     * Get the generic index name (normally the index type).
      *
      * @return the index name
      */
     String getIndexName();
 
     /**
+     * Get the specific index name (the path of the index definition, or the
+     * index type if that one is unique).
+     *
+     * @return the index name
+     */
+    default String getIndexName(Filter filter, NodeState rootState) {
+        return getIndexName();
+    }
+
+    /**
      *  A marker interface which means this index supports executing native 
queries
      */
     interface NativeQueryIndex {

Modified: 
jackrabbit/oak/trunk/oak-query-spi/src/main/java/org/apache/jackrabbit/oak/spi/query/package-info.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-query-spi/src/main/java/org/apache/jackrabbit/oak/spi/query/package-info.java?rev=1852102&r1=1852101&r2=1852102&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-query-spi/src/main/java/org/apache/jackrabbit/oak/spi/query/package-info.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-query-spi/src/main/java/org/apache/jackrabbit/oak/spi/query/package-info.java
 Fri Jan 25 09:29:39 2019
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@Version("1.1.0")
+@Version("1.2.0")
 package org.apache.jackrabbit.oak.spi.query;
 
 import org.osgi.annotation.versioning.Version;


Reply via email to