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 re...@apache.org on 2021/02/08 17:33:16 UTC

svn commit: r1886329 - in /jackrabbit/oak/branches/1.6/oak-core: ./ src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandler.java src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandlerTest.java

Author: reschke
Date: Mon Feb  8 17:33:15 2021
New Revision: 1886329

URL: http://svn.apache.org/viewvc?rev=1886329&view=rev
Log:
OAK-8411: RDBConnectionHandler: add minimal open connection stats in TRACE log level (merged 1861630 into 1.6)

Added:
    jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandlerTest.java
      - copied unchanged from r1861630, jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandlerTest.java
Modified:
    jackrabbit/oak/branches/1.6/oak-core/   (props changed)
    jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandler.java

Propchange: jackrabbit/oak/branches/1.6/oak-core/
------------------------------------------------------------------------------
  Merged /jackrabbit/oak/trunk/oak-store-document:r1861630

Modified: jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandler.java?rev=1886329&r1=1886328&r2=1886329&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandler.java (original)
+++ jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandler.java Mon Feb  8 17:33:15 2021
@@ -18,8 +18,11 @@ package org.apache.jackrabbit.oak.plugin
 
 import java.io.Closeable;
 import java.io.IOException;
+import java.lang.ref.WeakReference;
 import java.sql.Connection;
 import java.sql.SQLException;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
@@ -144,11 +147,13 @@ public class RDBConnectionHandler implem
     @Nonnull
     private Connection getConnection() throws IllegalStateException, SQLException {
         long ts = System.currentTimeMillis();
+        dumpConnectionMap(ts);
         Connection c = getDataSource().getConnection();
+        remember(c);
         if (LOG.isDebugEnabled()) {
             long elapsed = System.currentTimeMillis() - ts;
             if (elapsed >= 100) {
-                LOG.debug("Obtaining a new connection from " + this.ds + " took " + elapsed + "ms");
+                LOG.debug("Obtaining a new connection from " + this.ds + " took " + elapsed + "ms", new Exception("call stack"));
             }
         }
         return c;
@@ -192,4 +197,96 @@ public class RDBConnectionHandler implem
             }
         }
     }
+
+    private static class ConnectionHolder {
+        public String thread;
+        public String caller;
+        public long ts;
+
+        public ConnectionHolder() {
+            Thread t = Thread.currentThread();
+            this.thread = t.getName();
+            this.caller = getCaller(t.getStackTrace());
+            this.ts = System.currentTimeMillis();
+        }
+
+        public long getTimestamp() {
+            return ts;
+        }
+
+        public String dump(long now) {
+            return "(thread=" + thread + ", caller=" + caller + ", age=" + (now - ts) + ")";
+        }
+    }
+
+    private final int LOGTHRESHOLD = 20;
+
+    private ConcurrentMap<WeakReference<Connection>, ConnectionHolder> connectionMap = new ConcurrentHashMap<>();
+
+    private void dumpConnectionMap(long ts) {
+        if (LOG.isTraceEnabled()) {
+            connectionMap.forEach((k, v) -> {
+                try {
+                    Connection con = k.get();
+                    if (con == null || con.isClosed()) {
+                        connectionMap.remove(k);
+                    }
+                } catch (SQLException ex) {
+                }
+            });
+
+            int size = connectionMap.size();
+            if (size > 0) {
+                int cnt = 0;
+                StringBuilder sb = new StringBuilder();
+                for (ConnectionHolder ch : connectionMap.values()) {
+                    if (ts - ch.getTimestamp() >= LOGTHRESHOLD) {
+                        if (cnt != 0) {
+                            sb.append(", ");
+                        }
+                        cnt += 1;
+                        sb.append(ch.dump(ts));
+                    }
+                }
+                if (cnt > 0) {
+                    LOG.trace(cnt + " connections with age >= " + LOGTHRESHOLD + "ms active while obtaining new connection: "
+                            + sb.toString());
+                }
+            }
+        }
+    }
+
+    private void remember(Connection c) {
+        if (LOG.isTraceEnabled()) {
+            connectionMap.put(new WeakReference<Connection>(c), new ConnectionHolder());
+        }
+    }
+
+    private static String getCaller(StackTraceElement[] elements) {
+        StringBuilder sb = new StringBuilder();
+        String prevClass = null;
+        for (StackTraceElement e : elements) {
+            String cn = e.getClassName();
+            if (!cn.startsWith(RDBConnectionHandler.class.getName()) && !(cn.startsWith(Thread.class.getName()))) {
+                if (sb.length() != 0) {
+                    sb.append(" ");
+                }
+                if (e.getClassName().equals(prevClass)) {
+                    String loc;
+                    if (e.isNativeMethod()) {
+                        loc = "Native Method";
+                    } else if (e.getFileName() == null) {
+                        loc = "Unknown Source";
+                    } else {
+                        loc = e.getFileName() + ":" + e.getLineNumber();
+                    }
+                    sb.append('.').append(e.getMethodName()).append('(').append(loc).append(')');
+                } else {
+                    sb.append(e.toString());
+                }
+                prevClass = e.getClassName();
+            }
+        }
+        return sb.toString();
+    }
 }