/** * Copyright 2014 SAP AG * * 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.spotter.ext.detection.blob; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; import org.lpe.common.util.LpeNumericUtils; import org.spotter.shared.result.model.SpotterResult; /** * God Class data analyzer. * * @author Alexander Wert * */ public final class Analyzer { private static final int THREE_SIGMA = 3; private static final double _100_PERCENT = 100D; private static Analyzer analyzer; /** * Analyze the given ProcessedData and put the results in the specified * SpotterResult object. * * @param processData * Data to analyze * @param result * Object for storing the results */ public static void analyzeData(ProcessedData processData, SpotterResult result) { if (result == null) { throw new NullPointerException("SpotterResult must not be null."); } if (analyzer == null) { analyzer = new Analyzer(); } analyzer.analyze(processData, result); } private static final DecimalFormat df = new DecimalFormat("0.000"); private long highestReceiveCount = 0; private double mean; private double standardDeviation; /** * Hide default constructor. */ private Analyzer() { } /** * Analyze the given data. * * @param processData * processed Data * @param result * spotter result to add detection results to */ public void analyze(ProcessedData processData, SpotterResult result) { findHighestReceiveCount(processData); calculateMean(processData); calculateStandardDeviation(processData); // oldAnalysis(processData, result); newAnalysis(processData, result); } private void newAnalysis(ProcessedData processData, SpotterResult result) { for (Component outer : processData.getComponents()) { result.addMessage("Investigated component: " + outer.getId()); List<Double> pctMsgReceivedList = new ArrayList<Double>(); for (Component inner : processData.getComponents()) { if (inner == outer) { continue; } pctMsgReceivedList.add(getRelativeReceivePct(inner)); } double currentMean = LpeNumericUtils.average(pctMsgReceivedList); double standardDeviation = LpeNumericUtils.stdDev(pctMsgReceivedList); result.addMessage("Component Pct Messages Sent: " + df.format(getRelativeReceivePct(outer)) + "$"); result.addMessage("Current Mean: " + df.format(currentMean) + "$"); result.addMessage("Current StdDev: " + df.format(standardDeviation) + "%"); result.addMessage("Critical Threshold (Mean + 3 * SD): " + df.format(currentMean + THREE_SIGMA * standardDeviation) + "%"); if (currentMean + THREE_SIGMA * standardDeviation < getRelativeReceivePct(outer)) { result.addMessage("Result: As GodClass detected"); result.setDetected(true); } else { result.addMessage("Result: not detected"); } result.addMessage("* * * *"); } } /** * Find the highest message received count in the given data. * * @param data */ private void findHighestReceiveCount(ProcessedData data) { for (Component c : data.getComponents()) { if (c.getMessagesReceived() > highestReceiveCount) { highestReceiveCount = c.getMessagesReceived(); } } } /** * Calculate the mean value of the relative percentage receive count. * * @param data */ private void calculateMean(ProcessedData data) { for (Component c : data.getComponents()) { mean += getRelativeReceivePct(c); } mean /= data.getComponents().size(); } /** * Calculate the standard deviation value of the relative percentage receive * count. * * @param data */ private void calculateStandardDeviation(ProcessedData data) { for (Component c : data.getComponents()) { standardDeviation += Math.pow(getRelativeReceivePct(c) - mean, 2); } standardDeviation = Math.sqrt(standardDeviation / (data.getComponents().size() - 1)); } /** * Calculates relative to the component, which has received the most * messages, the percentage of messages that were received by the specified * component. */ private double getRelativeReceivePct(Component component) { return _100_PERCENT / highestReceiveCount * component.getMessagesReceived(); } }