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 2019/06/19 14:32:54 UTC
svn commit: r1861630 - in /jackrabbit/oak/trunk/oak-store-document/src:
main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandler.java
test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandlerTest.java
Author: reschke
Date: Wed Jun 19 14:32:54 2019
New Revision: 1861630
URL: http://svn.apache.org/viewvc?rev=1861630&view=rev
Log:
OAK-8411: RDBConnectionHandler: add minimal open connection stats in TRACE log level
Added:
jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandlerTest.java (with props)
Modified:
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandler.java
Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandler.java?rev=1861630&r1=1861629&r2=1861630&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandler.java (original)
+++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandler.java Wed Jun 19 14:32:54 2019
@@ -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.sql.DataSource;
@@ -143,11 +146,13 @@ public class RDBConnectionHandler implem
@NotNull
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;
@@ -191,4 +196,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();
+ }
}
Added: jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandlerTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandlerTest.java?rev=1861630&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandlerTest.java (added)
+++ jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandlerTest.java Wed Jun 19 14:32:54 2019
@@ -0,0 +1,68 @@
+/*
+ * 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.plugins.document.rdb;
+
+import static org.junit.Assert.assertEquals;
+
+import java.sql.Connection;
+
+import javax.sql.DataSource;
+
+import org.apache.jackrabbit.oak.commons.junit.LogCustomizer;
+import org.junit.Test;
+import org.slf4j.event.Level;
+
+public class RDBConnectionHandlerTest {
+
+ @Test
+ public void logging() throws Exception {
+ LogCustomizer customLogs = LogCustomizer.forLogger(RDBConnectionHandler.class.getName()).enable(Level.TRACE)
+ .contains("while obtaining new").create();
+ DataSource ds = RDBDataSourceFactory.forJdbcUrl("jdbc:h2:mem:", "", "");
+ Connection c1 = null, c2 = null, c3 = null;
+
+ try (RDBConnectionHandler ch = new RDBConnectionHandler(ds)) {
+ customLogs.starting();
+ c1 = ch.getROConnection();
+ long ts = System.currentTimeMillis();
+ assertEquals(0, customLogs.getLogs().size());
+ c2 = ch.getROConnection();
+ // age threshold not reached
+ assertEquals(0, customLogs.getLogs().size());
+ while (System.currentTimeMillis() - ts < 21) {
+ // busy wait for LOGTHRESHOLD to pass
+ }
+ c3 = ch.getROConnection();
+ assertEquals(1, customLogs.getLogs().size());
+ // System.out.println(customLogs.getLogs());
+ } finally {
+ close(c1);
+ close(c2);
+ close(c3);
+ customLogs.finished();
+ }
+ }
+
+ private static void close(AutoCloseable c) {
+ if (c != null) {
+ try {
+ c.close();
+ } catch (Exception ex) {
+ }
+ }
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBConnectionHandlerTest.java
------------------------------------------------------------------------------
svn:eol-style = native