http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9a2b5d7b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMemberService.java ---------------------------------------------------------------------- diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMemberService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMemberService.java new file mode 100644 index 0000000..6a42c0d --- /dev/null +++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMemberService.java @@ -0,0 +1,132 @@ +/* + * + * 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 com.vmware.geode.tools.pulse.internal.service; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.vmware.geode.tools.pulse.internal.controllers.PulseController; +import com.vmware.geode.tools.pulse.internal.data.Cluster; +import com.vmware.geode.tools.pulse.internal.data.PulseConstants; +import com.vmware.geode.tools.pulse.internal.data.Repository; +import com.vmware.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.math.BigDecimal; +import java.math.RoundingMode; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; + +/** + * Class ClusterMemberService + * + * This class contains implementations of getting Cluster Member's details + * + * @since GemFire version 7.5 + */ +@Component +// @Service("ClusterMember") +@Service("ClusterMembers") +@Scope("singleton") +public class ClusterMemberService implements PulseService { + + private final ObjectMapper mapper = new ObjectMapper(); + + private final String HEAP_USAGE = "heapUsage"; + + public ObjectNode execute(final HttpServletRequest request) throws Exception { + + // get cluster object + Cluster cluster = Repository.get().getCluster(); + + // json object to be sent as response + ObjectNode responseJSON = mapper.createObjectNode(); + + Cluster.Member[] clusterMembersList = cluster.getMembers(); + + // create members json + ArrayNode memberListJson = mapper.createArrayNode(); + for (Cluster.Member clusterMember : clusterMembersList) { + ObjectNode memberJSON = mapper.createObjectNode(); + // getting members detail + memberJSON.put("gemfireVersion", clusterMember.getGemfireVersion()); + memberJSON.put("memberId", clusterMember.getId()); + memberJSON.put("name", clusterMember.getName()); + memberJSON.put("host", clusterMember.getHost()); + + List<String> serverGroups = clusterMember.getServerGroups(); + if(serverGroups.size() == 0){ + serverGroups = new ArrayList<>(); + serverGroups.add(PulseConstants.DEFAULT_SERVER_GROUP); + } + + memberJSON.put("serverGroups", mapper.valueToTree(serverGroups)); + + List<String> redundancyZones = clusterMember.getRedundancyZones(); + if(redundancyZones.size() == 0){ + redundancyZones = new ArrayList<String>(); + redundancyZones.add(PulseConstants.DEFAULT_REDUNDANCY_ZONE); + } + memberJSON.put("redundancyZones", mapper.valueToTree(redundancyZones)); + + long usedHeapSize = cluster.getUsedHeapSize(); + long currentHeap = clusterMember.getCurrentHeapSize(); + if (usedHeapSize > 0) { + double heapUsage = ((double) currentHeap / (double) usedHeapSize) * 100; + memberJSON.put(this.HEAP_USAGE, truncate(heapUsage, 2)); + } else { + memberJSON.put(this.HEAP_USAGE, 0); + } + double currentCPUUsage = clusterMember.getCpuUsage(); + double loadAvg = clusterMember.getLoadAverage(); + + memberJSON.put("cpuUsage", truncate(currentCPUUsage, 2)); + memberJSON.put("currentHeapUsage", clusterMember.getCurrentHeapSize()); + memberJSON.put("isManager", clusterMember.isManager()); + memberJSON.put("uptime", TimeUtils.convertTimeSecondsToHMS(clusterMember.getUptime())); + memberJSON.put("loadAvg", truncate(loadAvg, 2)); + memberJSON.put("sockets", clusterMember.getTotalFileDescriptorOpen()); + memberJSON.put("threads", clusterMember.getNumThreads()); + + // Number of member clients + if (PulseController.getPulseProductSupport().equalsIgnoreCase( + PulseConstants.PRODUCT_NAME_SQLFIRE)){ + memberJSON.put("clients", clusterMember.getNumSqlfireClients()); + }else{ + memberJSON.put("clients", clusterMember.getMemberClientsHMap().size()); + } + memberJSON.put("queues", clusterMember.getQueueBacklog()); + + memberListJson.add(memberJSON); + } + // cluster's Members + responseJSON.put("members", memberListJson); + // Send json response + return responseJSON; + } + + private double truncate(double value, int places) { + return new BigDecimal(value).setScale(places, RoundingMode.HALF_UP).doubleValue(); + } +}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9a2b5d7b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMembersRGraphService.java ---------------------------------------------------------------------- diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMembersRGraphService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMembersRGraphService.java new file mode 100644 index 0000000..f8617cb --- /dev/null +++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMembersRGraphService.java @@ -0,0 +1,359 @@ +/* + * + * 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 com.vmware.geode.tools.pulse.internal.service; + +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; + +import com.vmware.geode.tools.pulse.internal.data.Cluster; +import com.vmware.geode.tools.pulse.internal.data.PulseConstants; +import com.vmware.geode.tools.pulse.internal.data.Repository; + +/** + * Class ClusterMembersRGraphService + * + * This class contains implementations of getting List of Cluster members and + * their details + * + * @since GemFire version 7.5 + */ +@Component +@Service("ClusterMembersRGraph") +@Scope("singleton") +public class ClusterMembersRGraphService implements PulseService { + + private final ObjectMapper mapper = new ObjectMapper(); + + // String constants used for forming a json response + private final String CLUSTER = "clustor"; + private final String MEMBER_COUNT = "memberCount"; + private final String ID = "id"; + private final String NAME = "name"; + private final String DATA = "data"; + private final String MEMORY_USAGE = "memoryUsage"; + private final String CPU_USAGE = "cpuUsage"; + private final String REGIONS = "regions"; + private final String HOST = "host"; + private final String PORT = "port"; + private final String CLIENTS = "clients"; + private final String GC_PAUSES = "gcPauses"; + private final String GATEWAY_SENDER = "gatewaySender"; + private final String GATEWAY_RECEIVER = "gatewayReceiver"; + private final String LOAD_AVG = "loadAvg"; + private final String SOCKETS = "sockets"; + private final String THREADS = "threads"; + private final String NUM_THREADS = "numThreads"; + + private final String MEMBER_NODE_TYPE_NORMAL = "Normal"; + private final String MEMBER_NODE_TYPE_WARNING = "Warning"; + private final String MEMBER_NODE_TYPE_ERROR = "Error"; + private final String MEMBER_NODE_TYPE_SEVERE = "Severe"; + private final String CHILDREN = "children"; + + // traversing the alert array list and members which have severe, error or + // warnings + // alerts saving them in three different arraylists + private List<String> severeAlertList; + private List<String> errorAlertsList; + private List<String> warningAlertsList; + + public ObjectNode execute(final HttpServletRequest request) throws Exception { + + // Reference to repository + Repository repository = Repository.get(); + + // get cluster object + Cluster cluster = repository.getCluster(); + + // json object to be sent as response + ObjectNode responseJSON = mapper.createObjectNode(); + + // cluster's Members + responseJSON.put(this.CLUSTER, + getPhysicalServerJson(cluster, repository.getJmxHost(), repository.getJmxPort())); + responseJSON.put(this.MEMBER_COUNT, cluster.getMemberCount()); + + // Send json response + return responseJSON; + } + + /** + * function used for getting all members details in format of JSON Object + * array defined under a cluster. This function create json based on the + * relation of physical host and members related to it. + * + * @param cluster + * @param host + * @param port + * @return Array list of JSON objects for required fields of members in + * cluster + */ + private ObjectNode getPhysicalServerJson(Cluster cluster, String host, String port) { + Map<String, List<Cluster.Member>> physicalToMember = cluster.getPhysicalToMember(); + + ObjectNode clusterTopologyJSON = mapper.createObjectNode(); + + clusterTopologyJSON.put(this.ID, cluster.getClusterId()); + clusterTopologyJSON.put(this.NAME, cluster.getClusterId()); + ObjectNode data1 = mapper.createObjectNode(); + clusterTopologyJSON.put(this.DATA, data1); + ArrayNode childHostArray = mapper.createArrayNode(); + DecimalFormat df2 = new DecimalFormat(PulseConstants.DECIMAL_FORMAT_PATTERN); + + updateAlertLists(cluster); + + for (Map.Entry<String, List<Cluster.Member>> physicalToMem : physicalToMember.entrySet()) { + String hostName = physicalToMem.getKey(); + double hostCpuUsage = 0.0; + long hostMemoryUsage = 0; + double hostLoadAvg = 0.0; + int hostNumThreads = 0; + long hostSockets = 0; + boolean hostSevere = false; + boolean hostError = false; + boolean hostWarning = false; + String hostStatus; + ObjectNode childHostObject = mapper.createObjectNode(); + childHostObject.put(this.ID, hostName); + childHostObject.put(this.NAME, hostName); + + ArrayNode membersArray = mapper.createArrayNode(); + + List<Cluster.Member> memberList = physicalToMem.getValue(); + for (Cluster.Member member : memberList) { + ObjectNode memberJSONObj = mapper.createObjectNode(); + + memberJSONObj.put(this.ID, member.getId()); + memberJSONObj.put(this.NAME, member.getName()); + + ObjectNode memberData = mapper.createObjectNode(); + + memberData.put("gemfireVersion", member.getGemfireVersion()); + + Long currentHeap = member.getCurrentHeapSize(); + Long usedHeapSize = cluster.getUsedHeapSize(); + + if (usedHeapSize > 0) { + double heapUsage = (currentHeap.doubleValue() / usedHeapSize.doubleValue()) * 100; + + memberData.put(this.MEMORY_USAGE, + Double.valueOf(df2.format(heapUsage))); + } else + memberData.put(this.MEMORY_USAGE, 0); + + double currentCPUUsage = member.getCpuUsage(); + + memberData.put(this.CPU_USAGE, + Double.valueOf(df2.format(currentCPUUsage))); + memberData.put(this.REGIONS, member.getMemberRegions().size()); + memberData.put(this.HOST, member.getHost()); + if ((member.getMemberPort() == null) + || (member.getMemberPort().equals(""))) { + memberData.put(this.PORT, "-"); + } else { + memberData.put(this.PORT, member.getMemberPort()); + } + memberData.put(this.CLIENTS, member.getMemberClientsHMap().size()); + memberData.put(this.GC_PAUSES, member.getGarbageCollectionCount()); + memberData.put(this.NUM_THREADS, member.getNumThreads()); + + // Host CPU Usage is aggregate of all members cpu usage + // hostCpuUsage = hostCpuUsage + currentCPUUsage; + hostCpuUsage = member.getHostCpuUsage(); + hostMemoryUsage = hostMemoryUsage + member.getCurrentHeapSize(); + hostLoadAvg = member.getLoadAverage(); + hostNumThreads = member.getNumThreads(); + hostSockets = member.getTotalFileDescriptorOpen(); + + // defining the status of Member Icons for R Graph based on the alerts + // created for that member + String memberNodeType = ""; + // for severe alert + if (severeAlertList.contains(member.getName())) { + memberNodeType = getMemberNodeType(member, this.MEMBER_NODE_TYPE_SEVERE); + if (!hostSevere) { + hostSevere = true; + } + } else if (errorAlertsList.contains(member.getName())) { + // for error alerts + memberNodeType = getMemberNodeType(member, + this.MEMBER_NODE_TYPE_ERROR); + if (!hostError) { + hostError = true; + } + } + // for warning alerts + else if (warningAlertsList.contains(member.getName())) { + memberNodeType = getMemberNodeType(member, this.MEMBER_NODE_TYPE_WARNING); + if (!hostWarning) { + hostWarning = true; + } + } else { + memberNodeType = getMemberNodeType(member, this.MEMBER_NODE_TYPE_NORMAL); + } + + memberData.put("nodeType", memberNodeType); + memberData.put("$type", memberNodeType); + memberData.put(this.GATEWAY_SENDER, member.getGatewaySenderList().size()); + if (member.getGatewayReceiver() != null) { + memberData.put(this.GATEWAY_RECEIVER, 1); + } else { + memberData.put(this.GATEWAY_RECEIVER, 0); + } + memberJSONObj.put(this.DATA, memberData); + memberJSONObj.put(this.CHILDREN, mapper.createArrayNode()); + membersArray.add(memberJSONObj); + } + ObjectNode data = mapper.createObjectNode(); + + data.put(this.LOAD_AVG, Double.valueOf(df2.format(hostLoadAvg))); + data.put(this.SOCKETS, hostSockets); + data.put(this.THREADS, hostNumThreads); + data.put(this.CPU_USAGE, Double.valueOf(df2.format(hostCpuUsage))); + data.put(this.MEMORY_USAGE, hostMemoryUsage); + + String hostNodeType; + // setting physical host status + if (hostSevere) { + hostStatus = this.MEMBER_NODE_TYPE_SEVERE; + hostNodeType = "hostSevereNode"; + } else if (hostError) { + hostStatus = this.MEMBER_NODE_TYPE_ERROR; + hostNodeType = "hostErrorNode"; + } else if (hostWarning) { + hostStatus = this.MEMBER_NODE_TYPE_WARNING; + hostNodeType = "hostWarningNode"; + } else { + hostStatus = this.MEMBER_NODE_TYPE_NORMAL; + hostNodeType = "hostNormalNode"; + } + data.put("hostStatus", hostStatus); + data.put("$type", hostNodeType); + + childHostObject.put(this.DATA, data); + + childHostObject.put(this.CHILDREN, membersArray); + childHostArray.add(childHostObject); + } + clusterTopologyJSON.put(this.CHILDREN, childHostArray); + + return clusterTopologyJSON; + } + + /** + * used for getting member node type based on member's current state + * + * @param member + * Member + * @param memberState + * i.e Severe, Error, Warning or Normal + * @return + */ + private String getMemberNodeType(Cluster.Member member, String memberState) { + String memberNodeType = ""; + + if ((member.isLocator()) && (member.isServer()) && (member.isManager())) { + memberNodeType = "memberLocatorManagerServer" + memberState + "Node"; + } else if ((member.isLocator()) && (member.isServer()) + && !(member.isManager())) { + memberNodeType = "memberLocatorServer" + memberState + "Node"; + } else if ((member.isLocator()) && !(member.isServer()) + && (member.isManager())) { + memberNodeType = "memberLocatorManager" + memberState + "Node"; + } else if ((member.isLocator()) && !(member.isServer()) + && !(member.isManager())) { + memberNodeType = "memberLocator" + memberState + "Node"; + } else if (!(member.isLocator()) && (member.isServer()) + && (member.isManager())) { + memberNodeType = "memberManagerServer" + memberState + "Node"; + } else if (!(member.isLocator()) && (member.isServer()) + && !(member.isManager())) { + memberNodeType = "memberServer" + memberState + "Node"; + } else if (!(member.isLocator()) && !(member.isServer()) + && (member.isManager())) { + memberNodeType = "memberManager" + memberState + "Node"; + } else if (!(member.isLocator()) && !(member.isServer()) + && !(member.isManager())) { + memberNodeType = "member" + memberState + "Node"; + } + return memberNodeType; + } + + /** + * function used for getting list of all the alerts and save the member names + * in respective error, warning and severe alert lists + * + * @param cluster + */ + private void updateAlertLists(Cluster cluster) { + + severeAlertList = new ArrayList<String>(); + errorAlertsList = new ArrayList<String>(); + warningAlertsList = new ArrayList<String>(); + + Cluster.Alert[] alertsList = cluster.getAlertsList(); + + for (Cluster.Alert alert : alertsList) { + // if alert is severe + if (alert.getSeverity() == Cluster.Alert.SEVERE) { + if (errorAlertsList.contains(alert.getMemberName())) { + errorAlertsList.remove(alert.getMemberName()); + } else if (warningAlertsList.contains(alert.getMemberName())) { + warningAlertsList.remove(alert.getMemberName()); + } + if (!severeAlertList.contains(alert.getMemberName())) { + severeAlertList.add(alert.getMemberName()); + } + } + // if alert is error + else if (alert.getSeverity() == Cluster.Alert.ERROR) { + if (!severeAlertList.contains(alert.getMemberName())) { + if (warningAlertsList.contains(alert.getMemberName())) { + warningAlertsList.remove(alert.getMemberName()); + } + if (!errorAlertsList.contains(alert.getMemberName())) { + errorAlertsList.add(alert.getMemberName()); + } + } + } + // if alert is warning + else if (alert.getSeverity() == Cluster.Alert.WARNING) { + if (!severeAlertList.contains(alert.getMemberName())) { + if (!errorAlertsList.contains(alert.getMemberName())) { + if (!warningAlertsList.contains(alert.getMemberName())) { + warningAlertsList.add(alert.getMemberName()); + } + } + } + } + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9a2b5d7b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMemoryUsageService.java ---------------------------------------------------------------------- diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMemoryUsageService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMemoryUsageService.java new file mode 100644 index 0000000..519deb1 --- /dev/null +++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMemoryUsageService.java @@ -0,0 +1,65 @@ +/* + * + * 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 com.vmware.geode.tools.pulse.internal.service; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.vmware.geode.tools.pulse.internal.data.Cluster; +import com.vmware.geode.tools.pulse.internal.data.Repository; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletRequest; + +/** + * Class ClusterMemoryUsageService + * + * This class contains implementations of getting Cluster's overall current + * memory usage details and its trend over the time. + * + * @since GemFire version 7.5 + */ + +@Component +@Service("ClusterMemoryUsage") +@Scope("singleton") +public class ClusterMemoryUsageService implements PulseService { + + private final ObjectMapper mapper = new ObjectMapper(); + + public ObjectNode execute(final HttpServletRequest request) throws Exception { + + // get cluster object + Cluster cluster = Repository.get().getCluster(); + + // json object to be sent as response + ObjectNode responseJSON = mapper.createObjectNode(); + + // cluster's Memory Usage trend added to json response object + + responseJSON.put("currentMemoryUsage", cluster.getUsedHeapSize()); + responseJSON.put("memoryUsageTrend", + mapper.valueToTree(cluster.getStatisticTrend(Cluster.CLUSTER_STAT_MEMORY_USAGE))); + + // Send json response + return responseJSON; + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9a2b5d7b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterRegionService.java ---------------------------------------------------------------------- diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterRegionService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterRegionService.java new file mode 100644 index 0000000..1723a98 --- /dev/null +++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterRegionService.java @@ -0,0 +1,211 @@ +/* + * + * 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 com.vmware.geode.tools.pulse.internal.service; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.vmware.geode.tools.pulse.internal.controllers.PulseController; +import com.vmware.geode.tools.pulse.internal.data.Cluster; +import com.vmware.geode.tools.pulse.internal.data.PulseConstants; +import com.vmware.geode.tools.pulse.internal.data.Repository; +import com.vmware.geode.tools.pulse.internal.util.StringUtils; +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; +import java.util.Map; + +/** + * Class ClusterRegionService + * + * This class contains implementations of getting Cluster's regions details + * + * @since GemFire version 7.5 + */ + +@Component +@Service("ClusterRegion") +@Scope("singleton") +public class ClusterRegionService 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.Region> regionEntryCountComparator = (r1, r2) -> { + long r1Cnt = r1.getSystemRegionEntryCount(); + long r2Cnt = r2.getSystemRegionEntryCount(); + if (r1Cnt < r2Cnt) { + return -1; + } else if (r1Cnt > r2Cnt) { + return 1; + } else { + return 0; + } + }; + + @Override + public ObjectNode execute(final HttpServletRequest request) throws Exception { + + String userName = request.getUserPrincipal().getName(); + + // 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("region", getRegionJson(cluster)); + + // Send json response + return responseJSON; + } + + /** + * This method is used to get various regions associated with the given + * cluster and create json for each region fields and returns Array List for + * all the regions associated with given cluster + * + * @param cluster + * @return ArrayNode Array List + */ + private ArrayNode getRegionJson(Cluster cluster) { + + Long totalHeapSize = cluster.getTotalHeapSize(); + Long totalDiskUsage = cluster.getTotalBytesOnDisk(); + + Map<String, Cluster.Region> clusterRegions = cluster.getClusterRegions(); + + List<Cluster.Region> clusterRegionsList = new ArrayList<Cluster.Region>(); + clusterRegionsList.addAll(clusterRegions.values()); + + Collections.sort(clusterRegionsList, regionEntryCountComparator); + + ArrayNode regionListJson = mapper.createArrayNode(); + for (int count = 0; count < clusterRegionsList.size(); count++) { + Cluster.Region reg = clusterRegionsList.get(count); + ObjectNode regionJSON = mapper.createObjectNode(); + + regionJSON.put("name", reg.getName()); + 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()); + + Cluster.Member[] clusterMembersList = cluster.getMembers(); + + ArrayNode memberNameArray = mapper.createArrayNode(); + 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))) { + ObjectNode regionMember = mapper.createObjectNode(); + regionMember.put("id", member.getId()); + regionMember.put("name", member.getName()); + memberNameArray.add(regionMember); + break; + } + } + } + + regionJSON.put("memberNames", memberNameArray); + regionJSON.put("entryCount", reg.getSystemRegionEntryCount()); + + Boolean persistent = reg.getPersistentEnabled(); + if (persistent) { + regionJSON.put("persistence", VALUE_ON); + } else { + regionJSON.put("persistence", VALUE_OFF); + } + + Boolean isEnableOffHeapMemory = reg.isEnableOffHeapMemory(); + if (isEnableOffHeapMemory) { + regionJSON.put("isEnableOffHeapMemory", VALUE_ON); + } else { + regionJSON.put("isEnableOffHeapMemory", VALUE_OFF); + } + + String regCompCodec = reg.getCompressionCodec(); + if (StringUtils.isNotNullNotEmptyNotWhiteSpace(regCompCodec)) { + regionJSON.put("compressionCodec", reg.getCompressionCodec()); + } else { + regionJSON.put("compressionCodec", VALUE_NA); + } + + if (PulseConstants.PRODUCT_NAME_SQLFIRE.equalsIgnoreCase(PulseController + .getPulseProductSupport())) { + // Convert region path to dot separated region path + regionJSON.put("regionPath", + StringUtils.getTableNameFromRegionName(reg.getFullPath())); + } else { + regionJSON.put("regionPath", reg.getFullPath()); + } + + regionJSON.put("memoryReadsTrend", + mapper.valueToTree(reg.getRegionStatisticTrend(Cluster.Region.REGION_STAT_GETS_PER_SEC_TREND))); + regionJSON.put("memoryWritesTrend", + mapper.valueToTree(reg.getRegionStatisticTrend(Cluster.Region.REGION_STAT_PUTS_PER_SEC_TREND))); + regionJSON.put("diskReadsTrend", + mapper.valueToTree(reg.getRegionStatisticTrend(Cluster.Region.REGION_STAT_DISK_READS_PER_SEC_TREND))); + regionJSON.put("diskWritesTrend", + mapper.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, 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); + + regionListJson.add(regionJSON); + } + + return regionListJson; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9a2b5d7b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterRegionsService.java ---------------------------------------------------------------------- diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterRegionsService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterRegionsService.java new file mode 100644 index 0000000..0568451 --- /dev/null +++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterRegionsService.java @@ -0,0 +1,206 @@ +/* + * + * 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 com.vmware.geode.tools.pulse.internal.service; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.vmware.geode.tools.pulse.internal.controllers.PulseController; +import com.vmware.geode.tools.pulse.internal.data.Cluster; +import com.vmware.geode.tools.pulse.internal.data.PulseConstants; +import com.vmware.geode.tools.pulse.internal.data.Repository; +import com.vmware.geode.tools.pulse.internal.util.StringUtils; +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; +import java.util.Map; + +/** + * Class ClusterRegionsService + * + * This class contains implementations of getting Cluster's regions details + * + * @since GemFire version 7.5 + */ + +@Component +@Service("ClusterRegions") +@Scope("singleton") +public class ClusterRegionsService 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.Region> regionEntryCountComparator = (r1, r2) -> { + long r1Cnt = r1.getSystemRegionEntryCount(); + long r2Cnt = r2.getSystemRegionEntryCount(); + if (r1Cnt < r2Cnt) { + return -1; + } else if (r1Cnt > r2Cnt) { + return 1; + } else { + return 0; + } + }; + + public ObjectNode execute(final HttpServletRequest request) throws Exception { + // 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("regions", getRegionJson(cluster)); + + // Send json response + return responseJSON; + } + + /** + * This method is used to get various regions associated with the given + * cluster and create json for each region fields and returns Array List for + * all the regions associated with given cluster + * + * @param cluster + * @return JSONObject Array List + */ + private ArrayNode getRegionJson(Cluster cluster) { + + Long totalHeapSize = cluster.getTotalHeapSize(); + Long totalDiskUsage = cluster.getTotalBytesOnDisk(); + + Map<String, Cluster.Region> clusterRegions = cluster.getClusterRegions(); + + List<Cluster.Region> clusterRegionsList = new ArrayList<Cluster.Region>(); + clusterRegionsList.addAll(clusterRegions.values()); + + Collections.sort(clusterRegionsList, regionEntryCountComparator); + + ArrayNode regionListJson = mapper.createArrayNode(); + for (int count = 0; count < clusterRegionsList.size(); count++) { + Cluster.Region reg = clusterRegionsList.get(count); + ObjectNode regionJSON = mapper.createObjectNode(); + + regionJSON.put("name", reg.getName()); + 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()); + + Cluster.Member[] clusterMembersList = cluster.getMembers(); + + ArrayNode memberNameArray = mapper.createArrayNode(); + 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))) { + ObjectNode regionMember = mapper.createObjectNode(); + regionMember.put("id", member.getId()); + regionMember.put("name", member.getName()); + memberNameArray.add(regionMember); + break; + } + } + } + + regionJSON.put("memberNames", memberNameArray); + regionJSON.put("entryCount", reg.getSystemRegionEntryCount()); + + Boolean persistent = reg.getPersistentEnabled(); + if (persistent) { + regionJSON.put("persistence", this.VALUE_ON); + } else { + regionJSON.put("persistence", this.VALUE_OFF); + } + + Boolean isEnableOffHeapMemory = reg.isEnableOffHeapMemory(); + if (isEnableOffHeapMemory) { + regionJSON.put("isEnableOffHeapMemory", this.VALUE_ON); + } else { + regionJSON.put("isEnableOffHeapMemory", this.VALUE_OFF); + } + + String regCompCodec = reg.getCompressionCodec(); + if (StringUtils.isNotNullNotEmptyNotWhiteSpace(regCompCodec)) { + regionJSON.put("compressionCodec", reg.getCompressionCodec()); + } else { + regionJSON.put("compressionCodec", this.VALUE_NA); + } + + if (PulseConstants.PRODUCT_NAME_SQLFIRE.equalsIgnoreCase(PulseController.getPulseProductSupport())) { + // Convert region path to dot separated region path + regionJSON.put("regionPath", + StringUtils.getTableNameFromRegionName(reg.getFullPath())); + regionJSON.put("id", + StringUtils.getTableNameFromRegionName(reg.getFullPath())); + } else { + regionJSON.put("regionPath", reg.getFullPath()); + regionJSON.put("id", reg.getFullPath()); + } + + regionJSON.put("memoryReadsTrend", + mapper.valueToTree(reg.getRegionStatisticTrend(Cluster.Region.REGION_STAT_GETS_PER_SEC_TREND))); + regionJSON.put("memoryWritesTrend", + mapper.valueToTree(reg.getRegionStatisticTrend(Cluster.Region.REGION_STAT_PUTS_PER_SEC_TREND))); + regionJSON.put("diskReadsTrend", + mapper.valueToTree(reg.getRegionStatisticTrend(Cluster.Region.REGION_STAT_DISK_READS_PER_SEC_TREND))); + regionJSON.put("diskWritesTrend", + mapper.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, this.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); + + regionListJson.add(regionJSON); + } + + return regionListJson; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9a2b5d7b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterSelectedRegionService.java ---------------------------------------------------------------------- diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterSelectedRegionService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterSelectedRegionService.java new file mode 100644 index 0000000..4dfc941 --- /dev/null +++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterSelectedRegionService.java @@ -0,0 +1,237 @@ +/* + * + * 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 com.vmware.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 com.vmware.geode.tools.pulse.internal.controllers.PulseController; +import com.vmware.geode.tools.pulse.internal.data.Cluster; +import com.vmware.geode.tools.pulse.internal.data.PulseConstants; +import com.vmware.geode.tools.pulse.internal.data.Repository; +import com.vmware.geode.tools.pulse.internal.log.PulseLogWriter; +import com.vmware.geode.tools.pulse.internal.util.StringUtils; +import com.vmware.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()); + + if (PulseController.getPulseProductSupport().equalsIgnoreCase( + PulseConstants.PRODUCT_NAME_SQLFIRE)){ + regionMember.put("clients", member.getNumSqlfireClients()); + }else{ + 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); + } + + if (PulseConstants.PRODUCT_NAME_SQLFIRE.equalsIgnoreCase(PulseController.getPulseProductSupport())) { + // Convert region path to dot separated region path + regionJSON.put("regionPath", StringUtils.getTableNameFromRegionName(reg.getFullPath())); + } else { + 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; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9a2b5d7b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterSelectedRegionsMemberService.java ---------------------------------------------------------------------- diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterSelectedRegionsMemberService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterSelectedRegionsMemberService.java new file mode 100644 index 0000000..1f3ffd6 --- /dev/null +++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterSelectedRegionsMemberService.java @@ -0,0 +1,143 @@ +/* + * + * 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 com.vmware.geode.tools.pulse.internal.service; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.vmware.geode.tools.pulse.internal.data.Cluster; +import com.vmware.geode.tools.pulse.internal.data.Cluster.RegionOnMember; +import com.vmware.geode.tools.pulse.internal.data.Repository; +import com.vmware.geode.tools.pulse.internal.log.PulseLogWriter; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletRequest; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * Class ClusterSelectedRegionsMemberService + * + * This class contains implementations of getting Cluster's selected region's member specific details + * for all members in that region + * + * @since GemFire version 7.5 cedar 2014-03-01 + */ + +@Component +@Service("ClusterSelectedRegionsMember") +@Scope("singleton") +public class ClusterSelectedRegionsMemberService implements PulseService { + + private final ObjectMapper mapper = new ObjectMapper(); + + //Comparator based upon regions entry count + private static Comparator<Cluster.RegionOnMember> romEntryCountComparator = (m1, m2) -> { + long m1EntryCount = m1.getEntryCount(); + long m2EntryCount = m2.getEntryCount(); + if (m1EntryCount < m2EntryCount) { + return -1; + } else if (m1EntryCount > m2EntryCount) { + return 1; + } else { + return 0; + } + }; + + @Override + public ObjectNode execute(final HttpServletRequest request) throws Exception { + PulseLogWriter LOGGER = PulseLogWriter.getLogger(); + String userName = request.getUserPrincipal().getName(); + String pulseData = request.getParameter("pulseData"); + JsonNode parameterMap = mapper.readTree(pulseData); + String selectedRegionFullPath = parameterMap.get("ClusterSelectedRegionsMember").get("regionFullPath").textValue(); + LOGGER.finest("ClusterSelectedRegionsMemberService selectedRegionFullPath = " + selectedRegionFullPath); + + // 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("selectedRegionsMembers", getSelectedRegionsMembersJson(cluster, selectedRegionFullPath)); + // Send json response + return responseJSON; + } + + /** + * Create JSON for selected cluster region's all members + */ + private ObjectNode getSelectedRegionsMembersJson(Cluster cluster, String selectedRegionFullPath) { + PulseLogWriter LOGGER = PulseLogWriter.getLogger(); + Cluster.Region reg = cluster.getClusterRegion(selectedRegionFullPath); + + if (reg != null){ + ObjectNode regionMemberJSON = mapper.createObjectNode(); + RegionOnMember[] regionOnMembers = reg.getRegionOnMembers(); + + //sort on entry count + List<RegionOnMember> romList = Arrays.asList(regionOnMembers); + Collections.sort(romList, romEntryCountComparator); + + for(RegionOnMember rom : romList) { + ObjectNode memberJSON = mapper.createObjectNode(); + memberJSON.put("memberName", rom.getMemberName()); + memberJSON.put("regionFullPath", rom.getRegionFullPath()); + memberJSON.put("entryCount", rom.getEntryCount()); + memberJSON.put("entrySize", rom.getEntrySize()); + + memberJSON.put("accessor", ((rom.getLocalMaxMemory() == 0) ? "True" : "False")); + LOGGER.finest("calling getSelectedRegionsMembersJson :: rom.getLocalMaxMemory() = " + rom.getLocalMaxMemory()); + + memberJSON.put("memoryReadsTrend", + mapper.<JsonNode>valueToTree(rom.getRegionOnMemberStatisticTrend(RegionOnMember.REGION_ON_MEMBER_STAT_GETS_PER_SEC_TREND))); + LOGGER.finest("memoryReadsTrend = " + rom.getRegionOnMemberStatisticTrend(RegionOnMember.REGION_ON_MEMBER_STAT_GETS_PER_SEC_TREND).length); + + memberJSON.put("memoryWritesTrend", + mapper.<JsonNode>valueToTree(rom.getRegionOnMemberStatisticTrend(RegionOnMember.REGION_ON_MEMBER_STAT_PUTS_PER_SEC_TREND))); + LOGGER.finest("memoryWritesTrend = " + rom.getRegionOnMemberStatisticTrend(RegionOnMember.REGION_ON_MEMBER_STAT_PUTS_PER_SEC_TREND).length); + + memberJSON.put("diskReadsTrend", + mapper.<JsonNode>valueToTree(rom.getRegionOnMemberStatisticTrend(RegionOnMember.REGION_ON_MEMBER_STAT_DISK_READS_PER_SEC_TREND))); + LOGGER.finest("diskReadsTrend = " + rom.getRegionOnMemberStatisticTrend(RegionOnMember.REGION_ON_MEMBER_STAT_DISK_READS_PER_SEC_TREND).length); + + memberJSON.put("diskWritesTrend", + mapper.<JsonNode>valueToTree(rom.getRegionOnMemberStatisticTrend(RegionOnMember.REGION_ON_MEMBER_STAT_DISK_WRITES_PER_SEC_TREND))); + LOGGER.finest("diskWritesTrend = " + rom.getRegionOnMemberStatisticTrend(RegionOnMember.REGION_ON_MEMBER_STAT_DISK_WRITES_PER_SEC_TREND).length); + + regionMemberJSON.put(rom.getMemberName(), memberJSON); + } + + LOGGER.fine("calling getSelectedRegionsMembersJson :: regionJSON = " + regionMemberJSON); + return regionMemberJSON; + } else { + ObjectNode responseJSON = mapper.createObjectNode(); + responseJSON.put("errorOnRegion", "Region [" + selectedRegionFullPath + "] is not available"); + return responseJSON; + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9a2b5d7b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterWANInfoService.java ---------------------------------------------------------------------- diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterWANInfoService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterWANInfoService.java new file mode 100644 index 0000000..7e26724 --- /dev/null +++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterWANInfoService.java @@ -0,0 +1,75 @@ +/* + * + * 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 com.vmware.geode.tools.pulse.internal.service; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.vmware.geode.tools.pulse.internal.data.Cluster; +import com.vmware.geode.tools.pulse.internal.data.Repository; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletRequest; +import java.util.Map; + +/** + * Class ClusterWANInfoService + * + * This class contains implementations of getting Cluster's WAN Informations + * (connected clusters) + * + * @since GemFire version 7.5 + */ +@Component +@Service("ClusterWANInfo") +@Scope("singleton") +public class ClusterWANInfoService implements PulseService { + + private final ObjectMapper mapper = new ObjectMapper(); + + public ObjectNode execute(final HttpServletRequest request) throws Exception { + + // get cluster object + Cluster cluster = Repository.get().getCluster(); + + // json object to be sent as response + ObjectNode responseJSON = mapper.createObjectNode(); + + // members list + ArrayNode connectedClusterListJson = mapper.createArrayNode(); + + for (Map.Entry<String, Boolean> entry : cluster.getWanInformation() + .entrySet()) { + ObjectNode clusterJSON = mapper.createObjectNode(); + clusterJSON.put("clusterId", entry.getKey()); + clusterJSON.put("name", entry.getKey()); + clusterJSON.put("status", entry.getValue()); + + connectedClusterListJson.add(clusterJSON); + } + // Response JSON + responseJSON.put("connectedClusters", connectedClusterListJson); + // Send json response + return responseJSON; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9a2b5d7b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberAsynchEventQueuesService.java ---------------------------------------------------------------------- diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberAsynchEventQueuesService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberAsynchEventQueuesService.java new file mode 100644 index 0000000..5fe6785 --- /dev/null +++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberAsynchEventQueuesService.java @@ -0,0 +1,99 @@ +/* + * + * 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 com.vmware.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 com.vmware.geode.tools.pulse.internal.data.Cluster; +import com.vmware.geode.tools.pulse.internal.data.Repository; +import com.vmware.geode.tools.pulse.internal.util.StringUtils; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletRequest; + +/** + * Class MemberAsynchEventQueuesService + * + * This class contains implementations of getting Asynchronous Event Queues + * details of Cluster Member. + * + * @since GemFire version 7.5 + */ +@Component +@Service("MemberAsynchEventQueues") +@Scope("singleton") +public class MemberAsynchEventQueuesService implements PulseService { + + private final ObjectMapper mapper = new ObjectMapper(); + + public ObjectNode execute(final HttpServletRequest request) throws Exception { + + // get cluster object + Cluster cluster = Repository.get().getCluster(); + + // json object to be sent as response + ObjectNode responseJSON = mapper.createObjectNode(); + + JsonNode requestDataJSON = mapper.readTree(request.getParameter("pulseData")); + String memberName = requestDataJSON.get("MemberAsynchEventQueues").get("memberName").textValue(); + + Cluster.Member clusterMember = cluster.getMember(StringUtils.makeCompliantName(memberName)); + + if (clusterMember != null) { + // response + Cluster.AsyncEventQueue[] asyncEventQueues = clusterMember + .getMemberAsyncEventQueueList(); + ArrayNode asyncEventQueueJsonList = mapper.createArrayNode(); + + if (asyncEventQueues != null && asyncEventQueues.length > 0) { + responseJSON.put("isAsyncEventQueuesPresent", true); + + for (Cluster.AsyncEventQueue asyncEventQueue : asyncEventQueues) { + ObjectNode asyncEventQueueJSON = mapper.createObjectNode(); + asyncEventQueueJSON.put("id", asyncEventQueue.getId()); + asyncEventQueueJSON.put("primary", asyncEventQueue.getPrimary()); + asyncEventQueueJSON.put("senderType", asyncEventQueue.isParallel()); + asyncEventQueueJSON + .put("batchSize", asyncEventQueue.getBatchSize()); + asyncEventQueueJSON.put("batchTimeInterval", + asyncEventQueue.getBatchTimeInterval()); + asyncEventQueueJSON.put("batchConflationEnabled", + asyncEventQueue.isBatchConflationEnabled()); + asyncEventQueueJSON.put("asyncEventListener", + asyncEventQueue.getAsyncEventListener()); + asyncEventQueueJSON.put("queueSize", + asyncEventQueue.getEventQueueSize()); + + asyncEventQueueJsonList.add(asyncEventQueueJSON); + } + responseJSON.put("asyncEventQueues", asyncEventQueueJsonList); + } else { + responseJSON.put("isAsyncEventQueuesPresent", false); + } + + } + // Send json response + return responseJSON; + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9a2b5d7b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberClientsService.java ---------------------------------------------------------------------- diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberClientsService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberClientsService.java new file mode 100644 index 0000000..41f3684 --- /dev/null +++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberClientsService.java @@ -0,0 +1,101 @@ +/* + * + * 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 com.vmware.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 com.vmware.geode.tools.pulse.internal.data.Cluster; +import com.vmware.geode.tools.pulse.internal.data.Repository; +import com.vmware.geode.tools.pulse.internal.util.StringUtils; +import com.vmware.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; + +/** + * Class MemberClientsService + * + * This class contains implementations of getting Memeber's Clients. + * + * @since GemFire version 7.5 + */ +@Component +@Service("MemberClients") +@Scope("singleton") +public class MemberClientsService implements PulseService { + + private final ObjectMapper mapper = new ObjectMapper(); + + // String constants used for forming a json response + private final String NAME = "name"; + private final String HOST = "host"; + + public ObjectNode execute(final HttpServletRequest request) throws Exception { + + // get cluster object + Cluster cluster = Repository.get().getCluster(); + + // json object to be sent as response + ObjectNode responseJSON = mapper.createObjectNode(); + + JsonNode requestDataJSON = mapper.readTree(request.getParameter("pulseData")); + String memberName = requestDataJSON.get("MemberClients").get("memberName").textValue(); + + ArrayNode clientListJson = mapper.createArrayNode(); + + Cluster.Member clusterMember = cluster.getMember(StringUtils.makeCompliantName(memberName)); + if (clusterMember != null) { + responseJSON.put("memberId", clusterMember.getId()); + responseJSON.put(this.NAME, clusterMember.getName()); + responseJSON.put(this.HOST, clusterMember.getHost()); + + // member's clients + + Cluster.Client[] memberClients = clusterMember.getMemberClients(); + for (Cluster.Client memberClient : memberClients) { + ObjectNode regionJSON = mapper.createObjectNode(); + regionJSON.put("clientId", memberClient.getId()); + regionJSON.put(this.NAME, memberClient.getName()); + regionJSON.put(this.HOST, memberClient.getHost()); + regionJSON.put("queueSize", memberClient.getQueueSize()); + regionJSON.put("clientCQCount", memberClient.getClientCQCount()); + regionJSON.put("isConnected", memberClient.isConnected() ? "Yes" : "No"); + regionJSON.put("isSubscriptionEnabled", memberClient.isSubscriptionEnabled() ? "Yes" : "No"); + regionJSON.put("uptime", TimeUtils.convertTimeSecondsToHMS(memberClient.getUptime())); + + regionJSON.put("cpuUsage", String.format("%.4f", memberClient.getCpuUsage()).toString()); + // regionJSON.put("cpuUsage", memberClient.getCpuUsage()); + regionJSON.put("threads", memberClient.getThreads()); + regionJSON.put("gets", memberClient.getGets()); + regionJSON.put("puts", memberClient.getPuts()); + + clientListJson.add(regionJSON); + } + responseJSON.put("memberClients", clientListJson); + } + // Send json response + return responseJSON; + + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9a2b5d7b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberDetailsService.java ---------------------------------------------------------------------- diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberDetailsService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberDetailsService.java new file mode 100644 index 0000000..c4f2ff7 --- /dev/null +++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberDetailsService.java @@ -0,0 +1,122 @@ +/* + * + * 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 com.vmware.geode.tools.pulse.internal.service; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.vmware.geode.tools.pulse.internal.controllers.PulseController; +import com.vmware.geode.tools.pulse.internal.data.Cluster; +import com.vmware.geode.tools.pulse.internal.data.PulseConstants; +import com.vmware.geode.tools.pulse.internal.data.Repository; +import com.vmware.geode.tools.pulse.internal.util.StringUtils; +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; + +/** + * Class MemberDetailsService + * + * This class contains implementations of getting Memeber's Statistics. + * + * @since GemFire version 7.5 + */ +@Component +@Service("MemberDetails") +@Scope("singleton") +public class MemberDetailsService implements PulseService { + + private final ObjectMapper mapper = new ObjectMapper(); + + public ObjectNode execute(final HttpServletRequest request) throws Exception { + + String userName = request.getUserPrincipal().getName(); + + // get cluster object + Cluster cluster = Repository.get().getCluster(); + + // json object to be sent as response + ObjectNode responseJSON = mapper.createObjectNode(); + + JsonNode requestDataJSON = mapper.readTree(request.getParameter("pulseData")); + String memberName = requestDataJSON.get("MemberDetails").get("memberName").textValue(); + DecimalFormat df2 = new DecimalFormat(PulseConstants.DECIMAL_FORMAT_PATTERN); + + Cluster.Member clusterMember = cluster.getMember(StringUtils + .makeCompliantName(memberName)); + if (clusterMember != null) { + responseJSON.put("memberId", clusterMember.getId()); + responseJSON.put("name", clusterMember.getName()); + responseJSON.put("host", clusterMember.getHost()); + responseJSON.put("clusterId", cluster.getId()); + responseJSON.put("clusterName", cluster.getServerName()); + responseJSON.put("userName", userName); + double loadAvg = clusterMember.getLoadAverage(); + responseJSON.put("loadAverage", Double.valueOf(df2.format(loadAvg))); + responseJSON.put("sockets", clusterMember.getTotalFileDescriptorOpen()); + responseJSON.put("threads", clusterMember.getNumThreads()); + responseJSON.put("offHeapFreeSize", clusterMember.getOffHeapFreeSize()); + responseJSON.put("offHeapUsedSize", clusterMember.getOffHeapUsedSize()); + responseJSON.put("regionsCount", clusterMember.getMemberRegionsList().length); + + // Number of member clients + if (PulseController.getPulseProductSupport().equalsIgnoreCase( + PulseConstants.PRODUCT_NAME_SQLFIRE)){ + responseJSON.put("numClients", clusterMember.getNumSqlfireClients()); + } else { + responseJSON.put("numClients", clusterMember.getMemberClientsHMap().size()); + } + + Long diskUsageVal = clusterMember.getTotalDiskUsage(); + Double diskUsage = diskUsageVal.doubleValue() / 1024; + + responseJSON.put("diskStorageUsed", Double.valueOf(df2.format(diskUsage))); + + Cluster.Alert[] alertsList = cluster.getAlertsList(); + + String status = "Normal"; + + for (Cluster.Alert alert : alertsList) { + if (clusterMember.getName().equals(alert.getMemberName())) { + if (alert.getSeverity() == Cluster.Alert.SEVERE) { + status = "Severe"; + break; + } else if (alert.getSeverity() == Cluster.Alert.ERROR) { + status = "Error"; + } else if (alert.getSeverity() == Cluster.Alert.WARNING) { + status = "Warning"; + } + } + } + + responseJSON.put("status", status); + + } else { + responseJSON.put("errorOnMember", "Member [" + memberName + + "] is not available"); + } + + // Send json response + return responseJSON; + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9a2b5d7b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberDiskThroughputService.java ---------------------------------------------------------------------- diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberDiskThroughputService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberDiskThroughputService.java new file mode 100644 index 0000000..2dd8b55 --- /dev/null +++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberDiskThroughputService.java @@ -0,0 +1,76 @@ +/* + * + * 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 com.vmware.geode.tools.pulse.internal.service; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.vmware.geode.tools.pulse.internal.data.Cluster; +import com.vmware.geode.tools.pulse.internal.data.Repository; +import com.vmware.geode.tools.pulse.internal.util.StringUtils; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletRequest; + +/** + * Class MemberDiskThroughputService + * + * This class contains implementations for getting Memeber's current Disk + * Throughput trends over the time. + * + * @since GemFire version 7.5 + */ +@Component +@Service("MemberDiskThroughput") +@Scope("singleton") +public class MemberDiskThroughputService implements PulseService { + + private final ObjectMapper mapper = new ObjectMapper(); + + public ObjectNode execute(final HttpServletRequest request) throws Exception { + + // get cluster object + Cluster cluster = Repository.get().getCluster(); + + // json object to be sent as response + ObjectNode responseJSON = mapper.createObjectNode(); + + // members list + JsonNode requestDataJSON = mapper.readTree(request.getParameter("pulseData")); + String memberName = requestDataJSON.get("MemberDiskThroughput").get("memberName").textValue(); + + Cluster.Member clusterMember = cluster.getMember(StringUtils.makeCompliantName(memberName)); + + if (clusterMember != null) { + // response + responseJSON.put("throughputWrites", clusterMember.getThroughputWrites()); + responseJSON.put("throughputWritesTrend", + mapper.valueToTree(clusterMember.getMemberStatisticTrend(Cluster.Member.MEMBER_STAT_THROUGHPUT_WRITES))); + responseJSON.put("throughputReads", clusterMember.getThroughputWrites()); + responseJSON.put("throughputReadsTrend", + mapper.valueToTree(clusterMember.getMemberStatisticTrend(Cluster.Member.MEMBER_STAT_THROUGHPUT_READS))); + } + + // Send json response + return responseJSON; + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9a2b5d7b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberGCPausesService.java ---------------------------------------------------------------------- diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberGCPausesService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberGCPausesService.java new file mode 100644 index 0000000..5b34c73 --- /dev/null +++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberGCPausesService.java @@ -0,0 +1,73 @@ +/* + * + * 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 com.vmware.geode.tools.pulse.internal.service; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.vmware.geode.tools.pulse.internal.data.Cluster; +import com.vmware.geode.tools.pulse.internal.data.Repository; +import com.vmware.geode.tools.pulse.internal.util.StringUtils; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletRequest; + +/** + * Class MemberGCPausesService + * + * This class contains implementations of getting Memeber's GC Pauses (JVM + * Pauses) details and its trend over the time. + * + * @since GemFire version 7.5 + */ + +@Component +@Service("MemberGCPauses") +@Scope("singleton") +public class MemberGCPausesService implements PulseService { + + private final ObjectMapper mapper = new ObjectMapper(); + + public ObjectNode execute(final HttpServletRequest request) throws Exception { + + // get cluster object + Cluster cluster = Repository.get().getCluster(); + + // json object to be sent as response + ObjectNode responseJSON = mapper.createObjectNode(); + + // members list + JsonNode requestDataJSON = mapper.readTree(request.getParameter("pulseData")); + String memberName = requestDataJSON.get("MemberGCPauses").get("memberName").textValue(); + Cluster.Member clusterMember = cluster.getMember(StringUtils.makeCompliantName(memberName)); + + if (clusterMember != null) { + // response + responseJSON.put("gcPausesTrend", + mapper.valueToTree(clusterMember.getMemberStatisticTrend(Cluster.Member.MEMBER_STAT_GARBAGE_COLLECTION))); + responseJSON.put("gcPausesCount", clusterMember.getGarbageCollectionCount()); + } + + // Send json response + return responseJSON; + } +}
