package org.spotter.ext.detection.trafficJam.strategies; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Properties; import org.aim.api.measurement.dataset.Dataset; import org.aim.api.measurement.dataset.ParameterSelection; import org.aim.artifacts.records.ResponseTimeRecord; import org.lpe.common.util.LpeNumericUtils; import org.lpe.common.util.NumericPairList; import org.spotter.core.chartbuilder.AnalysisChartBuilder; import org.spotter.core.detection.AbstractDetectionController; import org.spotter.ext.detection.trafficJam.ITrafficJamStrategy; import org.spotter.ext.detection.trafficJam.TrafficJamDetectionController; import org.spotter.ext.detection.trafficJam.TrafficJamExtension; import org.spotter.shared.result.model.SpotterResult; public class TTestStrategy implements ITrafficJamStrategy { private int requiredSignificantSteps; private double requiredSignificanceLevel; private TrafficJamDetectionController mainDetectionController; @Override public boolean analyseOperationResponseTimes(Dataset dataset, String operation, SpotterResult result) { try { int prevNumUsers = -1; int firstSignificantNumUsers = -1; int significantSteps = 0; List<Integer> sortedNumUsersList = new ArrayList<Integer>(dataset.getValueSet( AbstractDetectionController.NUMBER_OF_USERS_KEY, Integer.class)); Collections.sort(sortedNumUsersList); int minNumUsers = sortedNumUsersList.get(0); NumericPairList<Integer, Double> rawData = new NumericPairList<>(); NumericPairList<Integer, Double> means = new NumericPairList<>(); List<Number> ci = new ArrayList<>(); for (Integer numUsers : sortedNumUsersList) { if (prevNumUsers > 0) { ParameterSelection selectionCurrent = new ParameterSelection().select( AbstractDetectionController.NUMBER_OF_USERS_KEY, numUsers).select( ResponseTimeRecord.PAR_OPERATION, operation); ParameterSelection selectionPrev = new ParameterSelection().select( AbstractDetectionController.NUMBER_OF_USERS_KEY, prevNumUsers).select( ResponseTimeRecord.PAR_OPERATION, operation); List<Long> currentValues = LpeNumericUtils.filterOutliersUsingIQR(selectionCurrent.applyTo(dataset) .getValues(ResponseTimeRecord.PAR_RESPONSE_TIME, Long.class)); List<Long> prevValues = LpeNumericUtils.filterOutliersUsingIQR(selectionPrev.applyTo(dataset) .getValues(ResponseTimeRecord.PAR_RESPONSE_TIME, Long.class)); List<Double> sums1 = new ArrayList<>(); List<Double> sums2 = new ArrayList<>(); LpeNumericUtils.createNormalDistributionByBootstrapping(prevValues, currentValues, sums1, sums2); if (sums2.size() < 2 || sums1.size() < 2) { throw new IllegalArgumentException("Traffic Jam detection failed for the operation '" + operation + "', because there are not enough measurement points for a t-test."); } double prevMean = LpeNumericUtils.average(sums1); double currentMean = LpeNumericUtils.average(sums2); double pValue = LpeNumericUtils.tTest(sums2, sums1); if (pValue >= 0 && pValue <= requiredSignificanceLevel && prevMean < currentMean) { if (firstSignificantNumUsers < 0) { firstSignificantNumUsers = prevNumUsers; } significantSteps++; } else { firstSignificantNumUsers = -1; significantSteps = 0; } // update chart data if (prevNumUsers == minNumUsers) { double stdDev = LpeNumericUtils.stdDev(sums1); for (Double val : sums1) { rawData.add(prevNumUsers, val); } double ciWidth = LpeNumericUtils.getConfidenceIntervalWidth(sums1.size(), stdDev, requiredSignificanceLevel); means.add(prevNumUsers, prevMean); ci.add(ciWidth / 2.0); } double stdDev = LpeNumericUtils.stdDev(sums2); for (Double val : sums2) { rawData.add(numUsers, val); } double ciWidth = LpeNumericUtils.getConfidenceIntervalWidth(sums2.size(), stdDev, requiredSignificanceLevel); means.add(numUsers, currentMean); ci.add(ciWidth / 2.0); } prevNumUsers = numUsers; } AnalysisChartBuilder chartBuilder = AnalysisChartBuilder.getChartBuilder(); String operationName = operation.contains("(")?operation.substring(0, operation.indexOf("(")):operation; chartBuilder.startChart(operationName, "number of users", "response time [ms]"); chartBuilder.addScatterSeries(rawData, "response times"); mainDetectionController.getResultManager().storeImageChartResource(chartBuilder, "Response Times", result); chartBuilder = AnalysisChartBuilder.getChartBuilder(); chartBuilder.startChart(operationName, "number of users", "response time [ms]"); chartBuilder.addScatterSeriesWithErrorBars(means, ci, "avg. response times"); mainDetectionController.getResultManager().storeImageChartResource(chartBuilder, "Confidence Intervals", result); if (firstSignificantNumUsers > 0 && significantSteps >= requiredSignificantSteps) { return true; } return false; } catch (Exception e) { return false; } } @Override public void setProblemDetectionConfiguration(Properties problemDetectionConfiguration) { String requiredSignificantStepsStr = problemDetectionConfiguration .getProperty(TrafficJamExtension.REQUIRED_SIGNIFICANT_STEPS_KEY); requiredSignificantSteps = requiredSignificantStepsStr != null ? Integer.parseInt(requiredSignificantStepsStr) : TrafficJamExtension.REQUIRED_SIGNIFICANT_STEPS_DEFAULT; String requiredConfidenceLevelStr = problemDetectionConfiguration .getProperty(TrafficJamExtension.REQUIRED_CONFIDENCE_LEVEL_KEY); requiredSignificanceLevel = 1.0 - (requiredConfidenceLevelStr != null ? Double .parseDouble(requiredConfidenceLevelStr) : TrafficJamExtension.REQUIRED_CONFIDENCE_LEVEL_DEFAULT); } @Override public void setMainDetectionController(TrafficJamDetectionController mainDetectionController) { this.mainDetectionController = mainDetectionController; } }