All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alibaba.druid.stat.DruidStatManagerFacade Maven / Gradle / Ivy

There is a newer version: 1.2.23
Show newest version
/*
 * Copyright 1999-2018 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 com.alibaba.druid.VERSION;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;
import com.alibaba.druid.support.http.stat.WebAppStatManager;
import com.alibaba.druid.support.spring.stat.SpringStatManager;
import com.alibaba.druid.util.DruidDataSourceUtils;
import com.alibaba.druid.util.JdbcSqlStatUtils;
import com.alibaba.druid.util.StringUtils;
import com.alibaba.druid.util.Utils;

import java.sql.Driver;
import java.sql.DriverManager;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 监控相关的对外数据暴露
 * 

* 1. 为了支持jndi数据源本类内部调用druid相关对象均需要反射调用,返回值也应该是Object,List<Object>,Map<String,Object>等无关于druid的类型 * 2. 对外暴露的public方法都应该先调用init(),应该有更好的方式,暂时没想到 * * @author sandzhang[[email protected]] */ public final class DruidStatManagerFacade { private static final DruidStatManagerFacade instance = new DruidStatManagerFacade(); private boolean resetEnable = true; private final AtomicLong resetCount = new AtomicLong(); private DruidStatManagerFacade() { } public static DruidStatManagerFacade getInstance() { return instance; } private Set getDruidDataSourceInstances() { return DruidDataSourceStatManager.getInstances().keySet(); } public Object getDruidDataSourceByName(String name) { for (Object o : this.getDruidDataSourceInstances()) { String itemName = DruidDataSourceUtils.getName(o); if (StringUtils.equals(name, itemName)) { return o; } } return null; } public void resetDataSourceStat() { DruidDataSourceStatManager.getInstance().reset(); } public void resetSqlStat() { JdbcStatManager.getInstance().reset(); } public void resetAll() { if (!isResetEnable()) { return; } SpringStatManager.getInstance().resetStat(); WebAppStatManager.getInstance().resetStat(); resetSqlStat(); resetDataSourceStat(); resetCount.incrementAndGet(); } public void logAndResetDataSource() { if (!isResetEnable()) { return; } DruidDataSourceStatManager.getInstance().logAndResetDataSource(); } public boolean isResetEnable() { return resetEnable; } public void setResetEnable(boolean resetEnable) { this.resetEnable = resetEnable; } public Object getSqlStatById(Integer id) { for (Object ds : getDruidDataSourceInstances()) { Object sqlStat = DruidDataSourceUtils.getSqlStat(ds, id); if (sqlStat != null) { return sqlStat; } } return null; } public Map getDataSourceStatData(Integer id) { if (id == null) { return null; } Object datasource = getDruidDataSourceById(id); return datasource == null ? null : dataSourceToMapData(datasource, false); } public Object getDruidDataSourceById(Integer identity) { if (identity == null) { return null; } for (Object datasource : getDruidDataSourceInstances()) { if (System.identityHashCode(datasource) == identity) { return datasource; } } return null; } public List> getSqlStatDataList(Integer dataSourceId) { Set dataSources = getDruidDataSourceInstances(); if (dataSourceId == null) { JdbcDataSourceStat globalStat = JdbcDataSourceStat.getGlobal(); List> sqlList = new ArrayList>(); DruidDataSource globalStatDataSource = null; for (Object datasource : dataSources) { if (datasource instanceof DruidDataSource) { if (((DruidDataSource) datasource).getDataSourceStat() == globalStat) { if (globalStatDataSource == null) { globalStatDataSource = (DruidDataSource) datasource; } else { continue; } } } sqlList.addAll(getSqlStatDataList(datasource)); } return sqlList; } for (Object datasource : dataSources) { if (dataSourceId != null && dataSourceId.intValue() != System.identityHashCode(datasource)) { continue; } return getSqlStatDataList(datasource); } return new ArrayList>(); } @SuppressWarnings("unchecked") public Map getWallStatMap(Integer dataSourceId) { Set dataSources = getDruidDataSourceInstances(); if (dataSourceId == null) { Map map = new HashMap(); for (Object datasource : dataSources) { Map wallStat = DruidDataSourceUtils.getWallStatMap(datasource); map = mergeWallStat(map, wallStat); } return map; } for (Object datasource : dataSources) { if (dataSourceId != null && dataSourceId.intValue() != System.identityHashCode(datasource)) { continue; } return DruidDataSourceUtils.getWallStatMap(datasource); } return new HashMap(); // } /** * Merges two wall stat maps into a single map. * * @param mapA the first wall stat map to be merged * @param mapB the second wall stat map to be merged * @return a new map that contains the merged wall stats from mapA and mapB * @deprecated */ public static Map mergWallStat(Map mapA, Map mapB) { return mergeWallStat(mapA, mapB); } @SuppressWarnings({"rawtypes", "unchecked"}) public static Map mergeWallStat(Map mapA, Map mapB) { if (mapA == null || mapA.size() == 0) { return mapB; } if (mapB == null || mapB.size() == 0) { return mapA; } Map newMap = new LinkedHashMap(); for (Object item : mapB.entrySet()) { Map.Entry entry = (Map.Entry) item; String key = (String) entry.getKey(); Object valueB = entry.getValue(); Object valueA = mapA.get(key); if (valueA == null) { newMap.put(key, valueB); } else if (valueB == null) { newMap.put(key, valueA); } else if ("blackList".equals(key)) { Map> newSet = new HashMap>(); Collection> collectionA = (Collection>) valueA; for (Map blackItem : collectionA) { if (newSet.size() >= 1000) { break; } String sql = (String) blackItem.get("sql"); Map oldItem = newSet.get(sql); newSet.put(sql, mergeWallStat(oldItem, blackItem)); } Collection> collectionB = (Collection>) valueB; for (Map blackItem : collectionB) { if (newSet.size() >= 1000) { break; } String sql = (String) blackItem.get("sql"); Map oldItem = newSet.get(sql); newSet.put(sql, mergeWallStat(oldItem, blackItem)); } newMap.put(key, newSet.values()); } else { if (valueA instanceof Map && valueB instanceof Map) { Object newValue = mergeWallStat((Map) valueA, (Map) valueB); newMap.put(key, newValue); } else if (valueA instanceof Set && valueB instanceof Set) { Set set = new HashSet(); set.addAll((Set) valueA); set.addAll((Set) valueB); newMap.put(key, set); } else if (valueA instanceof List && valueB instanceof List) { List> mergedList = mergeNamedList((List) valueA, (List) valueB); newMap.put(key, mergedList); } else if (valueA instanceof long[] && valueB instanceof long[]) { long[] arrayA = (long[]) valueA; long[] arrayB = (long[]) valueB; int len = arrayA.length >= arrayB.length ? arrayA.length : arrayB.length; long[] sum = new long[len]; for (int i = 0; i < sum.length; ++i) { if (i < arrayA.length) { sum[i] += arrayA.length; } if (i < arrayB.length) { sum[i] += arrayB.length; } } newMap.put(key, sum); } else if (valueA instanceof String && valueB instanceof String) { newMap.put(key, valueA); } else { Object sum = SQLEvalVisitorUtils.add(valueA, valueB); newMap.put(key, sum); } } } return newMap; } @SuppressWarnings({"rawtypes", "unchecked"}) private static List> mergeNamedList(List listA, List listB) { Map> mapped = new HashMap>(); for (Object item : (List) listA) { Map map = (Map) item; String name = (String) map.get("name"); mapped.put(name, map); } List> mergedList = new ArrayList>(); for (Object item : (List) listB) { Map mapB = (Map) item; String name = (String) mapB.get("name"); Map mapA = mapped.get(name); Map mergedMap = mergeWallStat(mapA, mapB); mergedList.add(mergedMap); } return mergedList; } public List> getSqlStatDataList(Object datasource) { List> result = new ArrayList>(); Map sqlStatMap = DruidDataSourceUtils.getSqlStatMap(datasource); for (Object sqlStat : sqlStatMap.values()) { Map data = JdbcSqlStatUtils.getData(sqlStat); long executeCount = (Long) data.get("ExecuteCount"); long runningCount = (Long) data.get("RunningCount"); if (executeCount == 0 && runningCount == 0) { continue; } result.add(data); } return result; } public Map getSqlStatData(Integer id) { if (id == null) { return null; } Object sqlStat = getSqlStatById(id); if (sqlStat == null) { return null; } return JdbcSqlStatUtils.getData(sqlStat); } public List> getDataSourceStatDataList() { return getDataSourceStatDataList(false); } public List> getDataSourceStatDataList(boolean includeSqlList) { List> datasourceList = new ArrayList>(); for (Object dataSource : getDruidDataSourceInstances()) { datasourceList.add(dataSourceToMapData(dataSource, includeSqlList)); } return datasourceList; } public List> getActiveConnStackTraceList() { List> traceList = new ArrayList>(); for (Object dataSource : getDruidDataSourceInstances()) { List stacks = ((DruidDataSource) dataSource).getActiveConnectionStackTrace(); if (stacks.size() > 0) { traceList.add(stacks); } } return traceList; } public Map returnJSONBasicStat() { Map dataMap = new LinkedHashMap(); dataMap.put("Version", VERSION.getVersionNumber()); dataMap.put("Drivers", getDriversData()); dataMap.put("ResetEnable", isResetEnable()); dataMap.put("ResetCount", getResetCount()); dataMap.put("JavaVMName", System.getProperty("java.vm.name")); dataMap.put("JavaVersion", System.getProperty("java.version")); dataMap.put("JavaClassPath", System.getProperty("java.class.path")); dataMap.put("StartTime", Utils.getStartTime()); return dataMap; } public long getResetCount() { return resetCount.get(); } private List getDriversData() { List drivers = new ArrayList(); for (Enumeration e = DriverManager.getDrivers(); e.hasMoreElements(); ) { Driver driver = e.nextElement(); drivers.add(driver.getClass().getName()); } return drivers; } public List> getPoolingConnectionInfoByDataSourceId(Integer id) { Object datasource = getDruidDataSourceById(id); if (datasource == null) { return null; } return DruidDataSourceUtils.getPoolingConnectionInfo(datasource); } public List getActiveConnectionStackTraceByDataSourceId(Integer id) { Object datasource = getDruidDataSourceById(id); if (datasource == null || !DruidDataSourceUtils.isRemoveAbandoned(datasource)) { return null; } return DruidDataSourceUtils.getActiveConnectionStackTrace(datasource); } private Map dataSourceToMapData(Object dataSource, boolean includeSql) { Map map = DruidDataSourceUtils.getStatData(dataSource); if (includeSql) { List> sqlList = getSqlStatDataList(dataSource); map.put("SQL", sqlList); } return map; } }