diff --git a/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java b/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java index db76323977..c8aa5d33b8 100644 --- a/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java +++ b/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java @@ -48,7 +48,7 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro protected StatementExecuteType lastExecuteType; - protected Integer updateCount = null; + protected Integer updateCount = null; private FilterChainImpl filterChain = null; @@ -319,9 +319,11 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro @Override public boolean getMoreResults() throws SQLException { - updateCount = null; FilterChainImpl chain = createChain(); boolean value = chain.statement_getMoreResults(this); + if (value) { + updateCount = null; + } recycleFilterChain(chain); return value; } @@ -549,21 +551,21 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro public boolean isFirstResultSet() { return firstResultSet; } - + @SuppressWarnings("unchecked") public T unwrap(Class iface) throws SQLException { if (iface == StatementProxy.class) { return (T) this; } - + return super.unwrap(iface); } - + public boolean isWrapperFor(Class iface) throws SQLException { if (iface == StatementProxy.class) { return true; } - + return super.isWrapperFor(iface); } diff --git a/src/main/java/com/alibaba/druid/support/http/stat/WebURIStat.java b/src/main/java/com/alibaba/druid/support/http/stat/WebURIStat.java index c32a5fd87c..54d18882d6 100644 --- a/src/main/java/com/alibaba/druid/support/http/stat/WebURIStat.java +++ b/src/main/java/com/alibaba/druid/support/http/stat/WebURIStat.java @@ -102,6 +102,32 @@ public class WebURIStat { private final static ThreadLocal currentLocal = new ThreadLocal(); + private volatile long histogram_0_1; + private volatile long histogram_1_10; + private volatile long histogram_10_100; + private volatile long histogram_100_1000; + private volatile int histogram_1000_10000; + private volatile int histogram_10000_100000; + private volatile int histogram_100000_1000000; + private volatile int histogram_1000000_more; + + final static AtomicLongFieldUpdater histogram_0_1_Updater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "histogram_0_1"); + final static AtomicLongFieldUpdater histogram_1_10_Updater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "histogram_1_10"); + final static AtomicLongFieldUpdater histogram_10_100_Updater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "histogram_10_100"); + final static AtomicLongFieldUpdater histogram_100_1000_Updater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "histogram_100_1000"); + final static AtomicIntegerFieldUpdater histogram_1000_10000_Updater = AtomicIntegerFieldUpdater.newUpdater(WebURIStat.class, + "histogram_1000_10000"); + final static AtomicIntegerFieldUpdater histogram_10000_100000_Updater = AtomicIntegerFieldUpdater.newUpdater(WebURIStat.class, + "histogram_10000_100000"); + final static AtomicIntegerFieldUpdater histogram_100000_1000000_Updater = AtomicIntegerFieldUpdater.newUpdater(WebURIStat.class, + "histogram_100000_1000000"); + final static AtomicIntegerFieldUpdater histogram_1000000_more_Updater = AtomicIntegerFieldUpdater.newUpdater(WebURIStat.class, + "histogram_1000000_more"); + public WebURIStat(String uri){ super(); this.uri = uri; @@ -145,6 +171,8 @@ public class WebURIStat { runningCountUpdater.decrementAndGet(this); requestTimeNanoUpdater.addAndGet(this, nanos); + histogramRecord(nanos); + if (error != null) { errorCountUpdater.incrementAndGet(this); } @@ -212,6 +240,28 @@ public class WebURIStat { currentLocal.set(null); } + private void histogramRecord(long nanos) { + final long millis = nanos / 1000 / 1000; + + if (millis < 1) { + histogram_0_1_Updater.incrementAndGet(this); + } else if (millis < 10) { + histogram_1_10_Updater.incrementAndGet(this); + } else if (millis < 100) { + histogram_10_100_Updater.incrementAndGet(this); + } else if (millis < 1000) { + histogram_100_1000_Updater.incrementAndGet(this); + } else if (millis < 10000) { + histogram_1000_10000_Updater.incrementAndGet(this); + } else if (millis < 100000) { + histogram_10000_100000_Updater.incrementAndGet(this); + } else if (millis < 1000000) { + histogram_100000_1000000_Updater.incrementAndGet(this); + } else { + histogram_1000000_more_Updater.incrementAndGet(this); + } + } + public int getRunningCount() { return this.runningCount; } @@ -364,6 +414,20 @@ public class WebURIStat { return profiletat; } + public long[] getHistogramValues() { + return new long[] { + // + histogram_0_1, // + histogram_1_10, // + histogram_10_100, // + histogram_100_1000, // + histogram_1000_10000, // + histogram_10000_100000, // + histogram_100000_1000000, // + histogram_1000000_more // + }; + } + public WebURIStatValue getValue(boolean reset) { WebURIStatValue val = new WebURIStatValue(); @@ -399,11 +463,20 @@ public class WebURIStat { val.setLastAccessTimeMillis(get(this, lastAccessTimeMillisUpdater, reset)); val.setProfileEntryStatValueList(this.getProfiletat().getStatValue(reset)); + + val.histogram_0_1 = get(this, histogram_0_1_Updater, reset); + val.histogram_1_10 = get(this, histogram_1_10_Updater, reset); + val.histogram_10_100 = get(this, histogram_10_100_Updater, reset); + val.histogram_100_1000 = get(this, histogram_100_1000_Updater, reset); + val.histogram_1000_10000 = get(this, histogram_1000_10000_Updater, reset); + val.histogram_10000_100000 = get(this, histogram_10000_100000_Updater, reset); + val.histogram_100000_1000000 = get(this, histogram_100000_1000000_Updater, reset); + val.histogram_1000000_more = get(this, histogram_1000000_more_Updater, reset); return val; } public Map getStatData() { - return getValue(false).getStatData(); + return getValue(false).getStatData(); } } diff --git a/src/main/java/com/alibaba/druid/support/http/stat/WebURIStatValue.java b/src/main/java/com/alibaba/druid/support/http/stat/WebURIStatValue.java index 13434cc1af..712f9abf63 100644 --- a/src/main/java/com/alibaba/druid/support/http/stat/WebURIStatValue.java +++ b/src/main/java/com/alibaba/druid/support/http/stat/WebURIStatValue.java @@ -58,6 +58,27 @@ public class WebURIStatValue { private List profileEntryStatValueList; + protected long histogram_0_1; + protected long histogram_1_10; + protected long histogram_10_100; + protected long histogram_100_1000; + protected int histogram_1000_10000; + protected int histogram_10000_100000; + protected int histogram_100000_1000000; + protected int histogram_1000000_more; + + public long[] getHistogram() { + return new long[] { histogram_0_1, // + histogram_1_10, // + histogram_10_100, // + histogram_100_1000, // + histogram_1000_10000, // + histogram_10000_100000, // + histogram_100000_1000000, // + histogram_1000000_more, // + }; + } + public List getProfileEntryStatValueList() { return profileEntryStatValueList; } @@ -280,6 +301,7 @@ public class WebURIStatValue { data.put("JdbcResultSetOpenCount", this.getJdbcResultSetOpenCount()); data.put("JdbcResultSetCloseCount", this.getJdbcResultSetCloseCount()); + data.put("Histogram", this.getHistogram()); if (this.profileEntryStatValueList != null) { int size = profileEntryStatValueList.size(); diff --git a/src/main/java/com/alibaba/druid/support/logging/LogFactory.java b/src/main/java/com/alibaba/druid/support/logging/LogFactory.java index 63effb848c..2ccaf7e95f 100644 --- a/src/main/java/com/alibaba/druid/support/logging/LogFactory.java +++ b/src/main/java/com/alibaba/druid/support/logging/LogFactory.java @@ -1,101 +1,101 @@ -/* - * Copyright 1999-2011 Alibaba Group Holding Ltd. - * - * Licensed 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 com.alibaba.druid.support.logging; - -import java.lang.reflect.Constructor; - -@SuppressWarnings("rawtypes") -public class LogFactory { - - private static Constructor logConstructor; - - static { - // TODO add slf4j logging - - // 优先选择log4j,而非Apache Common Logging. 因为后者无法设置真实Log调用者的信息 - tryImplementation("org.slf4j.Logger", "com.alibaba.druid.support.logging.SLF4JImpl"); - tryImplementation("org.apache.log4j.Logger", "com.alibaba.druid.support.logging.Log4jImpl"); - tryImplementation("java.util.logging.Logger", "com.alibaba.druid.support.logging.Jdk14LoggingImpl"); - tryImplementation("org.apache.commons.logging.LogFactory", - "com.alibaba.druid.support.logging.JakartaCommonsLoggingImpl"); - - if (logConstructor == null) { - try { - logConstructor = NoLoggingImpl.class.getConstructor(String.class); - } catch (Exception e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - } - - @SuppressWarnings("unchecked") - private static void tryImplementation(String testClassName, String implClassName) { - if (logConstructor != null) { - return; - } - - try { - Resources.classForName(testClassName); - Class implClass = Resources.classForName(implClassName); - logConstructor = implClass.getConstructor(new Class[] { String.class }); - - Class declareClass = logConstructor.getDeclaringClass(); - if (!Log.class.isAssignableFrom(declareClass)) { - logConstructor = null; - } - - try { - logConstructor.newInstance(LogFactory.class.getName()); - } catch (Throwable t) { - logConstructor = null; - } - } catch (Throwable t) { - // skip - } - } - - public static Log getLog(Class clazz) { - return getLog(clazz.getName()); - } - - public static Log getLog(String loggerName) { - try { - return (Log) logConstructor.newInstance(new Object[] { loggerName }); - } catch (Throwable t) { - throw new RuntimeException("Error creating logger for logger '" + loggerName + "'. Cause: " + t, t); - } - } - - @SuppressWarnings("unchecked") - public static synchronized void selectLog4JLogging() { - try { - Resources.classForName("org.apache.log4j.Logger"); - Class implClass = Resources.classForName("com.alibaba.druid.support.logging.Log4jImpl"); - logConstructor = implClass.getConstructor(new Class[] { String.class }); - } catch (Throwable t) { - } - } - - @SuppressWarnings("unchecked") - public static synchronized void selectJavaLogging() { - try { - Resources.classForName("java.util.logging.Logger"); - Class implClass = Resources.classForName("com.alibaba.druid.support.logging.Jdk14LoggingImpl"); - logConstructor = implClass.getConstructor(new Class[] { String.class }); - } catch (Throwable t) { - } - } -} +/* + * Copyright 1999-2011 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.druid.support.logging; + +import java.lang.reflect.Constructor; + +@SuppressWarnings("rawtypes") +public class LogFactory { + + private static Constructor logConstructor; + + static { + // TODO add slf4j logging + + // 优先选择log4j,而非Apache Common Logging. 因为后者无法设置真实Log调用者的信息 + tryImplementation("org.apache.log4j.Logger", "com.alibaba.druid.support.logging.Log4jImpl"); + tryImplementation("org.slf4j.Logger", "com.alibaba.druid.support.logging.SLF4JImpl"); + tryImplementation("org.apache.commons.logging.LogFactory", + "com.alibaba.druid.support.logging.JakartaCommonsLoggingImpl"); + tryImplementation("java.util.logging.Logger", "com.alibaba.druid.support.logging.Jdk14LoggingImpl"); + + if (logConstructor == null) { + try { + logConstructor = NoLoggingImpl.class.getConstructor(String.class); + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + } + + @SuppressWarnings("unchecked") + private static void tryImplementation(String testClassName, String implClassName) { + if (logConstructor != null) { + return; + } + + try { + Resources.classForName(testClassName); + Class implClass = Resources.classForName(implClassName); + logConstructor = implClass.getConstructor(new Class[] { String.class }); + + Class declareClass = logConstructor.getDeclaringClass(); + if (!Log.class.isAssignableFrom(declareClass)) { + logConstructor = null; + } + + try { + logConstructor.newInstance(LogFactory.class.getName()); + } catch (Throwable t) { + logConstructor = null; + } + } catch (Throwable t) { + // skip + } + } + + public static Log getLog(Class clazz) { + return getLog(clazz.getName()); + } + + public static Log getLog(String loggerName) { + try { + return (Log) logConstructor.newInstance(new Object[] { loggerName }); + } catch (Throwable t) { + throw new RuntimeException("Error creating logger for logger '" + loggerName + "'. Cause: " + t, t); + } + } + + @SuppressWarnings("unchecked") + public static synchronized void selectLog4JLogging() { + try { + Resources.classForName("org.apache.log4j.Logger"); + Class implClass = Resources.classForName("com.alibaba.druid.support.logging.Log4jImpl"); + logConstructor = implClass.getConstructor(new Class[] { String.class }); + } catch (Throwable t) { + } + } + + @SuppressWarnings("unchecked") + public static synchronized void selectJavaLogging() { + try { + Resources.classForName("java.util.logging.Logger"); + Class implClass = Resources.classForName("com.alibaba.druid.support.logging.Jdk14LoggingImpl"); + logConstructor = implClass.getConstructor(new Class[] { String.class }); + } catch (Throwable t) { + } + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_db2_0.java b/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_db2_0.java index d59158a1fa..ca10383607 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_db2_0.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_db2_0.java @@ -21,7 +21,7 @@ public class PagerUtilsTest_Limit_db2_0 extends TestCase { String sql = "select * from t"; String result = PagerUtils.limit(sql, JdbcConstants.DB2, 10, 10); Assert.assertEquals("SELECT *"// - + "\nFROM (SELECT *, ROW_NUMBER() AS ROWNUM"// + + "\nFROM (SELECT *, ROW_NUMBER() OVER () AS ROWNUM"// + "\n\tFROM t"// + "\n\t) XX"// + "\nWHERE ROWNUM > 10"// @@ -32,7 +32,7 @@ public class PagerUtilsTest_Limit_db2_0 extends TestCase { String sql = "select * from t where age > 100"; String result = PagerUtils.limit(sql, JdbcConstants.DB2, 20, 10); Assert.assertEquals("SELECT *"// - + "\nFROM (SELECT *, ROW_NUMBER() AS ROWNUM"// + + "\nFROM (SELECT *, ROW_NUMBER() OVER () AS ROWNUM"// + "\n\tFROM t"// + "\n\tWHERE age > 100"// + "\n\t) XX"//