package org.epics.archiverappliance.common;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.LinkedList;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.epics.archiverappliance.config.ApplianceInfo;
import org.epics.archiverappliance.config.ConfigService;
import org.epics.archiverappliance.config.ConfigService.WAR_FILE;
import org.epics.archiverappliance.config.DefaultConfigService;
import org.epics.archiverappliance.utils.ui.GetUrlContent;
import org.epics.archiverappliance.utils.ui.MimeTypeConstants;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
public class ProcessMetricsChartData implements BPLAction {
private static Logger logger = Logger.getLogger(ProcessMetricsChartData.class.getName());
@Override
public void execute(HttpServletRequest req, HttpServletResponse resp, ConfigService configService) throws IOException {
String identity = req.getParameter("appliance");
if(identity == null) {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
if(!identity.equals(configService.getMyApplianceInfo().getIdentity())) {
String url = configService.getAppliance(identity).getMgmtURL() + "/" + req.getPathInfo() + "?appliance=" + URLEncoder.encode(identity, "UTF-8");
logger.debug("Proxying " + url);
GetUrlContent.proxyURL(url, resp);
return;
}
configService.getAppliance(identity);
// We are casting to DefaultConfigService here as I do not want to expose processMetrics in the public interface just yet.
DefaultConfigService defaultConfigService = (DefaultConfigService) configService;
ProcessMetrics processMetrics = defaultConfigService.getProcessMetrics();
assert(configService.getWarFile() == WAR_FILE.MGMT);
HashMap<String, Object> myProcessMetricsJSON = processMetrics.getProcessMetricsJSON(configService.getWarFile().name() + "_");
ApplianceInfo myApplianceInfo = configService.getMyApplianceInfo();
// In this case we have combine the results from the various wars
logger.debug("Asking for process metrics from engine using " + myApplianceInfo.getEngineURL() + "/getProcessMetrics");
JSONObject engineMetricsJSON = GetUrlContent.getURLContentAsJSONObject(myApplianceInfo.getEngineURL() + "/getProcessMetrics");
logger.debug("Asking for process metrics from ETL using " + myApplianceInfo.getEtlURL() + "/getProcessMetrics");
JSONObject etlMetricsJSON = GetUrlContent.getURLContentAsJSONObject(myApplianceInfo.getEtlURL() + "/getProcessMetrics");
logger.debug("Asking for process metrics from retrieval using " + myApplianceInfo.getRetrievalURL() + "/getProcessMetrics");
JSONObject retrievalMetricsJSON = GetUrlContent.getURLContentAsJSONObject(myApplianceInfo.getRetrievalURL() + "/getProcessMetrics");
GetUrlContent.combineJSONObjectsWithArrays(myProcessMetricsJSON, engineMetricsJSON);
GetUrlContent.combineJSONObjectsWithArrays(myProcessMetricsJSON, etlMetricsJSON);
GetUrlContent.combineJSONObjectsWithArrays(myProcessMetricsJSON, retrievalMetricsJSON);
// In the mgmt webapp, we convert this into a jflot friendly json, something like so....
// [
// { label: "engine_heap", data: [ [22414837000, 25.16], [22414838000, 26.82] ] },
// { label: "system_load", data: [ [22414837000, 0.36], [22414838000, 0.13] ] }
// ]
try {
LinkedList<Object> finalData = new LinkedList<Object>();
addChartData(myProcessMetricsJSON, finalData, "ENGINE_metrics", "systemLoadAverage", "system_load (%)");
addChartData(myProcessMetricsJSON, finalData, "ENGINE_metrics", "heapUsedPercent", "engine_heap (%)");
addChartData(myProcessMetricsJSON, finalData, "ETL_metrics", "heapUsedPercent", "etl_heap (%)");
addChartData(myProcessMetricsJSON, finalData, "RETRIEVAL_metrics", "heapUsedPercent", "retrieval_heap (%)");
// addChartData(myProcessMetricsJSON, finalData, "MGMT_metrics", "heapUsedPercent", "mgmt_heap");
resp.setContentType(MimeTypeConstants.APPLICATION_JSON);
try (PrintWriter out = resp.getWriter()) {
JSONValue.writeJSONString(finalData, out);
}
} catch(Exception ex) {
logger.error(ex);
throw new IOException(ex);
}
}
private static void addChartData(HashMap<String, Object> myProcessMetricsJSON, LinkedList<Object> finalData, String keyInProcessMetrics, String yaxisdataelementName, String chartlabel) {
JSONArray processMetrics = (JSONArray) myProcessMetricsJSON.get(keyInProcessMetrics);
if(processMetrics != null && processMetrics.size() > 0) {
HashMap<String, Object> processMetric = new HashMap<String, Object>();
processMetric.put("label", chartlabel);
LinkedList<Object> data = new LinkedList<Object>();
for(int i = 0; i < processMetrics.size(); i++) {
@SuppressWarnings("unchecked")
HashMap<String, String> engineMetric = (HashMap<String, String>) processMetrics.get(i);
String timeInEpochSecondsStr = engineMetric.get("timeInEpochSeconds");
long epochMillisUTC = Long.parseLong(timeInEpochSecondsStr)*1000;
long epochMillisLocalTZ = TimeUtils.convertToLocalEpochMillis(epochMillisUTC);
String heapUsedPercentStr = engineMetric.get(yaxisdataelementName);
Double heapUsedPercent = Double.parseDouble(heapUsedPercentStr);
LinkedList<Number> dataElements = new LinkedList<Number>();
dataElements.add(epochMillisLocalTZ);
dataElements.add(heapUsedPercent);
data.add(dataElements);
}
processMetric.put("data", data);
finalData.add(processMetric);
}
}
}