diff options
| author | Shireesh Anjal <shireesh@gluster.com> | 2011-07-12 23:16:54 +0530 |
|---|---|---|
| committer | Shireesh Anjal <shireesh@gluster.com> | 2011-07-18 00:02:42 +0530 |
| commit | 4290f5519fb7480df6c5919583efc1f7feebf4b3 (patch) | |
| tree | 5930ba1eb58235ec12b897c300f7fd7bef9694d1 /src/com.gluster.storage.management.server | |
| parent | 194d5787da03f843a4eb81f304d6f30057bb5be2 (diff) | |
Story #38 - CPU Usage graph
Diffstat (limited to 'src/com.gluster.storage.management.server')
5 files changed, 315 insertions, 53 deletions
diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml b/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml index 7c20d6c7..405c4e40 100644 --- a/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml @@ -81,14 +81,14 @@ <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> - + <security-constraint> - <web-resource-collection> - <web-resource-name>Gluster Management Gateway</web-resource-name> - <url-pattern>/*</url-pattern> - </web-resource-collection> - <user-data-constraint> - <transport-guarantee>CONFIDENTIAL</transport-guarantee> - </user-data-constraint> -</security-constraint> + <web-resource-collection> + <web-resource-name>Gluster Management Gateway</web-resource-name> + <url-pattern>/*</url-pattern> + </web-resource-collection> + <user-data-constraint> + <transport-guarantee>CONFIDENTIAL</transport-guarantee> + </user-data-constraint> + </security-constraint> </web-app> diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GenericExceptionMapper.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GenericExceptionMapper.java new file mode 100644 index 00000000..4cd7f4f9 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GenericExceptionMapper.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + *******************************************************************************/ +package com.gluster.storage.management.server.resources.v1_0; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +import com.gluster.storage.management.core.exceptions.GlusterValidationException; + +@Provider +public class GenericExceptionMapper implements ExceptionMapper<Exception> { + + /* (non-Javadoc) + * @see javax.ws.rs.ext.ExceptionMapper#toResponse(java.lang.Throwable) + */ + @Override + public Response toResponse(Exception exception) { + ResponseBuilder builder; + if (exception instanceof GlusterValidationException) { + builder = Response.status(Response.Status.BAD_REQUEST); + } else { + builder = Response.status(Response.Status.INTERNAL_SERVER_ERROR); + } + return builder.entity(exception.getMessage()).type(MediaType.TEXT_PLAIN).build(); + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterServersResource.java index a5f366a2..09391841 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterServersResource.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterServersResource.java @@ -18,15 +18,21 @@ *******************************************************************************/ package com.gluster.storage.management.server.resources.v1_0; -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_SERVER_NAME; import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_FSTYPE; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_SERVER_NAME; import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_CLUSTER_NAME; import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_DISK_NAME; import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_SERVER_NAME; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_DETAILS; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_TYPE; import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_DISKS; import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_CLUSTERS; import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_SERVERS; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_STATISTICS; import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_TASKS; +import static com.gluster.storage.management.core.constants.RESTConstants.STATISTICS_TYPE_CPU; +import static com.gluster.storage.management.core.constants.RESTConstants.STATISTICS_TYPE_NETWORK; +import static com.gluster.storage.management.core.constants.RESTConstants.STATISTICS_TYPE_MEMORY; import java.util.ArrayList; import java.util.List; @@ -39,6 +45,7 @@ import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @@ -49,14 +56,15 @@ import com.gluster.storage.management.core.constants.CoreConstants; import com.gluster.storage.management.core.constants.RESTConstants; import com.gluster.storage.management.core.exceptions.ConnectionException; import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.ServerStats; import com.gluster.storage.management.core.model.GlusterServer; import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; import com.gluster.storage.management.core.response.GlusterServerListResponse; +import com.gluster.storage.management.core.response.ServerNameListResponse; import com.gluster.storage.management.server.data.ClusterInfo; import com.gluster.storage.management.server.data.ServerInfo; import com.gluster.storage.management.server.services.ClusterService; import com.gluster.storage.management.server.tasks.InitializeDiskTask; -import com.gluster.storage.management.server.utils.GlusterUtil; import com.gluster.storage.management.server.utils.SshUtil; import com.sun.jersey.api.core.InjectParam; import com.sun.jersey.spi.resource.Singleton; @@ -92,17 +100,44 @@ public class GlusterServersResource extends AbstractServersResource { @GET @Produces(MediaType.APPLICATION_JSON) - public Response getGlusterServersJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { - return getGlusterServers(clusterName, MediaType.APPLICATION_JSON); + public Response getGlusterServersJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @QueryParam(QUERY_PARAM_DETAILS) Boolean details) { + return getGlusterServers(clusterName, MediaType.APPLICATION_JSON, details); } @GET @Produces(MediaType.APPLICATION_XML) - public Response getGlusterServersXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { - return getGlusterServers(clusterName, MediaType.APPLICATION_XML); + public Response getGlusterServersXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @QueryParam(QUERY_PARAM_DETAILS) Boolean details) { + return getGlusterServers(clusterName, MediaType.APPLICATION_XML, details); } + + private List<GlusterServer> getGlusterServers(String clusterName, boolean fetchDetails) { + List<GlusterServer> glusterServers; + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); + } - public Response getGlusterServers(String clusterName, String mediaType) { + try { + glusterServers = getGlusterServers(clusterName, onlineServer, fetchDetails); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); + } + glusterServers = getGlusterServers(clusterName, onlineServer, fetchDetails); + } + return glusterServers; + } + + private Response getGlusterServers(String clusterName, String mediaType, Boolean fetchDetails) { + if(fetchDetails == null) { + // by default, fetch the server details + fetchDetails = true; + } + List<GlusterServer> glusterServers = new ArrayList<GlusterServer>(); if (clusterName == null || clusterName.isEmpty()) { @@ -118,37 +153,30 @@ public class GlusterServersResource extends AbstractServersResource { return okResponse(new GlusterServerListResponse(glusterServers), mediaType); } - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - try { - glusterServers = getGlusterServers(clusterName, onlineServer); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - try { - glusterServers = getGlusterServers(clusterName, onlineServer); - } catch (Exception e1) { - return errorResponse(e1.getMessage()); - } + glusterServers = getGlusterServers(clusterName, fetchDetails); } catch (Exception e) { return errorResponse(e.getMessage()); } - - String errMsg = fetchDetailsOfServers(glusterServers, onlineServer); - if (!errMsg.isEmpty()) { - return errorResponse("Couldn't fetch details for server(s): " + errMsg); + + if(fetchDetails) { + return okResponse(new GlusterServerListResponse(glusterServers), mediaType); + } else { + // no details to be fetched. Return list of server names. + return okResponse(new ServerNameListResponse(getServerNames(glusterServers)), mediaType); } + } + - return okResponse(new GlusterServerListResponse(glusterServers), mediaType); + private List<String> getServerNames(List<GlusterServer> glusterServers) { + List<String> serverNames = new ArrayList<String>(); + for(GlusterServer server : glusterServers) { + serverNames.add(server.getName()); + } + return serverNames; } - public String fetchDetailsOfServers(List<GlusterServer> glusterServers, GlusterServer onlineServer) { + private String fetchDetailsOfServers(List<GlusterServer> glusterServers, GlusterServer onlineServer) { String errMsg = ""; for (GlusterServer server : glusterServers) { @@ -161,7 +189,7 @@ public class GlusterServersResource extends AbstractServersResource { return errMsg; } - public List<GlusterServer> getGlusterServers(String clusterName, GlusterServer onlineServer) { + private List<GlusterServer> getGlusterServers(String clusterName, GlusterServer onlineServer, boolean fetchDetails) { List<GlusterServer> glusterServers; try { glusterServers = glusterUtil.getGlusterServers(onlineServer); @@ -174,11 +202,18 @@ public class GlusterServersResource extends AbstractServersResource { glusterServers = glusterUtil.getGlusterServers(onlineServer); } + + if (fetchDetails) { + String errMsg = fetchDetailsOfServers(glusterServers, onlineServer); + if (!errMsg.isEmpty()) { + throw new GlusterRuntimeException("Couldn't fetch details for server(s): " + errMsg); + } + } return glusterServers; } @GET - @Path("{serverName}") + @Path("{" + PATH_PARAM_SERVER_NAME + "}") @Produces(MediaType.APPLICATION_XML) public Response getGlusterServerXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @PathParam(PATH_PARAM_SERVER_NAME) String serverName) { @@ -186,7 +221,7 @@ public class GlusterServersResource extends AbstractServersResource { } @GET - @Path("{serverName}") + @Path("{" + PATH_PARAM_SERVER_NAME + "}") @Produces(MediaType.APPLICATION_JSON) public Response getGlusterServerJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @PathParam(PATH_PARAM_SERVER_NAME) String serverName) { @@ -428,20 +463,57 @@ public class GlusterServersResource extends AbstractServersResource { return errorResponse(e.getMessage()); } } + + @GET + @Produces(MediaType.APPLICATION_XML) + @Path(RESOURCE_STATISTICS) + public Response getAggregatedPerformanceDataXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @QueryParam(QUERY_PARAM_TYPE) String type) { + return getAggregaredPerformanceData(clusterName, type, MediaType.APPLICATION_XML); + } - private void setGlusterUtil(GlusterUtil glusterUtil) { - this.glusterUtil = glusterUtil; + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path(RESOURCE_STATISTICS) + public Response getAggregaredPerformanceDataJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @QueryParam(QUERY_PARAM_TYPE) String type) { + return getAggregaredPerformanceData(clusterName, type, MediaType.APPLICATION_JSON); } - public static void main(String[] args) { - GlusterServersResource glusterServersResource = new GlusterServersResource(); - GlusterUtil glusterUtil = new GlusterUtil(); - glusterUtil.setSshUtil(new SshUtil()); - glusterServersResource.setGlusterUtil(glusterUtil); - // System.out.println(glusterServersResource.getServerDetails("127.0.0.1").size()); + @GET + @Produces(MediaType.APPLICATION_XML) + @Path("{" + PATH_PARAM_SERVER_NAME + "}/" + RESOURCE_STATISTICS) + public Response getPerformanceDataXML(@PathParam(PATH_PARAM_SERVER_NAME) String serverName, @QueryParam(QUERY_PARAM_TYPE) String type) { + return getPerformanceData(serverName, type, MediaType.APPLICATION_XML); + } - // To add a server - // GlusterServerResponse response = glusterServersResource.addServer("my-server"); - // System.out.println(response.getData().getName()); + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("{" + PATH_PARAM_SERVER_NAME + "}/" + RESOURCE_STATISTICS) + public Response getPerformanceDataJSON(@PathParam(PATH_PARAM_SERVER_NAME) String serverName, @QueryParam(QUERY_PARAM_TYPE) String type) { + return getPerformanceData(serverName, type, MediaType.APPLICATION_JSON); + } + + private Response getAggregaredPerformanceData(String clusterName, String type, String mediaType) { + List<String> serverNames = getServerNames(getGlusterServers(clusterName, false)); + if(type.equals(STATISTICS_TYPE_CPU)) { + return okResponse(serverUtil.fetchAggregatedCPUStats(serverNames), mediaType); + } else { + return badRequestResponse("Server Statistics for [" + type + "] not supported! Valid values are [" + + STATISTICS_TYPE_CPU + ", " + STATISTICS_TYPE_NETWORK + ", " + STATISTICS_TYPE_MEMORY + "]"); + } + } + + private Response getPerformanceData(String serverName, String type, String mediaType) { + if(type.equals(STATISTICS_TYPE_CPU)) { + return okResponse(serverUtil.fetchCPUUsageData(serverName), mediaType); + } else if(type.equals(STATISTICS_TYPE_NETWORK)) { + return okResponse(serverUtil.fetchCPUUsageData(serverName), mediaType); + } else if(type.equals(STATISTICS_TYPE_MEMORY)) { + return okResponse(serverUtil.fetchCPUUsageData(serverName), mediaType); + } else { + return badRequestResponse("Server Statistics for [" + type + "] not supported! Valid values are [" + + STATISTICS_TYPE_CPU + ", " + STATISTICS_TYPE_NETWORK + ", " + STATISTICS_TYPE_MEMORY + "]"); + } } } diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ValidationExceptionMapper.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ValidationExceptionMapper.java new file mode 100644 index 00000000..cab6cc62 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ValidationExceptionMapper.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + *******************************************************************************/ +package com.gluster.storage.management.server.resources.v1_0; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +import com.gluster.storage.management.core.exceptions.GlusterValidationException; + +@Provider +public class ValidationExceptionMapper implements ExceptionMapper<GlusterValidationException> { + + /* (non-Javadoc) + * @see javax.ws.rs.ext.ExceptionMapper#toResponse(java.lang.Throwable) + */ + @Override + public Response toResponse(GlusterValidationException exception) { + return Response.status(Response.Status.BAD_REQUEST).entity(exception.getMessage()) + .type(MediaType.TEXT_PLAIN).build(); + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java index ae4bc919..55be59b4 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java @@ -22,6 +22,8 @@ package com.gluster.storage.management.server.utils; import java.io.ByteArrayInputStream; import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; import java.util.List; import javax.servlet.ServletContext; @@ -29,12 +31,15 @@ import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; +import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.gluster.storage.management.core.constants.CoreConstants; import com.gluster.storage.management.core.exceptions.ConnectionException; import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.ServerStatsRow; +import com.gluster.storage.management.core.model.ServerStats; import com.gluster.storage.management.core.model.Server; import com.gluster.storage.management.core.model.Status; import com.gluster.storage.management.core.response.GenericResponse; @@ -48,6 +53,8 @@ public class ServerUtil { @Autowired private SshUtil sshUtil; + + private static final Logger logger = Logger.getLogger(ServerUtil.class); private static final String SCRIPT_DIR = "scripts"; private static final String SCRIPT_COMMAND = "python"; @@ -216,4 +223,103 @@ public class ServerUtil { public Status getDiskForDir(String serverName, String brickDir) { return (Status) executeOnServer(true, serverName, REMOTE_SCRIPT_GET_DISK_FOR_DIR + " " + brickDir, Status.class); } + + public ServerStats fetchCPUUsageData(String serverName) { + String cpuUsageData = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> <xport> <meta> <start>1310468100</start> <step>300</step> <end>1310471700</end> <rows>13</rows> <columns>3</columns> <legend> <entry>user</entry> <entry>system</entry> <entry>total</entry> </legend> </meta> <data> <row><t>1310468100</t><v>NaN</v><v>4.3747778209e-01</v><v>6.6128073384e-01</v></row> <row><t>1310468400</t><v>2.3387347338e-01</v><v>4.4642717442e-01</v><v>6.8030064780e-01</v></row> <row><t>1310468700</t><v>5.5043873220e+00</v><v>6.2462376636e+00</v><v>1.1750624986e+01</v></row> <row><t>1310469000</t><v>2.4350593653e+01</v><v>2.6214585217e+01</v><v>5.0565178869e+01</v></row> <row><t>1310469300</t><v>4.0786489953e+01</v><v>4.6784713828e+01</v><v>8.7571203781e+01</v></row> <row><t>1310469600</t><v>4.1459955508e+01</v><v>5.2546309044e+01</v><v>9.4006264551e+01</v></row> <row><t>1310469900</t><v>4.2312286165e+01</v><v>5.2390588332e+01</v><v>9.4702874497e+01</v></row> <row><t>1310470200</t><v>4.2603794982e+01</v><v>5.1598861493e+01</v><v>9.4202656475e+01</v></row> <row><t>1310470500</t><v>3.8238751290e+01</v><v>4.5312089966e+01</v><v>8.3550841256e+01</v></row> <row><t>1310470800</t><v>1.7949961224e+01</v><v>2.1282058418e+01</v><v>3.9232019642e+01</v></row> <row><t>1310471100</t><v>1.2330371421e-01</v><v>4.6347832868e-01</v><v>5.8678204289e-01</v></row> <row><t>1310471400</t><v>1.6313260492e-01</v><v>5.4088119561e-01</v><v>7.0401380052e-01</v></row> <row><t>1310471700</t><v>NaN</v><v>NaN</v><v>NaN</v></row> </data> </xport>"; + Object output = unmarshal(ServerStats.class, cpuUsageData, false); + if(output instanceof Status) { + throw new GlusterRuntimeException(((Status)output).toString()); + } + return (ServerStats) output; + } + + private ServerStats getFirstOnlineServerCPUStats(List<String> serverNames, boolean removeServerOnError, boolean removeOnlineServer) { + for(String serverName : serverNames) { + try { + ServerStats stats = fetchCPUUsageData(serverName); + if(removeOnlineServer) { + serverNames.remove(serverName); + } + } catch(Exception e) { + // server might be offline - continue with next one + logger.warn("Couldn't fetch CPU stats from server [" + serverName + "]!", e); + if(removeServerOnError) { + serverNames.remove(serverName); + } + continue; + } + } + throw new GlusterRuntimeException("All servers offline!"); + } + + public Object fetchAggregatedCPUStats(List<String> serverNames) { + if(serverNames == null || serverNames.size() == 0) { + throw new GlusterRuntimeException("No server names passed to fetchAggregaredCPUUsageData!"); + } + + ServerStats firstServerStats = getFirstOnlineServerCPUStats(serverNames, true, true); + + ServerStats aggregatedStats = new ServerStats(firstServerStats); + aggregateCPUStats(serverNames, aggregatedStats); + return aggregatedStats; + } + + private void aggregateCPUStats(List<String> serverNames, ServerStats aggregatedStats) { + int[][] dataCount = new int[aggregatedStats.getMetadata().getRowCount()][aggregatedStats.getMetadata() + .getLegend().size()]; + + for (String serverName : serverNames) { + ServerStats serverStats; + try { + serverStats = fetchCPUUsageData(serverName); + } catch(Exception e) { + // server might be offline - continue with next one + logger.warn("Couldn't fetch CPU stats from server [" + serverName + "]!", e); + continue; + } + List<ServerStatsRow> serverStatsRows = addServerStats(serverStats, aggregatedStats, dataCount); + } + + List<ServerStatsRow> rows = aggregatedStats.getRows(); + for(int rowNum = 0; rowNum < rows.size(); rowNum++) { + List<Double> data = rows.get(rowNum).getUsageData(); + for(int columnNum = 0; columnNum < data.size(); columnNum++) { + data.set(columnNum, data.get(columnNum) / dataCount[rowNum][columnNum]); + } + } + } + + /** + * + * @param statsToBeAdded + * @param targetStats + * @param dataCount Each element of this matrix will be incremented for every valid element added + * @return + */ + private List<ServerStatsRow> addServerStats(ServerStats statsToBeAdded, ServerStats targetStats, int[][] dataCount) { + List<ServerStatsRow> serverStatsRows = statsToBeAdded.getRows(); + for (int rowNum = 0; rowNum < serverStatsRows.size() + && rowNum < targetStats.getMetadata().getRowCount(); rowNum++) { + ServerStatsRow row = serverStatsRows.get(rowNum); + List<Double> rowData = row.getUsageData(); + + List<Double> aggregatedStatsRowData = targetStats.getRows().get(rowNum).getUsageData(); + for(int i = 1; i < targetStats.getMetadata().getLegend().size(); i++) { + // Add the data + Double data = rowData.get(i); + if(!data.isNaN()) { + // data is available. add it. + aggregatedStatsRowData.set(i, aggregatedStatsRowData.get(i) + data); + // increment record count. this will be used for calculating average of aggregated data. + dataCount[rowNum][i]++; + } + } + } + return serverStatsRows; + } + + public static void main(String[] args) { + ServerStats stats = new ServerUtil().fetchCPUUsageData("s1"); + System.out.println(stats.getMetadata().getLegend()); + } } |
