/* * * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.tools.pulse.internal.service; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import org.apache.geode.tools.pulse.internal.controllers.PulseController; import org.apache.geode.tools.pulse.internal.data.Cluster; import org.apache.geode.tools.pulse.internal.data.PulseConstants; import org.apache.geode.tools.pulse.internal.data.Repository; import org.apache.geode.tools.pulse.internal.log.PulseLogWriter; import org.apache.geode.tools.pulse.internal.util.StringUtils; import org.apache.geode.tools.pulse.internal.util.TimeUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; /** * Class ClusterSelectedRegionService * * This class contains implementations of getting Cluster's selected region details * * @since GemFire version 7.5 cedar 2014-03-01 */ @Component @Service("ClusterSelectedRegion") @Scope("singleton") public class ClusterSelectedRegionService implements PulseService { private final ObjectMapper mapper = new ObjectMapper(); // String constants used for forming a json response private final String ENTRY_SIZE = "entrySize"; // Comparator based upon regions entry count private static Comparator<Cluster.Member> memberCurrentHeapUsageComparator = (m1, m2) -> { long m1HeapUsage = m1.getCurrentHeapSize(); long m2HeapUsage = m2.getCurrentHeapSize(); if (m1HeapUsage < m2HeapUsage) { return -1; } else if (m1HeapUsage > m2HeapUsage) { return 1; } else { return 0; } }; @Override public ObjectNode execute(final HttpServletRequest request) throws Exception { String userName = request.getUserPrincipal().getName(); String pulseData = request.getParameter("pulseData"); JsonNode parameterMap = mapper.readTree(pulseData); String selectedRegionFullPath = parameterMap.get("ClusterSelectedRegion").get("regionFullPath").textValue(); // get cluster object Cluster cluster = Repository.get().getCluster(); // json object to be sent as response ObjectNode responseJSON = mapper.createObjectNode(); // getting cluster's Regions responseJSON.put("clusterName", cluster.getServerName()); responseJSON.put("userName", userName); responseJSON.put("selectedRegion", getSelectedRegionJson(cluster, selectedRegionFullPath)); // Send json response return responseJSON; } /** * Create JSON for selected cluster region * * @param cluster * @return ObjectNode Array List */ private ObjectNode getSelectedRegionJson(Cluster cluster, String selectedRegionFullPath) { PulseLogWriter LOGGER = PulseLogWriter.getLogger(); Long totalHeapSize = cluster.getTotalHeapSize(); Long totalDiskUsage = cluster.getTotalBytesOnDisk(); Cluster.Region reg = cluster.getClusterRegion(selectedRegionFullPath); if (reg != null) { ObjectNode regionJSON = mapper.createObjectNode(); regionJSON.put("name", reg.getName()); regionJSON.put("path", reg.getFullPath()); regionJSON.put("totalMemory", totalHeapSize); regionJSON.put("systemRegionEntryCount", reg.getSystemRegionEntryCount()); regionJSON.put("memberCount", reg.getMemberCount()); final String regionType = reg.getRegionType(); regionJSON.put("type", regionType); regionJSON.put("getsRate", reg.getGetsRate()); regionJSON.put("putsRate", reg.getPutsRate()); regionJSON.put("lruEvictionRate", reg.getLruEvictionRate()); DecimalFormat df2 = new DecimalFormat(PulseConstants.DECIMAL_FORMAT_PATTERN); Cluster.Member[] clusterMembersList = cluster.getMembers(); // collect members of this region List<Cluster.Member> clusterMembersL = new ArrayList<Cluster.Member>(); for (String memberName : reg.getMemberName()) { for (Cluster.Member member : clusterMembersList) { String name = member.getName(); name = name.replace(":", "-"); String id = member.getId(); id = id.replace(":", "-"); if ((memberName.equals(id)) || (memberName.equals(name))) { clusterMembersL.add(member); } } } // sort members of this region Collections.sort(clusterMembersL, memberCurrentHeapUsageComparator); // return sorted member list by heap usage ArrayNode memberArray = mapper.createArrayNode(); for (Cluster.Member member : clusterMembersL) { ObjectNode regionMember = mapper.createObjectNode(); regionMember.put("memberId", member.getId()); regionMember.put("name", member.getName()); regionMember.put("host", member.getHost()); long usedHeapSize = cluster.getUsedHeapSize(); long currentHeap = member.getCurrentHeapSize(); if (usedHeapSize > 0) { double heapUsage = ((double) currentHeap / (double) usedHeapSize) * 100; regionMember.put("heapUsage", Double.valueOf(df2.format(heapUsage))); } else { regionMember.put("heapUsage", 0); } double currentCPUUsage = member.getCpuUsage(); double loadAvg = member.getLoadAverage(); regionMember.put("cpuUsage", Double.valueOf(df2.format(currentCPUUsage))); regionMember.put("currentHeapUsage", member.getCurrentHeapSize()); regionMember.put("isManager", member.isManager()); regionMember.put("uptime", TimeUtils.convertTimeSecondsToHMS(member.getUptime())); regionMember.put("loadAvg", Double.valueOf(df2.format(loadAvg))); regionMember.put("sockets", member.getTotalFileDescriptorOpen()); regionMember.put("threads", member.getNumThreads()); regionMember.put("clients", member.getMemberClientsHMap().size()); regionMember.put("queues", member.getQueueBacklog()); memberArray.add(regionMember); } regionJSON.put("members", memberArray); regionJSON.put("entryCount", reg.getSystemRegionEntryCount()); regionJSON.put("persistence", reg.getPersistentEnabled() ? PulseService.VALUE_ON : PulseService.VALUE_OFF); regionJSON.put("isEnableOffHeapMemory", reg.isEnableOffHeapMemory() ? PulseService.VALUE_ON : PulseService.VALUE_OFF); String regCompCodec = reg.getCompressionCodec(); if (StringUtils.isNotNullNotEmptyNotWhiteSpace(regCompCodec)) { regionJSON.put("compressionCodec", reg.getCompressionCodec()); } else { regionJSON.put("compressionCodec", PulseService.VALUE_NA); } regionJSON.put("regionPath", reg.getFullPath()); regionJSON.put("memoryReadsTrend", mapper.<JsonNode>valueToTree( reg.getRegionStatisticTrend(Cluster.Region.REGION_STAT_GETS_PER_SEC_TREND))); regionJSON.put("memoryWritesTrend", mapper.<JsonNode>valueToTree( reg.getRegionStatisticTrend(Cluster.Region.REGION_STAT_PUTS_PER_SEC_TREND))); regionJSON.put("diskReadsTrend", mapper.<JsonNode>valueToTree( reg.getRegionStatisticTrend(Cluster.Region.REGION_STAT_DISK_READS_PER_SEC_TREND))); regionJSON.put("diskWritesTrend", mapper.<JsonNode>valueToTree( reg.getRegionStatisticTrend(Cluster.Region.REGION_STAT_DISK_WRITES_PER_SEC_TREND))); regionJSON.put("emptyNodes", reg.getEmptyNode()); Long entrySize = reg.getEntrySize(); DecimalFormat form = new DecimalFormat(PulseConstants.DECIMAL_FORMAT_PATTERN_2); String entrySizeInMB = form.format(entrySize / (1024f * 1024f)); if (entrySize < 0) { regionJSON.put(this.ENTRY_SIZE, PulseService.VALUE_NA); } else { regionJSON.put(this.ENTRY_SIZE, entrySizeInMB); } regionJSON.put("dataUsage", reg.getDiskUsage()); regionJSON.put("wanEnabled", reg.getWanEnabled()); regionJSON.put("totalDataUsage", totalDiskUsage); regionJSON.put("memoryUsage", entrySizeInMB); LOGGER.fine("calling getSelectedRegionJson :: regionJSON = " + regionJSON); return regionJSON; } else { ObjectNode responseJSON = mapper.createObjectNode(); responseJSON.put("errorOnRegion", "Region [" + selectedRegionFullPath + "] is not available"); return responseJSON; } } }