/* * * 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()); } } } } } } }