/* * 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.stat; import java.lang.management.ManagementFactory; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicLong; import javax.management.JMException; import javax.management.MBeanServer; import javax.management.ObjectName; import javax.management.openmbean.CompositeDataSupport; import javax.management.openmbean.CompositeType; import javax.management.openmbean.OpenType; import javax.management.openmbean.SimpleType; import javax.management.openmbean.TabularData; import javax.management.openmbean.TabularDataSupport; import javax.management.openmbean.TabularType; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.util.ConcurrentIdentityHashMap; import com.alibaba.druid.util.JMXUtils; public class DruidDataSourceStatManager implements DruidDataSourceStatManagerMBean { private final static Log LOG = LogFactory.getLog(DruidDataSourceStatManager.class); private final static DruidDataSourceStatManager instance = new DruidDataSourceStatManager(); private final AtomicLong resetCount = new AtomicLong(); // global instances private static final ConcurrentIdentityHashMap dataSources = new ConcurrentIdentityHashMap(); private final static String MBEAN_NAME = "com.alibaba.druid:type=DruidDataSourceStat"; public static DruidDataSourceStatManager getInstance() { return instance; } public synchronized static void add(DruidDataSource dataSource) { MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer(); if (dataSources.size() == 0) { try { ObjectName objectName = new ObjectName(MBEAN_NAME); if (!mbeanServer.isRegistered(objectName)) { mbeanServer.registerMBean(instance, objectName); } } catch (JMException ex) { LOG.error("register mbean error", ex); } } ObjectName objectName = null; if (dataSource.getNameInternal() != null) { try { objectName = new ObjectName("com.alibaba.druid:type=DruidDataSource,id=" + dataSource.getNameInternal()); mbeanServer.registerMBean(dataSource, objectName); } catch (JMException ex) { LOG.error("register mbean error", ex); objectName = null; } } if (objectName == null) { try { int id = System.identityHashCode(dataSource); objectName = new ObjectName("com.alibaba.druid:type=DruidDataSource,id=" + id); mbeanServer.registerMBean(dataSource, objectName); } catch (JMException ex) { LOG.error("register mbean error", ex); objectName = null; } } dataSources.put(dataSource, objectName); dataSource.setObjectName(objectName); } public synchronized static void remove(DruidDataSource dataSource) { ObjectName objectName = dataSources.remove(dataSource); if (objectName == null) { objectName = dataSource.getObjectName(); } if (objectName == null) { LOG.error("unregister mbean failed. url " + dataSource.getUrl()); return; } MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer(); if (objectName != null) { try { mbeanServer.unregisterMBean(objectName); } catch (JMException ex) { LOG.error("unregister mbean error", ex); } } if (dataSources.size() == 0) { try { mbeanServer.unregisterMBean(new ObjectName(MBEAN_NAME)); } catch (JMException ex) { LOG.error("unregister mbean error", ex); } } } public static Set getDruidDataSourceInstances() { return dataSources.keySet(); } public void reset() { final Set dataSources = getDruidDataSourceInstances(); for (DruidDataSource dataSource : dataSources) { dataSource.resetStat(); } resetCount.incrementAndGet(); } public long getResetCount() { return resetCount.get(); } public TabularData getDataSourceList() throws JMException { CompositeType rowType = getDruidDataSourceCompositeType(); String[] indexNames = rowType.keySet().toArray(new String[rowType.keySet().size()]); TabularType tabularType = new TabularType("DruidDataSourceStat", "DruidDataSourceStat", rowType, indexNames); TabularData data = new TabularDataSupport(tabularType); final Set dataSources = getDruidDataSourceInstances(); for (DruidDataSource dataSource : dataSources) { data.put(getCompositeData(dataSource)); } return data; } public CompositeDataSupport getCompositeData(DruidDataSource dataSource) throws JMException { CompositeType rowType = getDruidDataSourceCompositeType(); Map map = new HashMap(); // 0 - 4 map.put("Name", dataSource.getName()); map.put("URL", dataSource.getUrl()); map.put("CreateCount", dataSource.getCreateCount()); map.put("DestroyCount", dataSource.getDestroyCount()); map.put("ConnectCount", dataSource.getConnectCount()); // 5 - 9 map.put("CloseCount", dataSource.getCloseCount()); map.put("ActiveCount", dataSource.getActivePeak()); map.put("PoolingCount", dataSource.getPoolingCount()); map.put("LockQueueLength", dataSource.getLockQueueLength()); map.put("WaitThreadCount", dataSource.getNotEmptyWaitThreadPeak()); // 10 - 14 map.put("InitialSize", dataSource.getInitialSize()); map.put("MaxActive", dataSource.getMaxActive()); map.put("MinIdle", dataSource.getMinIdle()); map.put("PoolPreparedStatements", dataSource.isPoolPreparedStatements()); map.put("TestOnBorrow", dataSource.isTestOnBorrow()); // 15 - 19 map.put("TestOnReturn", dataSource.isTestOnReturn()); map.put("MinEvictableIdleTimeMillis", dataSource.getMinEvictableIdleTimeMillis()); map.put("ConnectErrorCount", dataSource.getConnectErrorCount()); map.put("CreateTimespanMillis", dataSource.getCreateTimespanMillis()); map.put("DbType", dataSource.getDbType()); // 20 - 24 map.put("ValidationQuery", dataSource.getValidationQuery()); map.put("ValidationQueryTimeout", dataSource.getValidationQueryTimeout()); map.put("DriverClassName", dataSource.getDriverClassName()); map.put("Username", dataSource.getUsername()); map.put("RemoveAbandonedCount", dataSource.getRemoveAbandonedCount()); // 25 - 29 map.put("NotEmptyWaitCount", dataSource.getNotEmptyWaitCount()); map.put("NotEmptyWaitNanos", dataSource.getNotEmptyWaitNanos()); map.put("ErrorCount", dataSource.getErrorCount()); map.put("ReusePreparedStatementCount", dataSource.getCachedPreparedStatementHitCount()); map.put("StartTransactionCount", dataSource.getStartTransactionCount()); // 30 - 34 map.put("CommitCount", dataSource.getCommitCount()); map.put("RollbackCount", dataSource.getRollbackCount()); map.put("LastError", JMXUtils.getErrorCompositeData(dataSource.getLastError())); map.put("LastCreateError", JMXUtils.getErrorCompositeData(dataSource.getLastCreateError())); map.put("PreparedStatementCacheDeleteCount", dataSource.getCachedPreparedStatementDeleteCount()); // 35 - 39 map.put("PreparedStatementCacheAccessCount", dataSource.getCachedPreparedStatementAccessCount()); map.put("PreparedStatementCacheMissCount", dataSource.getCachedPreparedStatementMissCount()); map.put("PreparedStatementCacheHitCount", dataSource.getCachedPreparedStatementHitCount()); map.put("PreparedStatementCacheCurrentCount", dataSource.getCachedPreparedStatementCount()); map.put("Version", dataSource.getVersion()); // 40 - map.put("LastErrorTime", dataSource.getLastErrorTime()); map.put("LastCreateErrorTime", dataSource.getLastCreateErrorTime()); map.put("CreateErrorCount", dataSource.getCreateErrorCount()); return new CompositeDataSupport(rowType, map); } private static CompositeType COMPOSITE_TYPE = null; public static CompositeType getDruidDataSourceCompositeType() throws JMException { if (COMPOSITE_TYPE != null) { return COMPOSITE_TYPE; } OpenType[] indexTypes = new OpenType[] { // 0 - 4 SimpleType.STRING, // SimpleType.STRING, // SimpleType.LONG, // SimpleType.LONG, // SimpleType.LONG, // // 5 - 9 SimpleType.LONG, // SimpleType.INTEGER, // SimpleType.INTEGER, // SimpleType.INTEGER, // SimpleType.INTEGER, // // 10 - 14 SimpleType.INTEGER, // SimpleType.INTEGER, // SimpleType.INTEGER, // SimpleType.BOOLEAN, // SimpleType.BOOLEAN, // // 15 - 19 SimpleType.BOOLEAN, // SimpleType.LONG, // SimpleType.LONG, // SimpleType.LONG, // SimpleType.STRING, // // 20 - 24 SimpleType.STRING, // SimpleType.INTEGER, // SimpleType.STRING, // SimpleType.STRING, // SimpleType.LONG, // // 25 - 29 SimpleType.LONG, // SimpleType.LONG, // SimpleType.LONG, // SimpleType.LONG, // SimpleType.LONG, // // 30 - 34 SimpleType.LONG, // SimpleType.LONG, // JMXUtils.getThrowableCompositeType(), // JMXUtils.getThrowableCompositeType(), // SimpleType.LONG, // // 35 - 39 SimpleType.LONG, // SimpleType.LONG, // SimpleType.LONG, // SimpleType.LONG, // SimpleType.STRING, // // 40 - SimpleType.DATE, // SimpleType.DATE, // SimpleType.LONG // // }; String[] indexNames = { // 0 - 4 "Name", // "URL", // "CreateCount", // "DestroyCount", // "ConnectCount", // // 5 - 9 "CloseCount", // "ActiveCount", // "PoolingCount", // "LockQueueLength", // "WaitThreadCount", // // 10 - 14 "InitialSize", // "MaxActive", // "MinIdle", // "PoolPreparedStatements", // "TestOnBorrow", // // 15 - 19 "TestOnReturn", // "MinEvictableIdleTimeMillis", // "ConnectErrorCount", // "CreateTimespanMillis", // "DbType", // // 20 - 24 "ValidationQuery", // "ValidationQueryTimeout", // "DriverClassName", // "Username", // "RemoveAbandonedCount", // // 25 - 29 "NotEmptyWaitCount", // "NotEmptyWaitNanos", // "ErrorCount", // "ReusePreparedStatementCount", // "StartTransactionCount", // // 30 - 34 "CommitCount", // "RollbackCount", // "LastError", // "LastCreateError", // "PreparedStatementCacheDeleteCount", // // 35 - 39 "PreparedStatementCacheAccessCount", // "PreparedStatementCacheMissCount", // "PreparedStatementCacheHitCount", // "PreparedStatementCacheCurrentCount", // "Version" // // 40 - , "LastErrorTime", // "LastCreateErrorTime", // "CreateErrorCount" // // }; String[] indexDescriptions = indexNames; COMPOSITE_TYPE = new CompositeType("DataSourceStatistic", "DataSource Statistic", indexNames, indexDescriptions, indexTypes); return COMPOSITE_TYPE; } }