You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by th...@apache.org on 2017/10/27 13:28:48 UTC

svn commit: r1813533 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/stats: QueryRecorder.java QueryStatsData.java

Author: thomasm
Date: Fri Oct 27 13:28:48 2017
New Revision: 1813533

URL: http://svn.apache.org/viewvc?rev=1813533&view=rev
Log:
OAK-6807 Query Recorder

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/stats/QueryRecorder.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/stats/QueryStatsData.java

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/stats/QueryRecorder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/stats/QueryRecorder.java?rev=1813533&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/stats/QueryRecorder.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/stats/QueryRecorder.java Fri Oct 27 13:28:48 2017
@@ -0,0 +1,137 @@
+/*
+ * 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.jackrabbit.oak.query.stats;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.LineNumberReader;
+import java.util.HashMap;
+import java.util.Map.Entry;
+import java.util.TreeSet;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class QueryRecorder {
+
+    private static final Logger LOG = LoggerFactory.getLogger(QueryRecorder.class);
+    private static final HashMap<String, Integer> RECORD_QUERIES_MAP = new HashMap<String, Integer>();
+    private final static int QUERIES_MAX =  Integer.getInteger("oak.query.record", 5000);
+    
+    public static void main(String... args) throws IOException {
+        // command line version: read from a file
+        LineNumberReader reader = new LineNumberReader(
+                new BufferedReader(new FileReader(args[0])));
+        TreeSet<String> sorted = new TreeSet<String>();
+        int lineCount = 0;
+        while(true) {
+            String line = reader.readLine();
+            if(line == null) {
+                break;
+            }
+            sorted.add(simplify(line));
+            lineCount++;
+        }
+        reader.close();
+        for(String s : sorted) {
+            System.out.println(s);
+        }
+        System.out.println("sorted: " + sorted.size() + " original: " + lineCount);
+    }
+    
+    public static void record(String query, boolean internal) {
+        if (internal) {
+            return;
+        }
+        if (!LOG.isDebugEnabled()) {
+            return;
+        }
+        query = query.replace('\n', ' ');
+        query = query.replace('\t', ' ');
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("query:\t{}", query);
+        }
+        try {
+            query = simplify(query);
+        } catch (Exception e) {
+            LOG.trace("failed to simplify {}", query, e);
+        }
+        record(query);
+    }
+    
+    public static String simplify(String query) {
+        query = query.replaceAll("'[^']*'", "'x'");
+        query = query.replaceAll("ISDESCENDANTNODE\\(\\[/[^]]*\\]\\)", "ISDESCENDANTNODE('x')");
+        int pathIndex = query.indexOf("/jcr:root/");
+        if (pathIndex >= 0) {
+            int start = pathIndex + "/jcr:root/".length();
+            int end = getFirstOccurance(query, start,
+                    " ", "/element(", "/text(", "/*", "/(", "/jcr:deref(");
+            String path = query.substring(start, end);
+            int first = path.indexOf('/');
+            if (first > 0) {
+                first = path.indexOf('/', first + 1);
+                if (first > 0) {
+                    path = path.substring(0, first + 1) + "...";
+                }
+            }
+            String newQuery = query.substring(0, pathIndex) + "/jcr:root/" + path + query.substring(end, query.length());
+            query = newQuery;
+        }
+        return query;
+    }
+    
+    static int getFirstOccurance(String text, int start, String... strings) {
+        int first = text.length();
+        for(String s : strings) {
+            int index = text.indexOf(s, start + 1);
+            if (index > 0 && index < first) {
+                first = index;
+            }
+        }
+        return first;
+    }
+    
+    private static void record(String query) {
+        HashMap<String, Integer> map = RECORD_QUERIES_MAP;
+        if (map.size() > QUERIES_MAX) {
+            HashMap<String, Integer> old;
+            synchronized (map) {
+                old = new HashMap<>(map);
+                map.clear();
+            }
+            for(Entry<String, Integer> e : old.entrySet()) {
+                log(e.getKey(), e.getValue());
+            }
+        }
+        Integer count;
+        synchronized (map) {
+            count = map.get(query);
+            count = count == null ? 1 : count + 1;
+            map.put(query, count);
+        }
+        if (count == 1 || count % 100 == 0) {
+            log(query, count);
+        }
+    }
+
+    private static void log(String query, int count) {
+        LOG.debug("count:\t{}\tquery:\t{}", count, query);
+    }
+
+}

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/stats/QueryStatsData.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/stats/QueryStatsData.java?rev=1813533&r1=1813532&r2=1813533&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/stats/QueryStatsData.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/stats/QueryStatsData.java Fri Oct 27 13:28:48 2017
@@ -140,6 +140,7 @@ public class QueryStatsData {
         long time;
         
         public void execute(long nanos) {
+            QueryRecorder.record(query, internal);
             executeCount++;
             lastExecutedMillis = System.currentTimeMillis();
             time += nanos;