You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by hi...@apache.org on 2016/09/09 21:44:00 UTC
[63/83] [abbrv] incubator-geode git commit: GEODE-37 renamed pulse
package
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/eff7f216/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..40eef85
--- /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 org.apache.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 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.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/eff7f216/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..6972144
--- /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 org.apache.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 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;
+
+/**
+ * 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/eff7f216/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..bde7270
--- /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 org.apache.geode.tools.pulse.internal.service;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.apache.geode.tools.pulse.internal.data.Cluster;
+import org.apache.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/eff7f216/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..ab0aef3
--- /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 org.apache.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 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.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/eff7f216/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..d0f4c77
--- /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 org.apache.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 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.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/eff7f216/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..2dffa2c
--- /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 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());
+
+ 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/eff7f216/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..abf8e6f
--- /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 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.ObjectNode;
+import org.apache.geode.tools.pulse.internal.data.Cluster;
+import org.apache.geode.tools.pulse.internal.data.Cluster.RegionOnMember;
+import org.apache.geode.tools.pulse.internal.data.Repository;
+import org.apache.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/eff7f216/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..fd6793d
--- /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 org.apache.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 org.apache.geode.tools.pulse.internal.data.Cluster;
+import org.apache.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/eff7f216/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..5200704
--- /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 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.data.Cluster;
+import org.apache.geode.tools.pulse.internal.data.Repository;
+import org.apache.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/eff7f216/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..ddd2b76
--- /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 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.data.Cluster;
+import org.apache.geode.tools.pulse.internal.data.Repository;
+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;
+
+/**
+ * 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/eff7f216/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..79cc2ba
--- /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 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.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.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/eff7f216/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..9f1eba9
--- /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 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.ObjectNode;
+import org.apache.geode.tools.pulse.internal.data.Cluster;
+import org.apache.geode.tools.pulse.internal.data.Repository;
+import org.apache.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/eff7f216/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..b1fa07c
--- /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 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.ObjectNode;
+import org.apache.geode.tools.pulse.internal.data.Cluster;
+import org.apache.geode.tools.pulse.internal.data.Repository;
+import org.apache.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;
+ }
+}