package com.sohu.cache.stats.instance.impl; import com.sohu.cache.constant.RedisConstant; import com.sohu.cache.dao.InstanceDao; import com.sohu.cache.dao.InstanceStatsDao; import com.sohu.cache.entity.InstanceCommandStats; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.entity.InstanceStats; import com.sohu.cache.entity.StandardStats; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.stats.instance.InstanceStatsCenter; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.util.DateUtil; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.Assert; import java.util.*; /** * Created by yijunzhang on 14-9-17. */ public class InstanceStatsCenterImpl implements InstanceStatsCenter { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private InstanceDao instanceDao; private InstanceStatsDao instanceStatsDao; private RedisCenter redisCenter; @Override public InstanceInfo getInstanceInfo(long instanceId) { return instanceDao.getInstanceInfoById(instanceId); } @Override public InstanceStats getInstanceStats(long instanceId) { InstanceStats instanceStats = instanceStatsDao.getInstanceStatsByInsId(instanceId); if (instanceStats == null) { logger.error("instanceStats id={} is null", instanceId); return null; } InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId); int type = instanceInfo.getType(); boolean isRun = redisCenter.isRun(instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort()); instanceStats.setRun(isRun); if (isRun) { Map<String, Object> infoMap = getInfoMap(instanceInfo.getAppId(), type, instanceInfo.getIp(), instanceInfo.getPort()); instanceStats.setInfoMap(infoMap); if (infoMap == null || infoMap.isEmpty()) { instanceStats.setRun(false); } } return instanceStats; } private Map<String, Object> getInfoMap(long appId, int type, String ip, int port) { Map<RedisConstant, Map<String, Object>> infoMap = redisCenter.getInfoStats(appId, ip, port); Map<String, Object> resultMap = new LinkedHashMap<String, Object>(); if (infoMap != null) { for (RedisConstant redisConstant : infoMap.keySet()) { resultMap.put(redisConstant.getValue(), infoMap.get(redisConstant)); } } return resultMap; } @Override public List<InstanceCommandStats> getCommandStatsList(Long instanceId, long beginTime, long endTime, String commandName) { if (instanceId == null) { return Collections.emptyList(); } InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId); List<InstanceCommandStats> resultList = new ArrayList<InstanceCommandStats>(); String ip = instanceInfo.getIp(); int port = instanceInfo.getPort(); int type = instanceInfo.getType(); List<Map<String, Object>> objectList = this.queryDiffMapList(beginTime, endTime, ip, port, ConstUtils.REDIS);; if (objectList != null) { for (Map<String, Object> map : objectList) { InstanceCommandStats stats = parseCommand(instanceId, commandName, map, true, type); if (stats != null) { resultList.add(stats); } } } return resultList; } @Override public Map<Integer, Map<String, List<InstanceCommandStats>>> getStandardStatsList(Long appId, long beginTime, long endTime, List<String> commands) { if (appId == null) { return Collections.emptyMap(); } List<InstanceInfo> list = instanceDao.getInstListByAppId(appId); if (list == null || list.isEmpty()) { return Collections.emptyMap(); } Map<Integer, Map<String, List<InstanceCommandStats>>> resultMap = new LinkedHashMap<Integer, Map<String, List<InstanceCommandStats>>>(); for (InstanceInfo instance : list) { if (instance.isOffline()) { continue; } int instanceId = instance.getId(); String ip = instance.getIp(); int port = instance.getPort(); int type = instance.getType(); Boolean isMaster = redisCenter.isMaster(appId, ip, port); if (BooleanUtils.isNotTrue(isMaster)){ continue; } List<Map<String, Object>> objectList = this.queryDiffMapList(beginTime, endTime, ip, port, ConstUtils.REDIS);; if (objectList != null) { Map<String, List<InstanceCommandStats>> commandMap = new LinkedHashMap<String, List<InstanceCommandStats>>(); for (String commandName : commands) { List<InstanceCommandStats> resultList = new ArrayList<InstanceCommandStats>(objectList.size()); for (Map<String, Object> map : objectList) { InstanceCommandStats stats = parseCommand(instanceId, commandName, map, false, type); if (stats != null) { resultList.add(stats); } } commandMap.put(commandName, resultList); } resultMap.put(instanceId, commandMap); } } return resultMap; } private InstanceCommandStats parseCommand(long instanceId, String command, Map<String, Object> commandMap, boolean isCommand, int type) { Long collectTime = MapUtils.getLong(commandMap, ConstUtils.COLLECT_TIME, null); if (collectTime == null) { return null; } Long count; if (isCommand) { count = MapUtils.getLong(commandMap, "cmdstat_" + command.toLowerCase(), null); } else { count = MapUtils.getLong(commandMap, command.toLowerCase(), null); } if (count == null) { return null; } InstanceCommandStats stats = new InstanceCommandStats(); stats.setCommandCount(count); stats.setCommandName(command); stats.setCollectTime(collectTime); stats.setCreateTime(DateUtil.getDateByFormat(String.valueOf(collectTime), "yyyyMMddHHmm")); stats.setModifyTime(DateUtil.getDateByFormat(String.valueOf(collectTime), "yyyyMMddHHmm")); stats.setInstanceId(instanceId); return stats; } @Override public String executeCommand(String host, int port, String command) { if (StringUtils.isBlank(host) || port == 0) { return "host or port is null"; } InstanceInfo instanceInfo = instanceDao.getAllInstByIpAndPort(host, port); if (instanceInfo == null) { return "instance not exist"; } if (TypeUtil.isRedisType(instanceInfo.getType())) { return redisCenter.executeCommand(instanceInfo.getAppId(), host, port, command); } return "not support type"; } @Override public String executeCommand(Long instanceId, String command) { InstanceInfo instanceInfo = getInstanceInfo(instanceId); return executeCommand(instanceInfo.getIp(), instanceInfo.getPort(), command); } @Override public List<InstanceStats> getInstanceStats() { return instanceStatsDao.getInstanceStats(); } @Override public List<InstanceStats> getInstanceStats(String ip) { List<InstanceStats> instanceStatsList = instanceStatsDao.getInstanceStatsByIp(ip); return instanceStatsList; } @Override public boolean saveStandardStats(Map<String, Object> infoMap, String ip, int port, String dbType) { Assert.isTrue(infoMap != null && infoMap.size() > 0); Assert.isTrue(StringUtils.isNotBlank(ip)); Assert.isTrue(port > 0); Assert.isTrue(infoMap.containsKey(ConstUtils.COLLECT_TIME), ConstUtils.COLLECT_TIME + " not in infoMap"); long collectTime = MapUtils.getLong(infoMap, ConstUtils.COLLECT_TIME); StandardStats ss = new StandardStats(); ss.setCollectTime(collectTime); ss.setIp(ip); ss.setPort(port); ss.setDbType(dbType); if (infoMap.containsKey(RedisConstant.DIFF.getValue())) { Map<String, Object> diffMap = (Map<String, Object>) infoMap.get(RedisConstant.DIFF.getValue()); ss.setDiffMap(diffMap); infoMap.remove(RedisConstant.DIFF.getValue()); } else { ss.setDiffMap(new HashMap<String, Object>(0)); } ss.setInfoMap(infoMap); int mergeCount = instanceStatsDao.mergeStandardStats(ss); return mergeCount > 0; } @Override public Map<String, Object> queryStandardInfoMap(long collectTime, String ip, int port, String dbType) { Assert.isTrue(StringUtils.isNotBlank(ip)); Assert.isTrue(port > 0); Assert.isTrue(collectTime > 0); StandardStats ss = instanceStatsDao.getStandardStats(collectTime, ip, port, dbType); if (ss != null) { Map<String, Object> infoMap = ss.getInfoMap(); Map<String, Object> diffMap = ss.getDiffMap(); infoMap.put(RedisConstant.DIFF.getValue(), diffMap); return infoMap; } else { return Collections.emptyMap(); } } @Override public List<Map<String, Object>> queryDiffMapList(long beginTime, long endTime, String ip, int port, String dbType) { Assert.isTrue(StringUtils.isNotBlank(ip)); Assert.isTrue(port > 0); Assert.isTrue(beginTime > 0); Assert.isTrue(endTime > 0); List<StandardStats> list = instanceStatsDao.getDiffJsonList(beginTime, endTime, ip, port, dbType); if (list == null || list.isEmpty()) { return new ArrayList<Map<String, Object>>(0); } List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>(list.size()); for (StandardStats ss : list) { Map<String, Object> diffMap = ss.getDiffMap(); diffMap.put(ConstUtils.COLLECT_TIME, ss.getCollectTime()); resultList.add(diffMap); } return resultList; } @Override public void cleanUpStandardStats(int day) { Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); calendar.add(Calendar.DAY_OF_MONTH, -Math.abs(day)); Date deleteTime = calendar.getTime(); int deleteCount = instanceStatsDao.deleteStandardStatsByCreatedTime(deleteTime); logger.warn("cleanUpStandardStats: {} day deleteCount={}", day, deleteCount); } public void setInstanceDao(InstanceDao instanceDao) { this.instanceDao = instanceDao; } public void setInstanceStatsDao(InstanceStatsDao instanceStatsDao) { this.instanceStatsDao = instanceStatsDao; } public void setRedisCenter(RedisCenter redisCenter) { this.redisCenter = redisCenter; } }