/******************************************************************************* * Copyright 2014 Miami-Dade County * * Licensed 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.sharegov.cirm.stats; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import mjson.Json; /** * CirmClusterStatistics provides all data and history for each server and an aggregated cluster data history. * * @author Thomas Hilpold */ public class CirmClusterStatistics implements ICirmClusterStatistics { public final static String DEFAULT_CONFIG_JSON = "/CirmClusterStatistics.json"; private final List<CirmServerStatistics> allServerDataHistory = new ArrayList<>(); private final CirmServerStatistics clusterDataHistory = new CirmServerStatistics(CLUSTER_NAME); public CirmClusterStatistics() throws Exception { this(readConfig()); } /** * Configuration is an array of objects with properties: * serverName String a human consumable server name * serverStatsJsonUrl String the full url to retrieve the json from * jsonStatsArrayProperty String the property which holds the array (e.g. "stats-all") * * @param configuration */ public CirmClusterStatistics(Json configuration) { if (!configuration.isArray()) throw new IllegalArgumentException("Config must be array"); initialize(configuration); } final static synchronized Json readConfig() throws Exception { InputStream is = CirmClusterStatistics.class.getResource(DEFAULT_CONFIG_JSON).openStream(); BufferedReader bfr = new BufferedReader(new InputStreamReader(is)); StringBuffer json = new StringBuffer(1000); String line; while ((line = bfr.readLine()) != null) { json.append(line + "\r\n"); } bfr.close(); return Json.read(json.toString()); } final void initialize(Json configuration) { for (Json serverConfig : configuration.asJsonList()) { if (!serverConfig.has("serverName")) throw new IllegalArgumentException("no servername in " + serverConfig.toString()); if (!serverConfig.has("serverStatsJsonUrl")) throw new IllegalArgumentException("no serverStatsJsonUrl in " + serverConfig.toString()); if (!serverConfig.has("jsonStatsArrayProperty")) throw new IllegalArgumentException("no jsonStatsArrayProperty in " + serverConfig.toString()); String serverName = serverConfig.at("serverName").asString(); String serverStatsJsonUrlStr = serverConfig.at("serverStatsJsonUrl").asString(); String jsonStatsArrayProperty = serverConfig.at("jsonStatsArrayProperty").asString(); URL serverStatsJsonUrl; try { serverStatsJsonUrl = new URL(serverStatsJsonUrlStr); } catch (MalformedURLException ex) { throw new IllegalArgumentException("Invalid serverStatsJsonUrl " +ex + " in "+ serverStatsJsonUrlStr); } CirmServerStatistics dhp = new CirmServerStatistics(serverName, serverStatsJsonUrl, jsonStatsArrayProperty); allServerDataHistory.add(dhp); } } /** * Updates all server data histories and the cluster history with the exact same timestamp. */ @Override public void updateAll() { Date now = new Date(); for (CirmServerStatistics p : allServerDataHistory) { try { p.updateFromUrl(now); System.out.println("Update succeeded " + p.getServerName()); } catch (Exception e) { e.printStackTrace(); System.err.println("update failed at time " + now + " for server " + p.getServerName()); } } System.out.println("updateAll took " + (((System.currentTimeMillis() - now.getTime()) / 10) /100.0f) + " seconds"); updateCluster(now); } protected void updateCluster(Date now) { CirmStatistics clusterNowStats = new CirmStatistics(); for (CirmServerStatistics p : allServerDataHistory) { CirmStatistics pStats = p.getStatsAt(now); if (pStats != null) { for (Map.Entry<CirmStatistics.StatsKey, CirmStatistics.StatsValue> statsKeyValue : pStats.getStatistics().entrySet()) { CirmStatistics.StatsKey cur = statsKeyValue.getKey(); CirmStatistics.StatsValue clusterValue = clusterNowStats.getEntry(cur.getComponent(), cur.getAction(), cur.gettype()); clusterValue.aggregate(statsKeyValue.getValue()); } } else { System.err.println("ClusterStats updateCluster not accurate as no information for server " + p.getServerName() + " at " + now + " could be aggregated"); } } clusterDataHistory.update(now, clusterNowStats); } @Override public CirmStatistics getLastClusterStatistics() { if (clusterDataHistory.getLastUpdateTime() == null) { return null; } else { return clusterDataHistory.getStatsAt(clusterDataHistory.getLastUpdateTime()); } } @Override public List<DateStatsValuePair> getClusterHistoryForKey(CirmStatistics.StatsKey key) { return clusterDataHistory.getHistoryForKey(key); } @Override public int getNrOfServers() { return allServerDataHistory.size(); } @Override public CirmServerStatistics getDataHistoryByName(String serverOrClusterName) { CirmServerStatistics result = null; if (CirmClusterStatistics.CLUSTER_NAME.equals(serverOrClusterName)) { result = getClusterDataHistory(); } else { for (int i = 0; i < getNrOfServers() && result == null; i++) { CirmServerStatistics cur = getServerDataHistory(i); if (cur.getServerName().equals(serverOrClusterName)){ result = cur; } } } return result; } @Override public CirmServerStatistics getClusterDataHistory() { return clusterDataHistory; } @Override public CirmServerStatistics getServerDataHistory(int serverIndex) { return allServerDataHistory.get(serverIndex); } @Override public CirmStatistics getLastServerStatistics(int serverIndex) { CirmServerStatistics serverData = allServerDataHistory.get(serverIndex); if (serverData.getLastUpdateTime() == null) return null; return serverData.getStatsAt(serverData.getLastUpdateTime()); } @Override public List<DateStatsValuePair> getServerHistoryForKey(int serverIndex, CirmStatistics.StatsKey key) { CirmServerStatistics serverData = allServerDataHistory.get(serverIndex); return serverData.getHistoryForKey(key); } }