diff --git a/src/main/java/com/alibaba/druid/support/monitor/MonitorClient.java b/src/main/java/com/alibaba/druid/support/monitor/MonitorClient.java index f60b28288e..4fab9c55a0 100644 --- a/src/main/java/com/alibaba/druid/support/monitor/MonitorClient.java +++ b/src/main/java/com/alibaba/druid/support/monitor/MonitorClient.java @@ -18,6 +18,7 @@ package com.alibaba.druid.support.monitor; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; @@ -26,6 +27,7 @@ import java.util.concurrent.TimeUnit; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.pool.DruidDataSourceStatValue; import com.alibaba.druid.stat.DruidDataSourceStatManager; +import com.alibaba.druid.stat.JdbcSqlStatValue; import com.alibaba.druid.support.http.stat.WebAppStat; import com.alibaba.druid.support.http.stat.WebAppStatManager; import com.alibaba.druid.support.http.stat.WebAppStatValue; @@ -153,6 +155,10 @@ public class MonitorClient { dao.saveWebURI(ctx, webURIValueList); dao.saveWebApp(ctx, webAppStatValueList); } + + public List loadSqlList(Map filters) { + return dao.loadSqlList(filters); + } public MonitorDao getDao() { return dao; diff --git a/src/main/java/com/alibaba/druid/support/monitor/MonitorContext.java b/src/main/java/com/alibaba/druid/support/monitor/MonitorContext.java index d7e6f5d03c..3ae60f3389 100644 --- a/src/main/java/com/alibaba/druid/support/monitor/MonitorContext.java +++ b/src/main/java/com/alibaba/druid/support/monitor/MonitorContext.java @@ -21,11 +21,11 @@ import java.util.Map; public class MonitorContext { - private final Map atrributes = new HashMap(); + private final Map atrributes = new HashMap(); - private String domainName; - private String appName; - private String clusterName; + private String domainName = "defaultDomain"; + private String appName = "defaultApp"; + private String clusterName = "defaultCluster"; private String host; private int pid; diff --git a/src/main/java/com/alibaba/druid/support/monitor/dao/MonitorDao.java b/src/main/java/com/alibaba/druid/support/monitor/dao/MonitorDao.java index 6de46f3551..0cc7558857 100644 --- a/src/main/java/com/alibaba/druid/support/monitor/dao/MonitorDao.java +++ b/src/main/java/com/alibaba/druid/support/monitor/dao/MonitorDao.java @@ -16,8 +16,10 @@ package com.alibaba.druid.support.monitor.dao; import java.util.List; +import java.util.Map; import com.alibaba.druid.pool.DruidDataSourceStatValue; +import com.alibaba.druid.stat.JdbcSqlStatValue; import com.alibaba.druid.support.http.stat.WebAppStatValue; import com.alibaba.druid.support.http.stat.WebURIStatValue; import com.alibaba.druid.support.monitor.MonitorContext; @@ -32,4 +34,6 @@ public interface MonitorDao { void saveWebURI(MonitorContext ctx, List uriList); void saveWebApp(MonitorContext ctx, List uriList); + + List loadSqlList(Map filters); } diff --git a/src/main/java/com/alibaba/druid/support/monitor/dao/MonitorDaoJdbcImpl.java b/src/main/java/com/alibaba/druid/support/monitor/dao/MonitorDaoJdbcImpl.java index b52458185f..e3977db77a 100644 --- a/src/main/java/com/alibaba/druid/support/monitor/dao/MonitorDaoJdbcImpl.java +++ b/src/main/java/com/alibaba/druid/support/monitor/dao/MonitorDaoJdbcImpl.java @@ -18,12 +18,16 @@ package com.alibaba.druid.support.monitor.dao; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.sql.Types; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; import javax.sql.DataSource; @@ -88,6 +92,216 @@ public class MonitorDaoJdbcImpl implements MonitorDao { save(webAppStatBeanInfo, ctx, list); } + @SuppressWarnings("unchecked") + public List loadSqlList(Map filters) { + return ((List) load(sqlStatBeanInfo, filters)); + } + + static Integer getInteger(Map filters, String key) { + Object value = filters.get(key); + + if (value == null) { + return null; + } + + if (value instanceof Integer) { + return (Integer) value; + } + + if (value instanceof Number) { + return ((Number) value).intValue(); + } + + if (value instanceof String) { + + String text = (String) value; + if (StringUtils.isEmpty(text)) { + return null; + } + + return Integer.parseInt(text); + } + + return null; + } + + static Date getDate(Map filters, String key) { + Object value = filters.get(key); + + if (value == null) { + return null; + } + + if (value instanceof Number) { + long millis = ((Number) value).longValue(); + return new Date(millis); + } + + if (value instanceof String) { + + String text = (String) value; + if (StringUtils.isEmpty(text)) { + return null; + } + + try { + return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(text); + } catch (ParseException e) { + LOG.error("parse filter error", e); + return null; + } + } + + return null; + } + + private List load(BeanInfo beanInfo, Map filters) { + List list = new ArrayList(); + + StringBuilder buf = new StringBuilder(); + + buf.append("SELECT "); + + List fields = beanInfo.getFields(); + for (int i = 0; i < fields.size(); ++i) { + FieldInfo field = fields.get(i); + if (i != 0) { + buf.append(", "); + } + buf.append(field.getColumnName()); + } + + buf.append("\nFROM "); + buf.append(getTableName(beanInfo)); + buf.append("\nWHERE collectTime >= ? AND collectTime <= ? AND domain = ? AND app = ? AND cluster = ?"); + + Date startTime = getDate(filters, "startTime"); + if (startTime == null) { + long now = System.currentTimeMillis(); + startTime = new Date(now - 1000 * 60 * 30); // 3 hours + } + + Date endTime = getDate(filters, "endTime"); + if (endTime == null) { + endTime = new Date(); // now + } + + String domain = (String) filters.get("domain"); + if (StringUtils.isEmpty(domain)) { + domain = "defaultDomain"; + } + String app = (String) filters.get("app"); + if (StringUtils.isEmpty(app)) { + app = "defaultApp"; + } + + String cluster = (String) filters.get("cluster"); + if (StringUtils.isEmpty(cluster)) { + cluster = "defaultCluster"; + } + + String host = (String) filters.get("host"); + if (!StringUtils.isEmpty(host)) { + buf.append("\nAND host = ?"); + } + + Integer pid = getInteger(filters, "pid"); + if (pid != null) { + buf.append("\nAND pid = ?"); + } + + { + Integer offset = (Integer) filters.get("offset"); + Integer limit = (Integer) filters.get("limit"); + + if (limit == null) { + limit = 1000; + } + + buf.append("\nLIMIT "); + if (offset != null) { + buf.append(offset); + buf.append(", "); + } + buf.append(limit); + } + + String sql = buf.toString(); + + Connection conn = null; + PreparedStatement stmt = null; + ResultSet rs = null; + try { + conn = dataSource.getConnection(); + stmt = conn.prepareStatement(sql); + + int paramIndex = 1; + + stmt.setTimestamp(paramIndex++, new Timestamp(startTime.getTime())); + stmt.setTimestamp(paramIndex++, new Timestamp(endTime.getTime())); + + stmt.setString(paramIndex++, domain); + stmt.setString(paramIndex++, app); + stmt.setString(paramIndex++, cluster); + + if (!StringUtils.isEmpty(host)) { + stmt.setString(paramIndex++, host); + } + + if (pid != null) { + stmt.setInt(paramIndex++, pid); + } + + rs = stmt.executeQuery(); + while (rs.next()) { + Object object = createInstance(beanInfo); + + for (int i = 0; i < fields.size(); ++i) { + FieldInfo field = fields.get(i); + readFieldValue(object, field, rs, i + 1); + } + + list.add(object); + } + + stmt.close(); + } catch (SQLException ex) { + LOG.error("save sql error", ex); + } finally { + JdbcUtils.close(rs); + JdbcUtils.close(stmt); + JdbcUtils.close(conn); + } + + return list; + } + + protected void readFieldValue(Object object, FieldInfo field, ResultSet rs, int paramIndex) throws SQLException { + Class fieldType = field.getFieldType(); + Object fieldValue = null; + if (fieldType.equals(int.class) || fieldType.equals(Integer.class)) { + fieldValue = rs.getInt(paramIndex); + } else if (fieldType.equals(long.class) || fieldType.equals(Long.class)) { + fieldValue = rs.getLong(paramIndex); + } else if (fieldType.equals(String.class)) { + fieldValue = rs.getString(paramIndex); + } else if (fieldType.equals(Date.class)) { + Timestamp timestamp = rs.getTimestamp(paramIndex); + if (timestamp != null) { + fieldValue = new Date(timestamp.getTime()); + } + } else { + throw new UnsupportedOperationException(); + } + try { + field.getField().set(object, fieldValue); + } catch (IllegalArgumentException e) { + throw new DruidRuntimeException("set field error" + field.getField(), e); + } catch (IllegalAccessException e) { + throw new DruidRuntimeException("set field error" + field.getField(), e); + } + } + private void save(BeanInfo beanInfo, MonitorContext ctx, List list) { String sql = buildInsertSql(beanInfo); Connection conn = null; @@ -151,6 +365,16 @@ public class MonitorDaoJdbcImpl implements MonitorDao { } } + public Object createInstance(BeanInfo beanInfo) { + try { + return beanInfo.getClazz().newInstance(); + } catch (InstantiationException ex) { + throw new DruidRuntimeException("create instance error", ex); + } catch (IllegalAccessException ex) { + throw new DruidRuntimeException("create instance error", ex); + } + } + public String buildInsertSql(BeanInfo beanInfo) { String sql = beanInfo.insertSql; diff --git a/src/test/java/com/alibaba/druid/bvt/support/monitor/MonitorDaoJdbcImplTest.java b/src/test/java/com/alibaba/druid/bvt/support/monitor/MonitorDaoJdbcImplTest.java index 0e7ea8416f..b54d321e5c 100644 --- a/src/test/java/com/alibaba/druid/bvt/support/monitor/MonitorDaoJdbcImplTest.java +++ b/src/test/java/com/alibaba/druid/bvt/support/monitor/MonitorDaoJdbcImplTest.java @@ -6,6 +6,8 @@ import java.util.List; import junit.framework.TestCase; +import org.junit.Assert; + import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.stat.JdbcSqlStatValue; @@ -41,7 +43,7 @@ public class MonitorDaoJdbcImplTest extends TestCase { MonitorClient client = new MonitorClient(); client.setDao(dao); - + { String sql = buildCreateSql(dao, new BeanInfo(JdbcSqlStatValue.class)); System.out.println(SQLUtils.format(sql, JdbcConstants.MYSQL)); @@ -50,6 +52,23 @@ public class MonitorDaoJdbcImplTest extends TestCase { client.collectSql(); + { + List sqlList = client.loadSqlList(Collections. emptyMap()); + for (JdbcSqlStatValue sqlStatValue : sqlList) { + System.out.println(sqlStatValue.getData()); + } + Assert.assertEquals(1, sqlList.size()); + } + + client.collectSql(); + + { + List sqlList = client.loadSqlList(Collections. emptyMap()); + for (JdbcSqlStatValue sqlStatValue : sqlList) { + System.out.println(sqlStatValue.getData()); + } + Assert.assertEquals(3, sqlList.size()); + } } public String buildCreateSql(MonitorDaoJdbcImpl dao, BeanInfo beanInfo) {