From d7727a0c02a293903a14d56db174a1c656e995dd Mon Sep 17 00:00:00 2001 From: wenshao Date: Tue, 28 Aug 2012 07:41:35 +0800 Subject: [PATCH] add sqlStat column, readBytesLength & readStringLength --- .../alibaba/druid/filter/stat/StatFilter.java | 86 ++++++++++++++- .../druid/proxy/jdbc/ResultSetProxy.java | 8 ++ .../druid/proxy/jdbc/ResultSetProxyImpl.java | 37 +++++-- .../com/alibaba/druid/stat/JdbcSqlStat.java | 31 +++++- .../support/http/resources/sql-detail.html | 10 ++ .../filter/StatFilterReadBytesLengthTest.java | 103 ++++++++++++++++++ .../StatFilterReadStringLengthTest.java | 97 +++++++++++++++++ 7 files changed, 362 insertions(+), 10 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/filter/StatFilterReadBytesLengthTest.java create mode 100644 src/test/java/com/alibaba/druid/bvt/filter/StatFilterReadStringLengthTest.java diff --git a/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java b/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java index d90d475a56..facb4864bc 100644 --- a/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java +++ b/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java @@ -16,6 +16,7 @@ package com.alibaba.druid.filter.stat; import java.io.InputStream; +import java.io.Reader; import java.sql.Blob; import java.sql.Clob; import java.sql.NClob; @@ -573,7 +574,18 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { sqlStat.addFetchRowCount(fetchRowCount); long stmtExecuteNano = resultSet.getStatementProxy().getLastExecuteTimeNano(); sqlStat.addResultSetHoldTimeNano(stmtExecuteNano, nanos); - sqlStat.addStringReadLength(resultSet.getReadStringLength()); + if (resultSet.getReadStringLength() > 0) { + sqlStat.addStringReadLength(resultSet.getReadStringLength()); + } + if (resultSet.getReadBytesLength() > 0) { + sqlStat.addReadBytesLength(resultSet.getReadBytesLength()); + } + if (resultSet.getOpenInputStreamCount() > 0) { + sqlStat.addInputStreamOpenCount(resultSet.getOpenInputStreamCount()); + } + if (resultSet.getOpenReaderCount() > 0) { + sqlStat.addReaderOpenCount(resultSet.getOpenReaderCount()); + } } } @@ -960,4 +972,76 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { return value; } + + @Override + public InputStream resultSet_getBinaryStream(FilterChain chain, ResultSetProxy result, int columnIndex) + throws SQLException { + InputStream input = chain.resultSet_getBinaryStream(result, columnIndex); + + if (input != null) { + result.incrementOpenInputStreamCount(); + } + + return input; + } + + @Override + public InputStream resultSet_getBinaryStream(FilterChain chain, ResultSetProxy result, String columnLabel) + throws SQLException { + InputStream input = chain.resultSet_getBinaryStream(result, columnLabel); + + if (input != null) { + result.incrementOpenInputStreamCount(); + } + + return input; + } + + @Override + public InputStream resultSet_getAsciiStream(FilterChain chain, ResultSetProxy result, int columnIndex) + throws SQLException { + InputStream input = chain.resultSet_getAsciiStream(result, columnIndex); + + if (input != null) { + result.incrementOpenInputStreamCount(); + } + + return input; + } + + @Override + public InputStream resultSet_getAsciiStream(FilterChain chain, ResultSetProxy result, String columnLabel) + throws SQLException { + InputStream input = chain.resultSet_getAsciiStream(result, columnLabel); + + if (input != null) { + result.incrementOpenInputStreamCount(); + } + + return input; + } + + @Override + public Reader resultSet_getCharacterStream(FilterChain chain, ResultSetProxy result, int columnIndex) + throws SQLException { + Reader reader = chain.resultSet_getCharacterStream(result, columnIndex); + + if (reader != null) { + result.incrementOpenReaderCount(); + } + + return reader; + } + + @Override + public Reader resultSet_getCharacterStream(FilterChain chain, ResultSetProxy result, String columnLabel) + throws SQLException { + Reader reader = chain.resultSet_getCharacterStream(result, columnLabel); + + if (reader != null) { + result.incrementOpenReaderCount(); + } + + return reader; + } } diff --git a/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxy.java b/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxy.java index 43d5521051..4b4e327d8d 100644 --- a/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxy.java +++ b/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxy.java @@ -51,4 +51,12 @@ public interface ResultSetProxy extends ResultSet, WrapperProxy { void addReadBytesLength(int length); long getReadBytesLength(); + + void incrementOpenInputStreamCount(); + + int getOpenInputStreamCount(); + + void incrementOpenReaderCount(); + + int getOpenReaderCount(); } diff --git a/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxyImpl.java b/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxyImpl.java index 3cc53b278b..ab54e36ada 100644 --- a/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxyImpl.java +++ b/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxyImpl.java @@ -51,14 +51,17 @@ public class ResultSetProxyImpl extends WrapperProxyImpl implements ResultSetPro private final StatementProxy statement; private final String sql; - protected int cursorIndex = 0; - protected int fetchRowCount = 0; + protected int cursorIndex = 0; + protected int fetchRowCount = 0; protected long constructNano; protected final JdbcSqlStat sqlStat; - private int closeCount = 0; + private int closeCount = 0; - private long readStringLength = 0; - private long readBytesLength = 0; + private long readStringLength = 0; + private long readBytesLength = 0; + + private int openInputStreamCount = 0; + private int openReaderCount = 0; public ResultSetProxyImpl(StatementProxy statement, ResultSet resultSet, long id, String sql){ super(resultSet, id); @@ -1090,15 +1093,35 @@ public class ResultSetProxyImpl extends WrapperProxyImpl implements ResultSetPro public long getReadStringLength() { return readStringLength; } - + @Override public void addReadBytesLength(int length) { this.readBytesLength += length; } - + @Override public long getReadBytesLength() { return readBytesLength; } + @Override + public void incrementOpenInputStreamCount() { + openInputStreamCount++; + } + + @Override + public int getOpenInputStreamCount() { + return openInputStreamCount; + } + + @Override + public void incrementOpenReaderCount() { + openReaderCount++; + } + + @Override + public int getOpenReaderCount() { + return openReaderCount; + } + } diff --git a/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java b/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java index 2cae8a2e21..2ab364dbd2 100644 --- a/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java +++ b/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java @@ -80,6 +80,9 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { private final AtomicLong readStringLength = new AtomicLong(); private final AtomicLong readBytesLength = new AtomicLong(); + private final AtomicLong inputStreamOpenCount = new AtomicLong(); + private final AtomicLong readerOpenCount = new AtomicLong(); + private final Histogram histogram = new Histogram(new long[] { // // 1, 10, 100, 1000, 10 * 1000, // @@ -230,6 +233,8 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { clobOpenCount.set(0); readStringLength.set(0); readBytesLength.set(0); + inputStreamOpenCount.set(0); + readerOpenCount.set(0); } public long getConcurrentMax() { @@ -299,9 +304,25 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { return readBytesLength.get(); } - public void addReadBytesLength(int length) { + public void addReadBytesLength(long length) { this.readBytesLength.addAndGet(length); } + + public long getReaderOpenCount() { + return readerOpenCount.get(); + } + + public void addReaderOpenCount(int count) { + this.readerOpenCount.addAndGet(count); + } + + public long getInputStreamOpenCount() { + return inputStreamOpenCount.get(); + } + + public void addInputStreamOpenCount(int count) { + this.inputStreamOpenCount.addAndGet(count); + } public long getId() { return id; @@ -530,6 +551,8 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { SimpleType.LONG, // SimpleType.LONG, // SimpleType.LONG, // + SimpleType.LONG, // + SimpleType.LONG, // }; @@ -586,7 +609,9 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { // 35 - "BlobOpenCount", // "ReadStringLength", // - "ReadBytesLength", + "ReadBytesLength", // + "InputStreamOpenCount", // + "ReaderOpenCount", // // }; @@ -662,6 +687,8 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { map.put("BlobOpenCount", getBlobOpenCount()); // 35 map.put("ReadStringLength", getReadStringLength()); // 36 map.put("ReadBytesLength", getReadBytesLength()); // 37 + map.put("InputStreamOpenCount", getInputStreamOpenCount()); // 38 + map.put("ReaderOpenCount", getReaderOpenCount()); // 39 return map; } diff --git a/src/main/resources/support/http/resources/sql-detail.html b/src/main/resources/support/http/resources/sql-detail.html index 57fdee1e49..b3ad5478b2 100644 --- a/src/main/resources/support/http/resources/sql-detail.html +++ b/src/main/resources/support/http/resources/sql-detail.html @@ -103,6 +103,14 @@ ClobOpenCount + + ReaderOpenCount + + + + InputStreamOpenCount + + ReadStringLength @@ -159,6 +167,8 @@ $("#BatchSizeTotal").text(sqlInfo.BatchSizeTotal) $("#BlobOpenCount").text(sqlInfo.BlobOpenCount) $("#ClobOpenCount").text(sqlInfo.ClobOpenCount) + $("#InputStreamOpenCount").text(sqlInfo.InputStreamOpenCount) + $("#ReaderOpenCount").text(sqlInfo.ReaderOpenCount) $("#ReadStringLength").text(sqlInfo.ReadStringLength) $("#ReadBytesLength").text(sqlInfo.ReadBytesLength) }, diff --git a/src/test/java/com/alibaba/druid/bvt/filter/StatFilterReadBytesLengthTest.java b/src/test/java/com/alibaba/druid/bvt/filter/StatFilterReadBytesLengthTest.java new file mode 100644 index 0000000000..2322a13f99 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/StatFilterReadBytesLengthTest.java @@ -0,0 +1,103 @@ +package com.alibaba.druid.bvt.filter; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.druid.filter.FilterAdapter; +import com.alibaba.druid.filter.FilterChain; +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.proxy.jdbc.ResultSetProxy; +import com.alibaba.druid.stat.JdbcSqlStat; +import com.alibaba.druid.util.JdbcUtils; + +public class StatFilterReadBytesLengthTest extends TestCase { + + private DruidDataSource dataSource; + + protected void setUp() throws Exception { + dataSource = new DruidDataSource(); + + dataSource.setUrl("jdbc:mock:xxx"); + dataSource.setFilters("stat"); + dataSource.setTestOnBorrow(false); + dataSource.getProxyFilters().add(new FilterAdapter() { + + @Override + public byte[] resultSet_getBytes(FilterChain chain, ResultSetProxy result, int columnIndex) + throws SQLException { + return new byte[6]; + } + + @Override + public byte[] resultSet_getBytes(FilterChain chain, ResultSetProxy result, String columnIndex) + throws SQLException { + return new byte[7]; + } + }); + + dataSource.init(); + } + + protected void tearDown() throws Exception { + JdbcUtils.close(dataSource); + } + + public void test_stat() throws Exception { + Connection conn = dataSource.getConnection(); + + String sql = "select 'x'"; + PreparedStatement stmt = conn.prepareStatement("select 'x'"); + + JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql); + + Assert.assertEquals(0, sqlStat.getReadStringLength()); + Assert.assertEquals(0, sqlStat.getReadBytesLength()); + + ResultSet rs = stmt.executeQuery(); + rs.next(); + rs.getBytes(1); + rs.close(); + stmt.close(); + + conn.close(); + + Assert.assertEquals(0, sqlStat.getReadStringLength()); + Assert.assertEquals(6, sqlStat.getReadBytesLength()); + + sqlStat.reset(); + Assert.assertEquals(0, sqlStat.getReadStringLength()); + Assert.assertEquals(0, sqlStat.getReadBytesLength()); + } + + public void test_stat_1() throws Exception { + Connection conn = dataSource.getConnection(); + + String sql = "select 'x'"; + PreparedStatement stmt = conn.prepareStatement("select 'x'"); + + JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql); + + Assert.assertEquals(0, sqlStat.getReadStringLength()); + Assert.assertEquals(0, sqlStat.getReadBytesLength()); + + ResultSet rs = stmt.executeQuery(); + rs.next(); + rs.getBytes("1"); + rs.close(); + stmt.close(); + + conn.close(); + + Assert.assertEquals(0, sqlStat.getReadStringLength()); + Assert.assertEquals(7, sqlStat.getReadBytesLength()); + + sqlStat.reset(); + Assert.assertEquals(0, sqlStat.getReadStringLength()); + Assert.assertEquals(0, sqlStat.getReadBytesLength()); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/filter/StatFilterReadStringLengthTest.java b/src/test/java/com/alibaba/druid/bvt/filter/StatFilterReadStringLengthTest.java new file mode 100644 index 0000000000..5ff79aab1c --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/StatFilterReadStringLengthTest.java @@ -0,0 +1,97 @@ +package com.alibaba.druid.bvt.filter; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.druid.filter.FilterAdapter; +import com.alibaba.druid.filter.FilterChain; +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.proxy.jdbc.ResultSetProxy; +import com.alibaba.druid.stat.JdbcSqlStat; +import com.alibaba.druid.util.JdbcUtils; + +public class StatFilterReadStringLengthTest extends TestCase { + + private DruidDataSource dataSource; + + protected void setUp() throws Exception { + dataSource = new DruidDataSource(); + + dataSource.setUrl("jdbc:mock:xxx"); + dataSource.setFilters("stat"); + dataSource.setTestOnBorrow(false); + dataSource.getProxyFilters().add(new FilterAdapter() { + + @Override + public String resultSet_getString(FilterChain chain, ResultSetProxy result, int columnIndex) + throws SQLException { + return "123456"; + } + + @Override + public String resultSet_getString(FilterChain chain, ResultSetProxy result, String columnIndex) + throws SQLException { + return "1234567"; + } + }); + + dataSource.init(); + } + + protected void tearDown() throws Exception { + JdbcUtils.close(dataSource); + } + + public void test_stat() throws Exception { + Connection conn = dataSource.getConnection(); + + String sql = "select 'x'"; + PreparedStatement stmt = conn.prepareStatement("select 'x'"); + + JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql); + + Assert.assertEquals(0, sqlStat.getReadStringLength()); + + ResultSet rs = stmt.executeQuery(); + rs.next(); + rs.getString(1); + rs.close(); + stmt.close(); + + conn.close(); + + Assert.assertEquals(6, sqlStat.getReadStringLength()); + + sqlStat.reset(); + Assert.assertEquals(0, sqlStat.getReadStringLength()); + } + + public void test_stat_1() throws Exception { + Connection conn = dataSource.getConnection(); + + String sql = "select 'x'"; + PreparedStatement stmt = conn.prepareStatement("select 'x'"); + + JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql); + + Assert.assertEquals(0, sqlStat.getReadStringLength()); + + ResultSet rs = stmt.executeQuery(); + rs.next(); + rs.getString("1"); + rs.close(); + stmt.close(); + + conn.close(); + + Assert.assertEquals(7, sqlStat.getReadStringLength()); + + sqlStat.reset(); + Assert.assertEquals(0, sqlStat.getReadStringLength()); + } +}