/*******************************************************************************
* Copyright (c) 2011 The Board of Trustees of the Leland Stanford Junior University
* as Operator of the SLAC National Accelerator Laboratory.
* Copyright (c) 2011 Brookhaven National Laboratory.
* EPICS archiver appliance is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*******************************************************************************/
package org.epics.archiverappliance.etl.bpl.reports;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DecimalFormat;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.epics.archiverappliance.common.BPLAction;
import org.epics.archiverappliance.common.TimeUtils;
import org.epics.archiverappliance.config.ConfigService;
import org.epics.archiverappliance.etl.common.ETLMetricsForLifetime;
import org.json.simple.JSONValue;
/**
* Get the metrics details for an appliance for ETL.
* @author mshankar
*
*/
public class ApplianceMetricsDetails implements BPLAction {
@Override
public void execute(HttpServletRequest req, HttpServletResponse resp, ConfigService configService) throws IOException {
try (PrintWriter out = resp.getWriter()) {
out.println(getETLMetricsDetails(configService));
}
}
public static String getETLMetricsDetails(ConfigService configService) {
DecimalFormat twoSignificantDigits = new DecimalFormat("###,###,###,###,###,###.##");
LinkedList<Map<String, String>> details = new LinkedList<Map<String, String>>();
List<ETLMetricsForLifetime> metricsForLifetime = configService.getETLLookup().getApplianceMetrics();
if(metricsForLifetime == null || metricsForLifetime.size() < 1) {
addDetailedStatus(details, "Startup", "In Progress");
} else {
for(ETLMetricsForLifetime metricForLifetime : metricsForLifetime) {
String lifetimeIdentifier = metricForLifetime.getLifeTimeId() + "»" + (metricForLifetime.getLifeTimeId()+1);
long totalRunsNum = metricForLifetime.getTotalETLRuns();
if(totalRunsNum != 0){
long timeForOverallETLInMillis=metricForLifetime.getTimeForOverallETLInMilliSeconds();
addDetailedStatus(details, "Total number of ETL("+lifetimeIdentifier+") runs so far", Long.toString(totalRunsNum));
double avgETLTimeInSeconds = ((double)timeForOverallETLInMillis)/(totalRunsNum*1000.0);
addDetailedStatus(details, "Average time spent in ETL("+lifetimeIdentifier+") (s/run)", twoSignificantDigits.format(avgETLTimeInSeconds));
double timeSpentInETLPercent = (avgETLTimeInSeconds*100)/(TimeUtils.getCurrentEpochSeconds() - metricForLifetime.getStartOfMetricsMeasurementInEpochSeconds());
addDetailedStatus(details, "Average percentage of time spent in ETL("+lifetimeIdentifier+")", twoSignificantDigits.format(timeSpentInETLPercent));
addDetailedStatus(details, "Approximate time taken by last job in ETL("+lifetimeIdentifier+") (s)", twoSignificantDigits.format(metricForLifetime.getApproximateLastGlobalETLTimeInMillis()/1000));
addDetailedStatus(details, "Estimated weekly usage in ETL("+lifetimeIdentifier+") (%)", twoSignificantDigits.format(metricForLifetime.getWeeklyETLUsageInPercent()));
addDetailedStatus(details, "Avg time spent by getETLStreams() in ETL("+lifetimeIdentifier+") (s/run)", twoSignificantDigits.format(((double)metricForLifetime.getTimeinMillSecond4getETLStreams())/(1000.0*totalRunsNum)));
addDetailedStatus(details, "Avg time spent by free space checks in ETL("+lifetimeIdentifier+") (s/run)", twoSignificantDigits.format(((double)metricForLifetime.getTimeinMillSecond4checkSizes())/(1000.0*totalRunsNum)));
addDetailedStatus(details, "Avg time spent by prepareForNewPartition() in ETL("+lifetimeIdentifier+") (s/run)", twoSignificantDigits.format(((double)metricForLifetime.getTimeinMillSecond4prepareForNewPartition())/(1000.0*totalRunsNum)));
addDetailedStatus(details, "Avg time spent by appendToETLAppendData() in ETL("+lifetimeIdentifier+") (s/run)", twoSignificantDigits.format(((double)metricForLifetime.getTimeinMillSecond4appendToETLAppendData())/(1000.0*totalRunsNum)));
addDetailedStatus(details, "Avg time spent by commitETLAppendData() in ETL("+lifetimeIdentifier+") (s/run)", twoSignificantDigits.format(((double)metricForLifetime.getTimeinMillSecond4commitETLAppendData())/(1000.0*totalRunsNum)));
addDetailedStatus(details, "Avg time spent by markForDeletion() in ETL("+lifetimeIdentifier+") (s/run)", twoSignificantDigits.format(((double)metricForLifetime.getTimeinMillSecond4markForDeletion())/(1000.0*totalRunsNum)));
addDetailedStatus(details, "Avg time spent by runPostProcessors() in ETL("+lifetimeIdentifier+") (s/run)", twoSignificantDigits.format(((double)metricForLifetime.getTimeinMillSecond4runPostProcessors())/(1000.0*totalRunsNum)));
addDetailedStatus(details, "Avg time spent by executePostETLTasks() in ETL("+lifetimeIdentifier+") (s/run)", twoSignificantDigits.format(((double)metricForLifetime.getTimeinMillSecond4executePostETLTasks())/(1000.0*totalRunsNum)));
String bytesTransferedUnits = "";
long bytesTransferred = metricForLifetime.getTotalSrcBytes();
double bytesTransferredInUnits = bytesTransferred;
if(bytesTransferred > 1024*10 && bytesTransferred <= 1024*1024) {
bytesTransferredInUnits = bytesTransferred/1024.0;
bytesTransferedUnits = "(KB)";
} else if (bytesTransferred > 1024*1024 && bytesTransferred <= 1024*1024*1024) {
bytesTransferredInUnits = bytesTransferred/(1024.0*1024.0);
bytesTransferedUnits = "(MB)";
} else if (bytesTransferred > 1024*1024*1024) {
bytesTransferredInUnits = bytesTransferred/(1024.0*1024.0*1024.0);
bytesTransferedUnits = "(GB)";
}
addDetailedStatus(details, "Estimated bytes transferred in ETL ("+lifetimeIdentifier+")"+bytesTransferedUnits, twoSignificantDigits.format(bytesTransferredInUnits));
}
}
}
return JSONValue.toJSONString(details);
}
private static void addDetailedStatus(LinkedList<Map<String, String>> statuses, String name, String value) {
Map<String, String> obj = new LinkedHashMap<String, String>();
obj.put("name", name);
obj.put("value", value);
obj.put("source", "etl");
statuses.add(obj);
}
}