package com.sohu.cache.web.controller; import com.alibaba.fastjson.JSONObject; import com.sohu.cache.constant.AppAuditType; import com.sohu.cache.constant.AppStatusEnum; import com.sohu.cache.constant.AppUserTypeEnum; import com.sohu.cache.constant.TimeDimensionalityEnum; import com.sohu.cache.entity.*; import com.sohu.cache.stats.app.AppDailyDataCenter; import com.sohu.cache.stats.app.AppDeployCenter; import com.sohu.cache.stats.app.AppStatsCenter; import com.sohu.cache.stats.instance.InstanceStatsCenter; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.DemoCodeUtil; import com.sohu.cache.web.vo.AppDetailVO; import com.sohu.cache.web.chart.model.HighchartPoint; import com.sohu.cache.web.chart.model.SimpleChartData; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.util.AppEmailUtil; import com.sohu.cache.web.util.DateUtil; import com.sohu.cache.web.util.Page; import net.sf.json.JSONArray; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.time.DateUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.sql.Timestamp; import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.TimeUnit; /** * 应用统计相关 * * @author leifu * @Time 2014年8月31日 */ @Controller @RequestMapping("/admin/app") public class AppController extends BaseController { private Logger logger = LoggerFactory.getLogger(AppController.class); @Resource(name = "appStatsCenter") private AppStatsCenter appStatsCenter; @Resource(name = "appEmailUtil") private AppEmailUtil appEmailUtil; @Resource(name = "appDeployCenter") private AppDeployCenter appDeployCenter; @Resource(name = "instanceStatsCenter") private InstanceStatsCenter instanceStatsCenter; @Resource(name = "appDailyDataCenter") private AppDailyDataCenter appDailyDataCenter; /** * 初始化贡献者页面 * @return */ @RequestMapping("/initBecomeContributor") public ModelAndView doInitBecomeContributor(HttpServletRequest request, HttpServletResponse response, Model model){ model.addAttribute("currentUser", getUserInfo(request)); return new ModelAndView("app/initBecomeContributor"); } /** * 成为cachecloud贡献者 * @param groupName 项目组 * @param applyReason 申请理由 * @return */ @RequestMapping("/addBecomeContributor") public ModelAndView doAddBecomeContributor(HttpServletRequest request, HttpServletResponse response, Model model, String groupName, String applyReason){ appEmailUtil.noticeBecomeContributor(groupName, applyReason, getUserInfo(request)); model.addAttribute("success", SuccessEnum.SUCCESS.value()); return new ModelAndView(""); } /** * 单个应用首页 * * @param appId * @param tabTag 标签名 * @param firstCommand 第一条命令 * @return * @throws ParseException */ @RequestMapping("/index") public ModelAndView index(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, String tabTag, String firstCommand) throws ParseException { // 如果应用id为空,取第一个应用id if (appId == null) { return new ModelAndView("redirect:/admin/app/list"); } // 日期转换 String startDateParam = request.getParameter("startDate"); String endDateParam = request.getParameter("endDate"); if (StringUtils.isBlank(startDateParam) || StringUtils.isBlank(endDateParam)) { Date startDate = new Date(); startDateParam = DateUtil.formatDate(startDate, "yyyy-MM-dd"); endDateParam = DateUtil.formatDate(DateUtils.addDays(startDate, 1), "yyyy-MM-dd"); } //慢查询 String slowLogStartDateParam = request.getParameter("slowLogStartDate"); String slowLogEndDateParam = request.getParameter("slowLogEndDate"); if (StringUtils.isBlank(slowLogStartDateParam) || StringUtils.isBlank(slowLogEndDateParam)) { Date startDate = new Date(); slowLogStartDateParam = DateUtil.formatDate(startDate, "yyyy-MM-dd"); slowLogEndDateParam = DateUtil.formatDate(DateUtils.addDays(startDate, 1), "yyyy-MM-dd"); } //日报 String dailyDateParam = request.getParameter("dailyDate"); if (StringUtils.isBlank(dailyDateParam)) { dailyDateParam = DateUtil.formatDate(DateUtils.addDays(new Date(), -1), "yyyy-MM-dd"); } model.addAttribute("startDate", startDateParam); model.addAttribute("endDate", endDateParam); model.addAttribute("slowLogStartDate", slowLogStartDateParam); model.addAttribute("slowLogEndDate", slowLogEndDateParam); model.addAttribute("dailyDate", dailyDateParam); model.addAttribute("appId", appId); model.addAttribute("tabTag", tabTag); model.addAttribute("firstCommand", firstCommand); return new ModelAndView("app/userAppsIndex"); } /** * 应用统计相关 * * @param appId 应用id * @return * @throws ParseException */ @RequestMapping("/stat") public ModelAndView appStat(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { String startDateParam = request.getParameter("startDate"); String endDateParam = request.getParameter("endDate"); /** 1.获取app的VO */ AppDetailVO appDetail = appStatsCenter.getAppDetail(appId); model.addAttribute("appDetail", appDetail); /** 2. 时间. */ Date startDate; Date endDate; if (StringUtils.isBlank(startDateParam) || StringUtils.isBlank(endDateParam)) { startDate = new Date(); endDate = DateUtils.addDays(startDate, 1); } else { endDate = DateUtil.parseYYYY_MM_dd(endDateParam); startDate = DateUtil.parseYYYY_MM_dd(startDateParam); } Date yesterDay = DateUtils.addDays(startDate, -1); long beginTime = NumberUtils.toLong(DateUtil.formatYYYYMMddHHMM(startDate)); long endTime = NumberUtils.toLong(DateUtil.formatYYYYMMddHHMM(endDate)); model.addAttribute("startDate", startDateParam); model.addAttribute("endDate", endDateParam); model.addAttribute("yesterDay", DateUtil.formatDate(yesterDay, "yyyy-MM-dd")); // 3.是否超过1天 if (endDate.getTime() - startDate.getTime() > TimeUnit.DAYS.toMillis(1)) { model.addAttribute("betweenOneDay", 0); } else { model.addAttribute("betweenOneDay", 1); } // 4. top5命令 List<AppCommandStats> top5Commands = appStatsCenter.getTopLimitAppCommandStatsList(appId, beginTime, endTime, 5); model.addAttribute("top5Commands", top5Commands); // 5.峰值 List<AppCommandStats> top5ClimaxList = new ArrayList<AppCommandStats>(); if (CollectionUtils.isNotEmpty(top5Commands)) { for (AppCommandStats appCommandStats : top5Commands) { AppCommandStats temp = appStatsCenter.getCommandClimax(appId, beginTime, endTime, appCommandStats.getCommandName()); if (temp != null) { top5ClimaxList.add(temp); } } } model.addAttribute("top5ClimaxList", top5ClimaxList); model.addAttribute("appId", appId); return new ModelAndView("app/appStat"); } /** * 命令曲线 * * @param appId * @param firstCommand 第一条命令 * @throws ParseException */ @RequestMapping("/commandAnalysis") public ModelAndView appCommandAnalysis(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, String firstCommand) throws ParseException { String startDateParam = request.getParameter("startDate"); String endDateParam = request.getParameter("endDate"); /** 1.获取app的VO */ AppDetailVO appDetail = appStatsCenter.getAppDetail(appId); model.addAttribute("appDetail", appDetail); /** 2.返回日期 */ Date endDate; Date startDate; if (StringUtils.isBlank(startDateParam) || StringUtils.isBlank(endDateParam)) { startDate = new Date(); endDate = DateUtils.addDays(startDate, 1); startDateParam = DateUtil.formatDate(startDate, "yyyy-MM-dd"); endDateParam = DateUtil.formatDate(endDate, "yyyy-MM-dd"); } else { endDate = DateUtil.parseYYYY_MM_dd(endDateParam); startDate = DateUtil.parseYYYY_MM_dd(startDateParam); } Date yesterDay = DateUtils.addDays(startDate, -1); model.addAttribute("yesterDay", DateUtil.formatDate(yesterDay, "yyyy-MM-dd")); model.addAttribute("startDate", startDateParam); model.addAttribute("endDate", endDateParam); long beginTime = NumberUtils.toLong(DateUtil.formatYYYYMMddHHMM(startDate)); long endTime = NumberUtils.toLong(DateUtil.formatYYYYMMddHHMM(endDate)); // 3.是否超过1天 if (endDate.getTime() - startDate.getTime() > TimeUnit.DAYS.toMillis(1)) { model.addAttribute("betweenOneDay", 0); } else { model.addAttribute("betweenOneDay", 1); } /** 3.获取top5命令 */ List<AppCommandStats> allCommands = appStatsCenter.getTopLimitAppCommandStatsList(appId, beginTime, endTime, 20); model.addAttribute("allCommands", allCommands); if (StringUtils.isBlank(firstCommand) && CollectionUtils.isNotEmpty(allCommands)) { model.addAttribute("firstCommand", allCommands.get(0).getCommandName()); } else { model.addAttribute("firstCommand", firstCommand); } model.addAttribute("appId", appId); // 返回标签名 return new ModelAndView("app/appCommandAnalysis"); } /** * 应用故障 */ @RequestMapping("/fault") public ModelAndView appFault(HttpServletRequest request, HttpServletResponse response, Model model) { return new ModelAndView("app/appFault"); } /** * 应用拓扑图 * * @param appId * @return */ @RequestMapping("/topology") public ModelAndView statTopology(HttpServletRequest request, HttpServletResponse response, Long appId, Model model) { //应用信息 AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); //实例相关信息(包含统计) fillAppInstanceStats(appId, model); return new ModelAndView("app/appTopology"); } /** * 应用机器拓扑图 * * @param appId * @return */ @RequestMapping("/machineInstancesTopology") public ModelAndView machineInstancesTopology(HttpServletRequest request, HttpServletResponse response, Long appId, Model model) { //应用信息 AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); //拓扑 fillAppMachineInstanceTopology(appId, model); return new ModelAndView("app/appMachineInstancesTopology"); } /** * 应用基本信息 * * @param appId 应用id */ @RequestMapping("/detail") public ModelAndView appDetail(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) { // 获取应用vo AppDetailVO appDetail = appStatsCenter.getAppDetail(appId); model.addAttribute("appDetail", appDetail); return new ModelAndView("app/appDetail"); } /** * 获取某个命令时间分布图 * * @param appId 应用id * @throws ParseException */ @RequestMapping("/getCommandStats") public ModelAndView getCommandStats(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { TimeBetween timeBetween = getJsonTimeBetween(request); long beginTime = timeBetween.getStartTime(); long endTime = timeBetween.getEndTime(); // 命令参数 String commandName = request.getParameter("commandName"); List<AppCommandStats> appCommandStatsList; if (StringUtils.isNotBlank(commandName)) { appCommandStatsList = appStatsCenter.getCommandStatsList(appId, beginTime, endTime, commandName); } else { appCommandStatsList = appStatsCenter.getCommandStatsList(appId, beginTime, endTime); } String result = assembleJson(appCommandStatsList); write(response, result); return null; } /** * 获取某个命令时间分布图 * * @param appId 应用id * @throws ParseException */ @RequestMapping("/getMutiDatesCommandStats") public ModelAndView getMutiDatesCommandStats(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { TimeBetween timeBetween = getJsonTimeBetween(request); // 命令参数 String commandName = request.getParameter("commandName"); List<AppCommandStats> appCommandStatsList; if (StringUtils.isNotBlank(commandName)) { appCommandStatsList = appStatsCenter.getCommandStatsListV2(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), TimeDimensionalityEnum.MINUTE, commandName); } else { appCommandStatsList = appStatsCenter.getCommandStatsListV2(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), TimeDimensionalityEnum.MINUTE); } String result = assembleMutilDateAppCommandJsonMinute(appCommandStatsList, timeBetween.getStartDate(), timeBetween.getEndDate()); model.addAttribute("data", result); return new ModelAndView(""); } /** * 获取命中率、丢失率等分布 * * @param appId 应用id * @param statName 统计项(hit,miss等) * @throws ParseException */ @RequestMapping("/getAppStats") public ModelAndView getAppStats(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, String statName) throws ParseException { TimeBetween timeBetween = getJsonTimeBetween(request); List<AppStats> appStats = appStatsCenter.getAppStatsListByMinuteTime(appId, timeBetween.getStartTime(), timeBetween.getEndTime()); String result = assembleAppStatsJson(appStats, statName); write(response, result); return null; } /** * 多命令 * @param appId * @param statName * @return * @throws ParseException */ @RequestMapping("/getMutiStatAppStats") public ModelAndView getMutiStatAppStats(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { String statNames = request.getParameter("statName"); List<String> statNameList = Arrays.asList(statNames.split(ConstUtils.COMMA)); TimeBetween timeBetween = getJsonTimeBetween(request); List<AppStats> appStats = appStatsCenter.getAppStatsList(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), TimeDimensionalityEnum.MINUTE); String result = assembleMutiStatAppStatsJsonMinute(appStats, statNameList, timeBetween.getStartDate()); model.addAttribute("data", result); return new ModelAndView(""); } /** * 获取命中率、丢失率等分布 * * @param appId 应用id * @param statName 统计项(hit,miss等) * @throws ParseException */ @RequestMapping("/getMutiDatesAppStats") public ModelAndView getMutiDatesAppStats(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, String statName, Integer addDay) throws ParseException { TimeBetween timeBetween = getJsonTimeBetween(request); List<AppStats> appStats = appStatsCenter.getAppStatsList(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), TimeDimensionalityEnum.MINUTE); String result = assembleMutilDateAppStatsJsonMinute(appStats, statName, timeBetween.getStartDate(), timeBetween.getEndDate()); model.addAttribute("data", result); return new ModelAndView(""); } /** * 获取指定时间内某个应用全部实例的统计信息 * @param appId */ @RequestMapping("/appInstanceNetStat") public ModelAndView appInstanceNetStat(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { // 应用基本信息 AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); model.addAttribute("appId", appId); // 日期格式转换 Date endDate; Date startDate; String startDateParam = request.getParameter("startDate"); String endDateParam = request.getParameter("endDate"); if (StringUtils.isBlank(startDateParam) || StringUtils.isBlank(endDateParam)) { startDate = new Date(); endDate = DateUtils.addDays(startDate, 1); startDateParam = DateUtil.formatDate(startDate, "yyyy-MM-dd"); endDateParam = DateUtil.formatDate(endDate, "yyyy-MM-dd"); } else { endDate = DateUtil.parseYYYY_MM_dd(endDateParam); startDate = DateUtil.parseYYYY_MM_dd(startDateParam); } model.addAttribute("startDate", startDateParam); model.addAttribute("endDate", endDateParam); return new ModelAndView("app/appInstanceNetStat"); } /** * 获取指定时间内某个应用全部实例的统计信息 * @param appId 应用流量 */ @RequestMapping("/getAppInstancesNetStat") public ModelAndView getAppInstancesNetStat(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { //时间转换 TimeBetween timeBetween = getJsonTimeBetween(request); //缩减字段 String netInCommand = "total_net_input_bytes"; String netOutCommand = "total_net_output_bytes"; Map<String,String> commandMap = new HashMap<String, String>(); commandMap.put(netInCommand, "i"); commandMap.put(netOutCommand, "o"); //获取应用下所有实例网络流量统计 Map<Integer, Map<String, List<InstanceCommandStats>>> appInstancesNetStat = instanceStatsCenter .getStandardStatsList(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), Arrays.asList(netInCommand, netOutCommand)); //解析成json数组 List<Map<String, Object>> appInstancesNetStatList = new ArrayList<Map<String, Object>>(); for (Entry<Integer, Map<String, List<InstanceCommandStats>>> entry : appInstancesNetStat.entrySet()) { Integer instanceId = entry.getKey(); //实例基本信息 Map<String, Object> instanceStatMap = new HashMap<String, Object>(); instanceStatMap.put("instanceId", instanceId); InstanceInfo instanceInfo = instanceStatsCenter.getInstanceInfo(instanceId); instanceStatMap.put("instanceInfo", instanceInfo.getIp() + ":" + instanceInfo.getPort()); //每个实例的统计信息 List<Map<String, Object>> instanceNetStatMapList = new ArrayList<Map<String, Object>>(); instanceStatMap.put("instanceNetStatMapList", instanceNetStatMapList); appInstancesNetStatList.add(instanceStatMap); //记录输入和输出流量 Map<String, List<InstanceCommandStats>> map = entry.getValue(); List<InstanceCommandStats> instanceCommandStatsList = new ArrayList<InstanceCommandStats>(); instanceCommandStatsList.addAll(map.get(netInCommand)); instanceCommandStatsList.addAll(map.get(netOutCommand)); Map<Long, Map<String, Object>> total = new HashMap<Long, Map<String, Object>>(); for (InstanceCommandStats instanceCommandStat : instanceCommandStatsList) { //用timestamp作为key,保证输入和输出流量在一个Map统计里 long timestamp = instanceCommandStat.getTimeStamp(); long commandCount = instanceCommandStat.getCommandCount(); String command = instanceCommandStat.getCommandName(); //精简字段 command = commandMap.get(command); if (total.containsKey(timestamp)) { Map<String,Object> tmpMap = total.get(timestamp); tmpMap.put(command, commandCount); } else { Map<String,Object> tmpMap = new HashMap<String, Object>(); tmpMap.put("t", timestamp); tmpMap.put(command, commandCount); total.put(timestamp, tmpMap); instanceNetStatMapList.add(tmpMap); } } } String result = JSONObject.toJSONString(appInstancesNetStatList); write(response, result); return null; } /** * * @param appId * @throws ParseException */ @RequestMapping("/getTop5Commands") public ModelAndView getAppTop5Commands(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { TimeBetween timeBetween = getJsonTimeBetween(request); List<AppCommandStats> appCommandStats = appStatsCenter.getTop5AppCommandStatsList(appId, timeBetween.getStartTime(), timeBetween.getEndTime()); String result = assembleJson(appCommandStats); write(response, result); return null; } /** * 应用各个命令分布情况 * * @param appId 应用id * @throws ParseException */ @RequestMapping("/appCommandDistribute") public ModelAndView appCommandDistribute(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { TimeBetween timeBetween = getJsonTimeBetween(request); List<AppCommandGroup> appCommandGroupList = appStatsCenter.getAppCommandGroup(appId, timeBetween.getStartTime(), timeBetween.getEndTime()); String result = assembleGroupJson(appCommandGroupList); write(response, result); return null; } /** * 应用列表 * * @param userId * @return */ @RequestMapping(value = "/list") public ModelAndView doAppList(HttpServletRequest request, HttpServletResponse response, Model model, AppSearch appSearch) { // 1.获取该用户能够读取的应用列表,没有返回申请页面 AppUser currentUser = getUserInfo(request); model.addAttribute("currentUser", currentUser); int userAppCount = appService.getUserAppCount(currentUser.getId()); if (userAppCount == 0 && !AppUserTypeEnum.ADMIN_USER.value().equals(currentUser.getType())) { return new ModelAndView("redirect:/admin/app/init"); } // 2.1 分页相关 int totalCount = appService.getAppDescCount(currentUser, appSearch); int pageNo = NumberUtils.toInt(request.getParameter("pageNo"), 1); int pageSize = NumberUtils.toInt(request.getParameter("pageSize"), 10); Page page = new Page(pageNo,pageSize, totalCount); model.addAttribute("page", page); // 2.2 查询指定时间客户端异常 appSearch.setPage(page); List<AppDesc> apps = appService.getAppDescList(currentUser, appSearch); // 2.3 应用列表 List<AppDetailVO> appDetailList = new ArrayList<AppDetailVO>(); model.addAttribute("appDetailList", appDetailList); // 3. 全局统计 long totalApplyMem = 0; long totalUsedMem = 0; long totalApps = 0; if (apps != null && apps.size() > 0) { for (AppDesc appDesc : apps) { AppDetailVO appDetail = appStatsCenter.getAppDetail(appDesc.getAppId()); appDetailList.add(appDetail); totalApplyMem += appDetail.getMem(); totalUsedMem += appDetail.getMemUsePercent() * appDetail.getMem() / 100.0; totalApps++; } } model.addAttribute("totalApps", totalApps); model.addAttribute("totalApplyMem", totalApplyMem); model.addAttribute("totalUsedMem", totalUsedMem); return new ModelAndView("app/appList"); } /** * 初始化应用申请 */ @RequestMapping(value = "/init") public ModelAndView doAppInit(HttpServletRequest request, HttpServletResponse response, Model model) { return new ModelAndView("app/appInit"); } /** * 添加应用 * * @param appDesc 应用实体 * @param memSize 申请容量(G) * @return */ @RequestMapping(value = "/add", method = RequestMethod.POST) public ModelAndView doAppAdd(HttpServletRequest request, HttpServletResponse response, Model model, AppDesc appDesc, String memSize) { AppUser appUser = getUserInfo(request); if (appDesc != null) { Timestamp now = new Timestamp(new Date().getTime()); appDesc.setCreateTime(now); appDesc.setPassedTime(now); appDesc.setVerId(1); appDesc.setStatus((short) AppStatusEnum.STATUS_ALLOCATED.getStatus()); appDeployCenter.createApp(appDesc, appUser, memSize); } return new ModelAndView("redirect:/admin/app/list"); } /** * 查看应用名是否存在 * * @param appName * @return */ @RequestMapping(value = "/checkAppNameExist") public ModelAndView doCheckAppNameExist(HttpServletRequest request, HttpServletResponse response, Model model, String appName) { AppDesc appDesc = appService.getAppByName(appName); if (appDesc != null) { write(response, String.valueOf(SuccessEnum.SUCCESS.value())); } else { write(response, String.valueOf(SuccessEnum.FAIL.value())); } return null; } /** * 应用命令查询 * * @param appId * @return */ @RequestMapping("/command") public ModelAndView command(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) { if (appId != null && appId > 0) { model.addAttribute("appId", appId); } return new ModelAndView("app/appCommand"); } /** * 执行应用命令 * * @param appId * @return */ @RequestMapping("/commandExecute") public ModelAndView commandExecute(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) { if (appId != null && appId > 0) { model.addAttribute("appId", appId); String command = request.getParameter("command"); String result = appStatsCenter.executeCommand(appId, command); model.addAttribute("result", result); } else { model.addAttribute("result", "error"); } return new ModelAndView("app/commandExecute"); } /** * 删除应用下的指定用户 * * @param userId * @param appId * @return */ @RequestMapping(value = "/deleteAppToUser") public ModelAndView doDeleteAppToUser(HttpServletRequest request, HttpServletResponse response, Model model, Long userId, Long appId) { if (userId != null && appId != null) { // 验证删除权限 AppUser currentUser = getUserInfo(request); List<AppToUser> appToUsers = appService.getAppToUserList(appId); if (CollectionUtils.isNotEmpty(appToUsers)) { for (AppToUser appToUser : appToUsers) { if (appToUser.getUserId().equals(currentUser.getId())) { write(response, String.valueOf(SuccessEnum.FAIL.value())); } } } appService.deleteAppToUser(appId, userId); write(response, String.valueOf(SuccessEnum.SUCCESS.value())); } else { write(response, String.valueOf(SuccessEnum.FAIL.value())); } return null; } /** * 更新用户 * @param name * @param chName * @param email * @param mobile * @param type * @param userId * @return */ @RequestMapping(value = "/changeAppUserInfo") public ModelAndView doAddUser(HttpServletRequest request, HttpServletResponse response, Model model, String name, String chName, String email, String mobile, Integer type, Long userId) { // 后台暂时不对参数进行验证 AppUser appUser = AppUser.buildFrom(userId, name, chName, email, mobile, type); try { if (userId == null) { userService.save(appUser); } else { userService.update(appUser); } write(response, String.valueOf(SuccessEnum.SUCCESS.value())); } catch (Exception e) { write(response, String.valueOf(SuccessEnum.FAIL.value())); logger.error(e.getMessage(), e); } return null; } /** * 扩容申请 * * @param appId 应用id * @param applyMemSize 申请容量 * @param appScaleReason 申请原因 * @return */ @RequestMapping(value = "/scale") public ModelAndView doScaleApp(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, String applyMemSize, String appScaleReason) { AppUser appUser = getUserInfo(request); AppDesc appDesc = appService.getByAppId(appId); AppAudit appAudit = appService.saveAppScaleApply(appDesc, appUser, applyMemSize, appScaleReason, AppAuditType.APP_SCALE); appEmailUtil.noticeAppResult(appDesc, appAudit); write(response, String.valueOf(SuccessEnum.SUCCESS.value())); return null; } /** * 应用修改配置申请 * * @param appId 应用id * @param appConfigKey 配置项 * @param appConfigValue 配置值 * @return */ @RequestMapping(value = "/changeAppConfig") public ModelAndView doChangeAppConfig(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, Long instanceId, String appConfigKey, String appConfigValue, String appConfigReason) { AppUser appUser = getUserInfo(request); AppDesc appDesc = appService.getByAppId(appId); AppAudit appAudit = appService.saveAppChangeConfig(appDesc, appUser, instanceId, appConfigKey, appConfigValue,appConfigReason, AppAuditType.APP_MODIFY_CONFIG); appEmailUtil.noticeAppResult(appDesc, appAudit); write(response, String.valueOf(SuccessEnum.SUCCESS.value())); return null; } /** * 实例修改配置申请 * * @param appId 应用id * @param appConfigKey 配置项 * @param appConfigValue 配置值 * @return */ @RequestMapping(value = "/changeInstanceConfig") public ModelAndView doChangeInstanceConfig(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, Long instanceId, String instanceConfigKey, String instanceConfigValue, String instanceConfigReason) { AppUser appUser = getUserInfo(request); AppDesc appDesc = appService.getByAppId(appId); AppAudit appAudit = appService.saveInstanceChangeConfig(appDesc, appUser, instanceId, instanceConfigKey, instanceConfigValue, instanceConfigReason, AppAuditType.INSTANCE_MODIFY_CONFIG); appEmailUtil.noticeAppResult(appDesc, appAudit); write(response, String.valueOf(SuccessEnum.SUCCESS.value())); return null; } /** * 添加应用和用户对应关系 * * @param appId 应用id * @param userName 用户名(邮箱前缀) * @return */ @RequestMapping(value = "/addAppToUser") public ModelAndView doAddAppToUser(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, String userName) { if (StringUtils.isNotBlank(userName)) { AppUser needAddAppUser = userService.getByName(userName); if (needAddAppUser != null) { appService.saveAppToUser(appId, needAddAppUser.getId()); write(response, String.valueOf(SuccessEnum.SUCCESS.value())); } else { write(response, String.valueOf(SuccessEnum.FAIL.value())); } } return null; } /** * 修改应用报警配置 */ @RequestMapping(value = "/changeAppAlertConfig") public ModelAndView doChangeAppAlertConfig(HttpServletRequest request, HttpServletResponse response, Model model) { long appId = NumberUtils.toLong(request.getParameter("appId"), -1); int memAlertValue = NumberUtils.toInt(request.getParameter("memAlertValue"), -1); int clientConnAlertValue = NumberUtils.toInt(request.getParameter("clientConnAlertValue"), -1); SuccessEnum result = appService.changeAppAlertConfig(appId, memAlertValue,clientConnAlertValue, getUserInfo(request)); write(response, String.valueOf(result.value())); return null; } /** * 修改应用信息 */ @RequestMapping(value = "/updateAppDetail") public ModelAndView doUpdateAppDetail(HttpServletRequest request, HttpServletResponse response, Model model) { long appId = NumberUtils.toLong(request.getParameter("appId"), 0); AppUser appUser = getUserInfo(request); logger.warn("{} want to update appId={} info!", appUser.getName(), appId); String appDescName = request.getParameter("appDescName"); String appDescIntro = request.getParameter("appDescIntro"); String officer = request.getParameter("officer"); SuccessEnum successEnum = SuccessEnum.SUCCESS; if (appId <= 0 || StringUtils.isBlank(appDescName) || StringUtils.isBlank(appDescIntro) || StringUtils.isBlank(officer)) { successEnum = SuccessEnum.FAIL; } else { try { AppDesc appDesc = appService.getByAppId(appId); appDesc.setName(appDescName); appDesc.setIntro(appDescIntro); appDesc.setOfficer(officer); appService.update(appDesc); } catch (Exception e) { logger.error(e.getMessage(), e); successEnum = SuccessEnum.FAIL; } } write(response, String.valueOf(successEnum.value())); return null; } @RequestMapping(value = "/demo") public ModelAndView doDemo(HttpServletRequest request, HttpServletResponse response, Long appId, Model model) { if (appId != null && appId > 0) { AppDesc appDesc = appService.getByAppId(appId); List<String> code = DemoCodeUtil.getCode(appDesc.getType(), appDesc.getAppId()); List<String> dependency = DemoCodeUtil.getDependencyRedis(); List<String> springConfig = DemoCodeUtil.getSpringConfig(appDesc.getType(), appDesc.getAppId()); String restApi = DemoCodeUtil.getRestAPI(appDesc.getType(), appDesc.getAppId()); if(CollectionUtils.isNotEmpty(springConfig) && springConfig.size() > 0){ model.addAttribute("springConfig", springConfig); } model.addAttribute("dependency",dependency); model.addAttribute("code", code); model.addAttribute("status", 1); model.addAttribute("restApi", restApi); } else { model.addAttribute("status", 0); } return new ModelAndView("app/appDemo"); } /** * 应用日报查询 */ @RequestMapping("/daily") public ModelAndView appDaily(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { // 1. 应用信息 AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); // 2. 日期 String dailyDateParam = request.getParameter("dailyDate"); Date date; if (StringUtils.isBlank(dailyDateParam)) { date = DateUtils.addDays(new Date(), -1); } else { date = DateUtil.parseYYYY_MM_dd(dailyDateParam); } model.addAttribute("dailyDate", dailyDateParam); // 3. 日报 AppDailyData appDailyData = appDailyDataCenter.getAppDailyData(appId, date); model.addAttribute("appDailyData", appDailyData); return new ModelAndView("app/appDaily"); } /** * 应用历史慢查询 * @param appId * @return * @throws ParseException */ @RequestMapping("/slowLog") public ModelAndView appSlowLog(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { // 应用基本信息 AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); // 开始和结束日期 String slowLogStartDateParam = request.getParameter("slowLogStartDate"); String slowLogEndDateParam = request.getParameter("slowLogEndDate"); Date startDate; Date endDate; if (StringUtils.isBlank(slowLogStartDateParam) || StringUtils.isBlank(slowLogEndDateParam)) { startDate = new Date(); endDate = DateUtils.addDays(startDate, 1); } else { startDate = DateUtil.parseYYYY_MM_dd(slowLogStartDateParam); endDate = DateUtil.parseYYYY_MM_dd(slowLogEndDateParam); } model.addAttribute("slowLogStartDate", slowLogStartDateParam); model.addAttribute("slowLogEndDate", slowLogEndDateParam); // 应用慢查询日志 Map<String,Long> appInstanceSlowLogCountMap = appStatsCenter.getInstanceSlowLogCountMapByAppId(appId, startDate, endDate); model.addAttribute("appInstanceSlowLogCountMap", appInstanceSlowLogCountMap); List<InstanceSlowLog> appInstanceSlowLogList = appStatsCenter.getInstanceSlowLogByAppId(appId, startDate, endDate); model.addAttribute("appInstanceSlowLogList", appInstanceSlowLogList); // 各个实例对应的慢查询日志 Map<String, List<InstanceSlowLog>> instaceSlowLogMap = new HashMap<String, List<InstanceSlowLog>>(); Map<String, Long> instanceHostPortIdMap = new HashMap<String, Long>(); for(InstanceSlowLog instanceSlowLog : appInstanceSlowLogList) { String hostPort = instanceSlowLog.getIp() + ":" + instanceSlowLog.getPort(); instanceHostPortIdMap.put(hostPort, instanceSlowLog.getInstanceId()); if(instaceSlowLogMap.containsKey(hostPort)) { instaceSlowLogMap.get(hostPort).add(instanceSlowLog); } else { List<InstanceSlowLog> list = new ArrayList<InstanceSlowLog>(); list.add(instanceSlowLog); instaceSlowLogMap.put(hostPort, list); } } model.addAttribute("instaceSlowLogMap", instaceSlowLogMap); model.addAttribute("instanceHostPortIdMap", instanceHostPortIdMap); return new ModelAndView("app/slowLog"); } /** * 清理应用数据 */ @RequestMapping(value = "/cleanAppData") public ModelAndView doCleanAppData(HttpServletRequest request, HttpServletResponse response, Model model, long appId) { AppUser appUser = getUserInfo(request); logger.warn("{} start to clean appId={} data!", appUser.getName(), appId); SuccessEnum successEnum = SuccessEnum.FAIL; if (appId > 0) { //验证用户对应用的权限 以及数据清理的结果 if (checkAppUserProvilege(request, appId) && appDeployCenter.cleanAppData(appId, getUserInfo(request))) { successEnum = SuccessEnum.SUCCESS; } } logger.warn("{} end to clean appId={} data, result is {}", appUser.getName(), appId, successEnum.info()); write(response, String.valueOf(successEnum.value())); return null; } /** * AppCommandGroup列表组装成json串 */ private String assembleGroupJson(List<AppCommandGroup> appCommandGroupList) { if (appCommandGroupList == null || appCommandGroupList.isEmpty()) { return "[]"; } List<SimpleChartData> list = new ArrayList<SimpleChartData>(); for (AppCommandGroup appCommandGroup : appCommandGroupList) { SimpleChartData chartData = SimpleChartData .getFromAppCommandGroup(appCommandGroup); list.add(chartData); } JSONArray jsonArray = JSONArray.fromObject(list); return jsonArray.toString(); } /** * AppStats列表组装成json串 */ private String assembleAppStatsJson(List<AppStats> appStats, String statName) { if (appStats == null || appStats.isEmpty()) { return "[]"; } List<SimpleChartData> list = new ArrayList<SimpleChartData>(); for (AppStats stat : appStats) { try { SimpleChartData chartData = SimpleChartData.getFromAppStats(stat, statName); list.add(chartData); } catch (ParseException e) { logger.info(e.getMessage(), e); } } JSONArray jsonArray = JSONArray.fromObject(list); return jsonArray.toString(); } private String assembleMutilDateAppCommandJsonMinute(List<AppCommandStats> appCommandStats, Date startDate, Date endDate) { if (appCommandStats == null || appCommandStats.isEmpty()) { return "[]"; } Map<String, List<HighchartPoint>> map = new HashMap<String, List<HighchartPoint>>(); Date currentDate = DateUtils.addDays(endDate, -1); int diffDays = 0; while (currentDate.getTime() >= startDate.getTime()) { List<HighchartPoint> list = new ArrayList<HighchartPoint>(); for (AppCommandStats stat : appCommandStats) { try { HighchartPoint highchartPoint = HighchartPoint.getFromAppCommandStats(stat, currentDate, diffDays); if (highchartPoint == null) { continue; } list.add(highchartPoint); } catch (ParseException e) { logger.info(e.getMessage(), e); } } String formatDate = DateUtil.formatDate(currentDate, "yyyy-MM-dd"); map.put(formatDate, list); currentDate = DateUtils.addDays(currentDate, -1); diffDays++; } net.sf.json.JSONObject jsonObject = net.sf.json.JSONObject.fromObject(map); return jsonObject.toString(); } /** * 多命令组装 * @param appStats * @param statNameList * @param startDate * @return */ private String assembleMutiStatAppStatsJsonMinute(List<AppStats> appStats, List<String> statNameList, Date startDate) { if (appStats == null || appStats.isEmpty()) { return "[]"; } Map<String, List<HighchartPoint>> map = new HashMap<String, List<HighchartPoint>>(); for(String statName : statNameList) { List<HighchartPoint> list = new ArrayList<HighchartPoint>(); for (AppStats stat : appStats) { try { HighchartPoint highchartPoint = HighchartPoint.getFromAppStats(stat, statName, startDate, 0); if (highchartPoint == null) { continue; } list.add(highchartPoint); } catch (ParseException e) { logger.info(e.getMessage(), e); } } map.put(statName, list); } net.sf.json.JSONObject jsonObject = net.sf.json.JSONObject.fromObject(map); return jsonObject.toString(); } /** * 多时间组装 * @param appStats * @param statName * @param startDate * @param endDate * @return */ private String assembleMutilDateAppStatsJsonMinute(List<AppStats> appStats, String statName, Date startDate, Date endDate) { if (appStats == null || appStats.isEmpty()) { return "[]"; } Map<String, List<HighchartPoint>> map = new HashMap<String, List<HighchartPoint>>(); Date currentDate = DateUtils.addDays(endDate, -1); int diffDays = 0; while (currentDate.getTime() >= startDate.getTime()) { List<HighchartPoint> list = new ArrayList<HighchartPoint>(); for (AppStats stat : appStats) { try { HighchartPoint highchartPoint = HighchartPoint.getFromAppStats(stat, statName, currentDate, diffDays); if (highchartPoint == null) { continue; } list.add(highchartPoint); } catch (ParseException e) { logger.info(e.getMessage(), e); } } String formatDate = DateUtil.formatDate(currentDate, "yyyy-MM-dd"); map.put(formatDate, list); currentDate = DateUtils.addDays(currentDate, -1); diffDays++; } net.sf.json.JSONObject jsonObject = net.sf.json.JSONObject.fromObject(map); return jsonObject.toString(); } /** * AppCommandStats列表组装成json串 */ private String assembleJson(List<AppCommandStats> appCommandStatsList) { return assembleJson(appCommandStatsList, null); } private String assembleJson(List<AppCommandStats> appCommandStatsList, Integer addDay) { if (appCommandStatsList == null || appCommandStatsList.isEmpty()) { return "[]"; } List<SimpleChartData> list = new ArrayList<SimpleChartData>(); for (AppCommandStats stat : appCommandStatsList) { try { SimpleChartData chartData = SimpleChartData .getFromAppCommandStats(stat, addDay); list.add(chartData); } catch (ParseException e) { logger.info(e.getMessage(), e); } } JSONArray jsonArray = JSONArray.fromObject(list); return jsonArray.toString(); } }