diff --git a/src/main/java/com/alibaba/druid/pool/ha/HADataSource.java b/src/main/java/com/alibaba/druid/pool/ha/HADataSource.java new file mode 100644 index 0000000000..d955d4aff1 --- /dev/null +++ b/src/main/java/com/alibaba/druid/pool/ha/HADataSource.java @@ -0,0 +1,89 @@ +/* + * 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.pool.ha; + +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.util.logging.Logger; + +import javax.sql.DataSource; + +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.pool.WrapperAdapter; + +public class HADataSource extends WrapperAdapter implements DataSource { + + private int loginTimeSeconds; + + protected PrintWriter logWriter = new PrintWriter(System.out); + + private DruidDataSource master; + private DruidDataSource second; + + public DruidDataSource getMaster() { + return master; + } + + public void setMaster(DruidDataSource master) { + this.master = master; + } + + public DruidDataSource getSecond() { + return second; + } + + public void setSecond(DruidDataSource second) { + this.second = second; + } + + @Override + public PrintWriter getLogWriter() throws SQLException { + return logWriter; + } + + @Override + public void setLogWriter(PrintWriter out) throws SQLException { + this.logWriter = out; + } + + @Override + public void setLoginTimeout(int seconds) throws SQLException { + this.loginTimeSeconds = seconds; + } + + @Override + public int getLoginTimeout() throws SQLException { + return loginTimeSeconds; + } + + @Override + public Logger getParentLogger() throws SQLFeatureNotSupportedException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Connection getConnection() throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Connection getConnection(String username, String password) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + +} diff --git a/src/main/java/com/alibaba/druid/support/spring/stat/SpringMethodStat.java b/src/main/java/com/alibaba/druid/support/spring/stat/SpringMethodStat.java index cc9b259103..736fe6ff2a 100644 --- a/src/main/java/com/alibaba/druid/support/spring/stat/SpringMethodStat.java +++ b/src/main/java/com/alibaba/druid/support/spring/stat/SpringMethodStat.java @@ -15,48 +15,124 @@ */ package com.alibaba.druid.support.spring.stat; +import static com.alibaba.druid.util.JdbcSqlStatUtils.get; + import java.util.Date; -import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicLongFieldUpdater; import com.alibaba.druid.support.profile.Profiler; public class SpringMethodStat { - private final static ThreadLocal currentLocal = new ThreadLocal(); + private final static ThreadLocal currentLocal = new ThreadLocal(); - private final SpringMethodInfo methodInfo; + private final SpringMethodInfo methodInfo; - private final AtomicInteger runningCount = new AtomicInteger(); - private final AtomicInteger concurrentMax = new AtomicInteger(); - private final AtomicLong executeCount = new AtomicLong(0); - private final AtomicLong executeErrorCount = new AtomicLong(0); - private final AtomicLong executeTimeNano = new AtomicLong(); + private final AtomicInteger runningCount = new AtomicInteger(); + private final AtomicInteger concurrentMax = new AtomicInteger(); + private final AtomicLong executeCount = new AtomicLong(0); + private final AtomicLong executeErrorCount = new AtomicLong(0); + private final AtomicLong executeTimeNano = new AtomicLong(); - private final AtomicLong jdbcFetchRowCount = new AtomicLong(); - private final AtomicLong jdbcUpdateCount = new AtomicLong(); - private final AtomicLong jdbcExecuteCount = new AtomicLong(); - private final AtomicLong jdbcExecuteErrorCount = new AtomicLong(); - private final AtomicLong jdbcExecuteTimeNano = new AtomicLong(); + private final AtomicLong jdbcFetchRowCount = new AtomicLong(); + private final AtomicLong jdbcUpdateCount = new AtomicLong(); + private final AtomicLong jdbcExecuteCount = new AtomicLong(); + private final AtomicLong jdbcExecuteErrorCount = new AtomicLong(); + private final AtomicLong jdbcExecuteTimeNano = new AtomicLong(); - private final AtomicLong jdbcCommitCount = new AtomicLong(); - private final AtomicLong jdbcRollbackCount = new AtomicLong(); + private final AtomicLong jdbcCommitCount = new AtomicLong(); + private final AtomicLong jdbcRollbackCount = new AtomicLong(); - private final AtomicLong jdbcPoolConnectionOpenCount = new AtomicLong(); - private final AtomicLong jdbcPoolConnectionCloseCount = new AtomicLong(); + private final AtomicLong jdbcPoolConnectionOpenCount = new AtomicLong(); + private final AtomicLong jdbcPoolConnectionCloseCount = new AtomicLong(); - private final AtomicLong jdbcResultSetOpenCount = new AtomicLong(); - private final AtomicLong jdbcResultSetCloseCount = new AtomicLong(); + private final AtomicLong jdbcResultSetOpenCount = new AtomicLong(); + private final AtomicLong jdbcResultSetCloseCount = new AtomicLong(); - private volatile Throwable lastError; - private volatile long lastErrorTimeMillis; + private volatile Throwable lastError; + private volatile long lastErrorTimeMillis; + + 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(SpringMethodStat.class, + "histogram_0_1"); + final static AtomicLongFieldUpdater histogram_1_10_Updater = AtomicLongFieldUpdater.newUpdater(SpringMethodStat.class, + "histogram_1_10"); + final static AtomicLongFieldUpdater histogram_10_100_Updater = AtomicLongFieldUpdater.newUpdater(SpringMethodStat.class, + "histogram_10_100"); + final static AtomicLongFieldUpdater histogram_100_1000_Updater = AtomicLongFieldUpdater.newUpdater(SpringMethodStat.class, + "histogram_100_1000"); + final static AtomicIntegerFieldUpdater histogram_1000_10000_Updater = AtomicIntegerFieldUpdater.newUpdater(SpringMethodStat.class, + "histogram_1000_10000"); + final static AtomicIntegerFieldUpdater histogram_10000_100000_Updater = AtomicIntegerFieldUpdater.newUpdater(SpringMethodStat.class, + "histogram_10000_100000"); + final static AtomicIntegerFieldUpdater histogram_100000_1000000_Updater = AtomicIntegerFieldUpdater.newUpdater(SpringMethodStat.class, + "histogram_100000_1000000"); + final static AtomicIntegerFieldUpdater histogram_1000000_more_Updater = AtomicIntegerFieldUpdater.newUpdater(SpringMethodStat.class, + "histogram_1000000_more"); public SpringMethodStat(SpringMethodInfo methodInfo){ this.methodInfo = methodInfo; } + public SpringMethodStatValue getStatValue(boolean reset) { + SpringMethodStatValue val = new SpringMethodStatValue(); + + val.setClassName(this.getMethodInfo().getClassName()); + val.setSignature(this.getMethodInfo().getSignature()); + + val.setRunningCount(this.getRunningCount()); + + val.setConcurrentMax(get(this.concurrentMax, reset)); + val.setExecuteCount(get(this.executeCount, reset)); + val.setExecuteErrorCount(get(this.executeErrorCount, reset)); + val.setExecuteTimeNano(get(this.executeTimeNano, reset)); + + val.setJdbcFetchRowCount(get(this.jdbcFetchRowCount, reset)); + val.setJdbcUpdateCount(get(this.jdbcUpdateCount, reset)); + val.setJdbcExecuteCount(get(this.jdbcExecuteCount, reset)); + val.setJdbcExecuteErrorCount(get(this.jdbcExecuteErrorCount, reset)); + val.setJdbcExecuteTimeNano(get(this.jdbcExecuteTimeNano, reset)); + + val.setJdbcCommitCount(get(this.jdbcCommitCount, reset)); + val.setJdbcRollbackCount(get(this.jdbcRollbackCount, reset)); + + val.setJdbcPoolConnectionOpenCount(get(this.jdbcPoolConnectionOpenCount, reset)); + val.setJdbcPoolConnectionCloseCount(get(this.jdbcPoolConnectionCloseCount, reset)); + + val.setJdbcResultSetOpenCount(get(this.jdbcResultSetOpenCount, reset)); + val.setJdbcResultSetCloseCount(get(this.jdbcResultSetCloseCount, reset)); + + val.setLastError(this.lastError); + val.setLastErrorTimeMillis(this.lastErrorTimeMillis); + if (reset) { + this.lastError = null; + this.lastErrorTimeMillis = 0; + } + + 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 void reset() { concurrentMax.set(0); executeCount.set(0); @@ -80,6 +156,15 @@ public class SpringMethodStat { lastError = null; lastErrorTimeMillis = 0; + + histogram_0_1_Updater.set(this, 0); + histogram_1_10_Updater.set(this, 0); + histogram_10_100_Updater.set(this, 0); + histogram_100_1000_Updater.set(this, 0); + histogram_1000_10000_Updater.set(this, 0); + histogram_10000_100000_Updater.set(this, 0); + histogram_100000_1000000_Updater.set(this, 0); + histogram_1000000_more_Updater.set(this, 0); } public SpringMethodInfo getMethodInfo() { @@ -120,16 +205,53 @@ public class SpringMethodStat { public void afterInvoke(Throwable error, long nanos) { runningCount.decrementAndGet(); executeTimeNano.addAndGet(nanos); + histogramRecord(nanos); if (error != null) { executeErrorCount.incrementAndGet(); lastError = error; lastErrorTimeMillis = System.currentTimeMillis(); } - + Profiler.release(nanos); } + 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 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 Throwable getLastError() { return lastError; } @@ -150,7 +272,7 @@ public class SpringMethodStat { return this.runningCount.get(); } - public long getConcurrentMax() { + public int getConcurrentMax() { return concurrentMax.get(); } @@ -295,35 +417,6 @@ public class SpringMethodStat { } public Map getStatData() { - Map data = new LinkedHashMap(); - - data.put("Class", this.getMethodInfo().getClassName()); - data.put("Method", this.getMethodInfo().getSignature()); - - data.put("RunningCount", this.getRunningCount()); - data.put("ConcurrentMax", this.getConcurrentMax()); - data.put("ExecuteCount", this.getExecuteCount()); - data.put("ExecuteErrorCount", this.getExecuteErrorCount()); - data.put("ExecuteTimeMillis", this.getExecuteTimeMillis()); - - data.put("JdbcCommitCount", this.getJdbcCommitCount()); - data.put("JdbcRollbackCount", this.getJdbcRollbackCount()); - - data.put("JdbcPoolConnectionOpenCount", this.getJdbcPoolConnectionOpenCount()); - data.put("JdbcPoolConnectionCloseCount", this.getJdbcPoolConnectionCloseCount()); - - data.put("JdbcResultSetOpenCount", this.getJdbcResultSetOpenCount()); - data.put("JdbcResultSetCloseCount", this.getJdbcResultSetCloseCount()); - - data.put("JdbcExecuteCount", this.getJdbcExecuteCount()); - data.put("JdbcExecuteErrorCount", this.getJdbcExecuteErrorCount()); - data.put("JdbcExecuteTimeMillis", this.getJdbcExecuteTimeMillis()); - data.put("JdbcFetchRowCount", this.getJdbcFetchRowCount()); - data.put("JdbcUpdateCount", this.getJdbcUpdateCount()); - - data.put("LastError", this.getLastError()); - data.put("LastErrorTime", this.getLastErrorTime()); - - return data; + return getStatValue(false).getData(); } } diff --git a/src/main/java/com/alibaba/druid/support/spring/stat/SpringMethodStatValue.java b/src/main/java/com/alibaba/druid/support/spring/stat/SpringMethodStatValue.java new file mode 100644 index 0000000000..a83d96589d --- /dev/null +++ b/src/main/java/com/alibaba/druid/support/spring/stat/SpringMethodStatValue.java @@ -0,0 +1,284 @@ +/* + * 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.spring.stat; + +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.Map; + +public class SpringMethodStatValue { + + private String className; + private String signature; + + private int runningCount; + private int concurrentMax; + private long executeCount; + private long executeErrorCount; + private long executeTimeNano; + + private long jdbcFetchRowCount; + private long jdbcUpdateCount; + private long jdbcExecuteCount; + private long jdbcExecuteErrorCount; + private long jdbcExecuteTimeNano; + + private long jdbcCommitCount; + private long jdbcRollbackCount; + + private long jdbcPoolConnectionOpenCount; + private long jdbcPoolConnectionCloseCount; + + private long jdbcResultSetOpenCount; + private long jdbcResultSetCloseCount; + + private Throwable lastError; + private long lastErrorTimeMillis; + + long histogram_0_1; + long histogram_1_10; + long histogram_10_100; + long histogram_100_1000; + int histogram_1000_10000; + int histogram_10000_100000; + int histogram_100000_1000000; + int histogram_1000000_more; + + public String getClassName() { + return className; + } + + public void setClassName(String className) { + this.className = className; + } + + public String getSignature() { + return signature; + } + + public void setSignature(String signature) { + this.signature = signature; + } + + public int getRunningCount() { + return runningCount; + } + + public void setRunningCount(int runningCount) { + this.runningCount = runningCount; + } + + public int getConcurrentMax() { + return concurrentMax; + } + + public void setConcurrentMax(int concurrentMax) { + this.concurrentMax = concurrentMax; + } + + public long getExecuteCount() { + return executeCount; + } + + public void setExecuteCount(long executeCount) { + this.executeCount = executeCount; + } + + public long getExecuteErrorCount() { + return executeErrorCount; + } + + public void setExecuteErrorCount(long executeErrorCount) { + this.executeErrorCount = executeErrorCount; + } + + public long getExecuteTimeNano() { + return executeTimeNano; + } + + public void setExecuteTimeNano(long executeTimeNano) { + this.executeTimeNano = executeTimeNano; + } + + public long getJdbcFetchRowCount() { + return jdbcFetchRowCount; + } + + public void setJdbcFetchRowCount(long jdbcFetchRowCount) { + this.jdbcFetchRowCount = jdbcFetchRowCount; + } + + public long getJdbcUpdateCount() { + return jdbcUpdateCount; + } + + public void setJdbcUpdateCount(long jdbcUpdateCount) { + this.jdbcUpdateCount = jdbcUpdateCount; + } + + public long getJdbcExecuteCount() { + return jdbcExecuteCount; + } + + public void setJdbcExecuteCount(long jdbcExecuteCount) { + this.jdbcExecuteCount = jdbcExecuteCount; + } + + public long getJdbcExecuteErrorCount() { + return jdbcExecuteErrorCount; + } + + public void setJdbcExecuteErrorCount(long jdbcExecuteErrorCount) { + this.jdbcExecuteErrorCount = jdbcExecuteErrorCount; + } + + public long getJdbcExecuteTimeNano() { + return jdbcExecuteTimeNano; + } + + public void setJdbcExecuteTimeNano(long jdbcExecuteTimeNano) { + this.jdbcExecuteTimeNano = jdbcExecuteTimeNano; + } + + public long getJdbcCommitCount() { + return jdbcCommitCount; + } + + public void setJdbcCommitCount(long jdbcCommitCount) { + this.jdbcCommitCount = jdbcCommitCount; + } + + public long getJdbcRollbackCount() { + return jdbcRollbackCount; + } + + public void setJdbcRollbackCount(long jdbcRollbackCount) { + this.jdbcRollbackCount = jdbcRollbackCount; + } + + public long getJdbcPoolConnectionOpenCount() { + return jdbcPoolConnectionOpenCount; + } + + public void setJdbcPoolConnectionOpenCount(long jdbcPoolConnectionOpenCount) { + this.jdbcPoolConnectionOpenCount = jdbcPoolConnectionOpenCount; + } + + public long getJdbcPoolConnectionCloseCount() { + return jdbcPoolConnectionCloseCount; + } + + public void setJdbcPoolConnectionCloseCount(long jdbcPoolConnectionCloseCount) { + this.jdbcPoolConnectionCloseCount = jdbcPoolConnectionCloseCount; + } + + public long getJdbcResultSetOpenCount() { + return jdbcResultSetOpenCount; + } + + public void setJdbcResultSetOpenCount(long jdbcResultSetOpenCount) { + this.jdbcResultSetOpenCount = jdbcResultSetOpenCount; + } + + public long getJdbcResultSetCloseCount() { + return jdbcResultSetCloseCount; + } + + public void setJdbcResultSetCloseCount(long jdbcResultSetCloseCount) { + this.jdbcResultSetCloseCount = jdbcResultSetCloseCount; + } + + public Throwable getLastError() { + return lastError; + } + + public void setLastError(Throwable lastError) { + this.lastError = lastError; + } + + public long getLastErrorTimeMillis() { + return lastErrorTimeMillis; + } + + public void setLastErrorTimeMillis(long lastErrorTimeMillis) { + this.lastErrorTimeMillis = lastErrorTimeMillis; + } + + public long getExecuteTimeMillis() { + return getExecuteTimeNano() / (1000 * 1000); + } + + public long getJdbcExecuteTimeMillis() { + return getJdbcExecuteTimeNano() / (1000 * 1000); + } + + public Date getLastErrorTime() { + if (lastErrorTimeMillis <= 0) { + return null; + } + + return new Date(lastErrorTimeMillis); + } + + 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 Map getData() { + Map data = new LinkedHashMap(); + + data.put("Class", this.getClassName()); + data.put("Method", this.getSignature()); + + data.put("RunningCount", this.getRunningCount()); + data.put("ConcurrentMax", this.getConcurrentMax()); + data.put("ExecuteCount", this.getExecuteCount()); + data.put("ExecuteErrorCount", this.getExecuteErrorCount()); + data.put("ExecuteTimeMillis", this.getExecuteTimeMillis()); + + data.put("JdbcCommitCount", this.getJdbcCommitCount()); + data.put("JdbcRollbackCount", this.getJdbcRollbackCount()); + + data.put("JdbcPoolConnectionOpenCount", this.getJdbcPoolConnectionOpenCount()); + data.put("JdbcPoolConnectionCloseCount", this.getJdbcPoolConnectionCloseCount()); + + data.put("JdbcResultSetOpenCount", this.getJdbcResultSetOpenCount()); + data.put("JdbcResultSetCloseCount", this.getJdbcResultSetCloseCount()); + + data.put("JdbcExecuteCount", this.getJdbcExecuteCount()); + data.put("JdbcExecuteErrorCount", this.getJdbcExecuteErrorCount()); + data.put("JdbcExecuteTimeMillis", this.getJdbcExecuteTimeMillis()); + data.put("JdbcFetchRowCount", this.getJdbcFetchRowCount()); + data.put("JdbcUpdateCount", this.getJdbcUpdateCount()); + + data.put("LastError", this.getLastError()); + data.put("LastErrorTime", this.getLastErrorTime()); + + data.put("Histogram", this.getHistogram()); + + return data; + } +}