package org.spotter.ext.detection.appHiccups.strategies; import java.util.ArrayList; import java.util.List; import org.lpe.common.util.NumericPairList; import org.spotter.core.detection.DetectionResultManager; import org.spotter.ext.detection.appHiccups.IHiccupAnalysisStrategy; import org.spotter.ext.detection.appHiccups.utils.Hiccup; import org.spotter.ext.detection.appHiccups.utils.HiccupDetectionConfig; import org.spotter.ext.detection.utils.Utils; import org.spotter.shared.result.model.SpotterResult; /** * Bucket strategy devides the experiment time in fixed-sizes buckets and * analyzes each bucket whether it conforms to the performance requirements, in * order to identify hiccups. * * @author Alexander Wert * */ public class BucketStrategy implements IHiccupAnalysisStrategy { @Override public List<Hiccup> findHiccups(NumericPairList<Long, Double> responsetimeSeries, HiccupDetectionConfig hiccupConfig, double perfReqThreshold, double perfReqConfidence, DetectionResultManager resultManager, SpotterResult result) { List<Hiccup> hiccups = new ArrayList<Hiccup>(); Hiccup currentHiccup = null; double maxRT = Double.MIN_VALUE; long bucketStart = Long.MIN_VALUE; long timestamp; long bucketStep = Math.max(5000, Utils.meanInterRequestTime(responsetimeSeries) * 50); NumericPairList<Long, Double> bucketSeries = null; for (int i = 0; i < responsetimeSeries.size(); i++) { timestamp = responsetimeSeries.get(i).getKey(); if (timestamp > bucketStart + bucketStep) { // new bucket started if (bucketSeries != null) { // analyze previous bucket List<Double> responseTimes = bucketSeries.getValueListAsDouble(); int reqViolationsCount = countRequirementViolations(perfReqThreshold, responseTimes); double percentageViolations = ((double) reqViolationsCount) / ((double) responseTimes.size()); if (percentageViolations > perfReqConfidence) { // new hiccup started maxRT = Math.max(maxRT, bucketSeries.getValueMax()); if (currentHiccup == null) { // new hiccup begin detected currentHiccup = new Hiccup(); currentHiccup.setStartTimestamp(bucketSeries.getKeyMin()); hiccups.add(currentHiccup); } currentHiccup.setEndTimestamp(bucketSeries.getKeyMax()); } else { if (currentHiccup != null) { currentHiccup.setMaxHiccupResponseTime(maxRT); currentHiccup = null; } maxRT = Double.MIN_VALUE; } } bucketSeries = new NumericPairList<>(); bucketStart = timestamp; } bucketSeries.add(responsetimeSeries.get(i)); } if (bucketSeries != null && bucketSeries.size() > 0) { // analyze previous bucket List<Double> responseTimes = bucketSeries.getValueListAsDouble(); int reqViolationsCount = countRequirementViolations(perfReqThreshold, responseTimes); double percentageViolations = ((double) reqViolationsCount) / ((double) responseTimes.size()); if (percentageViolations > perfReqConfidence) { // new hiccup started maxRT = Math.max(maxRT, bucketSeries.getValueMax()); if (currentHiccup == null) { // new hiccup begin detected currentHiccup = new Hiccup(); currentHiccup.setStartTimestamp(bucketSeries.getKeyMin()); hiccups.add(currentHiccup); } currentHiccup.setEndTimestamp(bucketSeries.getKeyMax()); } if (currentHiccup != null) { currentHiccup.setMaxHiccupResponseTime(maxRT); } } return hiccups; } private int countRequirementViolations(double perfReqThreshold, List<Double> responseTimes) { int count = 0; for (Double rt : responseTimes) { if (rt > perfReqThreshold) { count++; } } return count; } }