diff --git a/slo-violation-detector/src/main/java/configuration/Constants.java b/slo-violation-detector/src/main/java/configuration/Constants.java index 53bff12..3e06d61 100644 --- a/slo-violation-detector/src/main/java/configuration/Constants.java +++ b/slo-violation-detector/src/main/java/configuration/Constants.java @@ -17,27 +17,20 @@ public class Constants { public static String EMPTY = ""; public static String SPACE = " "; public static Double LOWER_LIMIT_DELTA = - 100.0; - public static Double UPPER_LIMIT_DELTA = - 100.0; - //Operational constants - public static boolean USE_CONFIGURATION_FILE_FOR_METRIC_VALUES_INPUT = false; - public static boolean USE_CONFIGURATION_FILE_FOR_METRIC_TOPICS_INPUT = false; - public static int elements_considered_in_prediction = 10; public static String slo_violation_determination_method; public static int time_horizon_seconds; public static int maximum_acceptable_forward_predictions; - - public static double confidence_interval; - public static double prediction_certainty; - public static String [] logic_operators = {"and","or"}; + public static final String default_handled_application_name = "default_application"; public static URI base_project_path; public static String configuration_file_location = "src/main/resources/config/input_data.properties"; public static String amq_library_configuration_location = "src/main/resources/config/eu.melodic.event.brokerclient.properties"; public static String topic_for_severity_announcement = "prediction.slo_severity_value"; public static String topic_for_lost_device_announcement = "eu.nebulouscloud.device_lost"; - public static String slo_rules_topic = "metrics.metric_list"; + public static String slo_rules_topic = "eu.nebulouscloud.monitoring.slo.new"; + public static String metric_list_topic = "eu.nebulouscloud.monitoring.metric_list"; public static double slo_violation_probability_threshold = 0.5; //The threshold over which the probability of a predicted slo violation should be to have a violation detection public static int kept_values_per_metric = 5; //Default to be overriden from the configuration file. This indicates how many metric values are kept to calculate the "previous" metric value during the rate of change calculation public static String roc_calculation_mode = "prototype"; diff --git a/slo-violation-detector/src/main/java/runtime/DetectorRequestMappings.java b/slo-violation-detector/src/main/java/runtime/DetectorRequestMappings.java index 9da9fe9..367bded 100644 --- a/slo-violation-detector/src/main/java/runtime/DetectorRequestMappings.java +++ b/slo-violation-detector/src/main/java/runtime/DetectorRequestMappings.java @@ -5,19 +5,18 @@ import slo_violation_detector_engine.DetectorSubcomponent; import java.io.IOException; -import static configuration.Constants.EMPTY; +import static configuration.Constants.default_handled_application_name; import static runtime.Main.detectors; import static slo_violation_detector_engine.DetectorSubcomponent.detector_integer_id; import static utilities.DebugDataSubscription.debug_data_generation; -import static utilities.DebugDataSubscription.debug_data_output_topic_name; import static utility_beans.CharacterizedThread.CharacterizedThreadRunMode.detached; @RestController @RequestMapping("/api") public class DetectorRequestMappings { @RequestMapping("/add-new-detector") - public static String start_new_detector_subcomponent() throws IOException { - detectors.add(new DetectorSubcomponent(detached)); + public static String start_new_detector_subcomponent() { + detectors.add(new DetectorSubcomponent(default_handled_application_name,detached)); return ("Spawned new SLO Detector subcomponent instance! Currently, there have been "+detector_integer_id+" detectors spawned"); } diff --git a/slo-violation-detector/src/main/java/runtime/DirectorRequestMappings.java b/slo-violation-detector/src/main/java/runtime/DirectorRequestMappings.java index 03ce305..d23a23f 100644 --- a/slo-violation-detector/src/main/java/runtime/DirectorRequestMappings.java +++ b/slo-violation-detector/src/main/java/runtime/DirectorRequestMappings.java @@ -1,23 +1,79 @@ package runtime; import configuration.Constants; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import slo_violation_detector_engine.DetectorSubcomponent; import utility_beans.CharacterizedThread; +import utility_beans.RealtimeMonitoringAttribute; +import java.util.HashMap; + +import static configuration.Constants.default_handled_application_name; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; @RestController @RequestMapping("/api") public class DirectorRequestMappings { - @PostMapping(value = "/new-application", + @PostMapping(value = "/new-application-slo", consumes = APPLICATION_JSON_VALUE) public static String start_new_detector_subcomponent(@RequestBody String string_rule_representation){ - DetectorSubcomponent new_detector = new DetectorSubcomponent(CharacterizedThread.CharacterizedThreadRunMode.detached); + JSONObject rule_representation_json; + JSONParser json_parser = new JSONParser(); + String application_name; + try { + rule_representation_json = (JSONObject) json_parser.parse(string_rule_representation); + } catch (ParseException e) { + return "Error in parsing the input string, the exception message follows:\n"+e; + } + application_name = (String) rule_representation_json.get("name"); + DetectorSubcomponent new_detector = DetectorSubcomponent.detector_subcomponents.getOrDefault(application_name,new DetectorSubcomponent(default_handled_application_name,CharacterizedThread.CharacterizedThreadRunMode.detached)); new_detector.slo_rule_topic_subscriber_function.apply(Constants.slo_rules_topic,string_rule_representation); return ("New application was spawned"); } + + @PostMapping(value = "/new-application-metric-list", + consumes = APPLICATION_JSON_VALUE) + public static String parse_metric_list(@RequestBody String metric_list){ + JSONObject metric_list_json; + JSONArray metrics_json_array; + JSONParser json_parser = new JSONParser(); + String application_name; + try { + metric_list_json = (JSONObject) json_parser.parse(metric_list); + } catch (ParseException e) { + return "Error in parsing the input string, the exception message follows:\n"+e; + } + application_name = (String) metric_list_json.get("name"); + DetectorSubcomponent new_detector = DetectorSubcomponent.detector_subcomponents.getOrDefault(application_name,new DetectorSubcomponent(application_name,CharacterizedThread.CharacterizedThreadRunMode.detached)); + + HashMap application_metrics = new_detector.getSubcomponent_state().getMonitoring_attributes(); + metrics_json_array = (JSONArray) metric_list_json.get("metric_list"); + for (Object metric : metrics_json_array){ + JSONObject metric_json = (JSONObject) metric; + String metric_name = (String) metric_json.get("name"); + int upper_bound = 100,lower_bound = 0; + if (((String) metric_json.get("upper_bound")).toLowerCase().contains("-inf")){ + upper_bound = -Integer.MAX_VALUE; + }else if (((String) metric_json.get("upper_bound")).toLowerCase().contains("inf")){ + upper_bound = Integer.MAX_VALUE; + } + if (((String) metric_json.get("lower_bound")).toLowerCase().contains("-inf")){ + lower_bound = -Integer.MAX_VALUE; + } + else if (((String) metric_json.get("lower_bound")).toLowerCase().contains("inf")){ + lower_bound = Integer.MAX_VALUE; + } + application_metrics.put(metric_name,new RealtimeMonitoringAttribute(metric_name,lower_bound,upper_bound)); + } + + RealtimeMonitoringAttribute.initialize_monitoring_attributes(new_detector,application_metrics); + return ("New application was spawned - The monitoring metrics related to the application are the following: "+application_metrics); + } } diff --git a/slo-violation-detector/src/main/java/runtime/Main.java b/slo-violation-detector/src/main/java/runtime/Main.java index e2495ba..665e3ef 100644 --- a/slo-violation-detector/src/main/java/runtime/Main.java +++ b/slo-violation-detector/src/main/java/runtime/Main.java @@ -46,7 +46,7 @@ public class Main { try { { - InputStream inputStream = null; + InputStream inputStream; if (args.length == 0) { operational_mode = getSLOViolationDetectionOperationalMode("DIRECTOR"); inputStream = getPreferencesFileInputStream(EMPTY); @@ -70,9 +70,9 @@ public class Main { slo_violation_probability_threshold = Double.parseDouble(prop.getProperty("slo_violation_probability_threshold")); slo_violation_determination_method = prop.getProperty("slo_violation_determination_method"); maximum_acceptable_forward_predictions = Integer.parseInt(prop.getProperty("maximum_acceptable_forward_predictions")); - DetectorSubcomponent detector = new DetectorSubcomponent(detached); + DetectorSubcomponent detector = new DetectorSubcomponent(default_handled_application_name,detached); detectors.add(detector); - ArrayList unbounded_metric_strings = new ArrayList(Arrays.asList(prop.getProperty("metrics_bounds").split(","))); + ArrayList unbounded_metric_strings = new ArrayList<>(Arrays.asList(prop.getProperty("metrics_bounds").split(","))); for (String metric_string : unbounded_metric_strings) { detector.getSubcomponent_state().getMonitoring_attributes_bounds_representation().put(metric_string.split(";")[0], metric_string.split(";", 2)[1]); } diff --git a/slo-violation-detector/src/main/java/slo_violation_detector_engine/DetectorSubcomponent.java b/slo-violation-detector/src/main/java/slo_violation_detector_engine/DetectorSubcomponent.java index f76c0ef..711a48b 100644 --- a/slo-violation-detector/src/main/java/slo_violation_detector_engine/DetectorSubcomponent.java +++ b/slo-violation-detector/src/main/java/slo_violation_detector_engine/DetectorSubcomponent.java @@ -19,8 +19,6 @@ import static utility_beans.CharacterizedThread.CharacterizedThreadRunMode.attac public class DetectorSubcomponent extends SLOViolationDetectorSubcomponent{ public static final SynchronizedInteger detector_integer_id = new SynchronizedInteger(); public static HashMap detector_subcomponents = new HashMap<>(); //A HashMap containing all detector subcomponents - private DetectorSubcomponentUtilities utilities; - private DetectorSubcomponentState subcomponent_state; public final AtomicBoolean stop_signal = new AtomicBoolean(false); public final SynchronizedBoolean can_modify_slo_rules = new SynchronizedBoolean(false); @@ -34,11 +32,10 @@ public class DetectorSubcomponent extends SLOViolationDetectorSubcomponent{ public Long last_processed_adaptation_time = -1L;//initialization - public DetectorSubcomponent(CharacterizedThread.CharacterizedThreadRunMode characterized_thread_run_mode) { + public DetectorSubcomponent(String application_name, CharacterizedThread.CharacterizedThreadRunMode characterized_thread_run_mode) { super.thread_type = CharacterizedThread.CharacterizedThreadType.slo_bound_running_thread; subcomponent_state = new DetectorSubcomponentState(); - utilities = new DetectorSubcomponentUtilities(); - Integer current_detector_id = -1;//initialization + Integer current_detector_id; synchronized (detector_integer_id){ /*try { detector_integer_id.wait(); @@ -54,7 +51,7 @@ public class DetectorSubcomponent extends SLOViolationDetectorSubcomponent{ }else/*detached mode*/{ CharacterizedThread.create_new_thread(new Runnables.SLODetectionEngineRunnable(this), "detector_"+current_detector_id+"_master_thread", true,this); } - detector_subcomponents.put(String.valueOf(current_detector_id),this); + detector_subcomponents.put(application_name+"_"+current_detector_id,this); } public BiFunction slo_rule_topic_subscriber_function = (topic, message) -> { @@ -84,15 +81,6 @@ public class DetectorSubcomponent extends SLOViolationDetectorSubcomponent{ //TODO possibly necessary to remove the next adaptation time as it will probably not be possible to start an adaptation during it return topic + ":MSG:" + message; }; - - public DetectorSubcomponentUtilities getUtilities() { - return utilities; - } - - public void setUtilities(DetectorSubcomponentUtilities utilities) { - this.utilities = utilities; - } - public static String get_detector_subcomponent_statistics() { return "Currently, the number of active detectors are "+detector_integer_id; } diff --git a/slo-violation-detector/src/main/java/utility_beans/RealtimeMonitoringAttribute.java b/slo-violation-detector/src/main/java/utility_beans/RealtimeMonitoringAttribute.java index 660d54f..09ef628 100644 --- a/slo-violation-detector/src/main/java/utility_beans/RealtimeMonitoringAttribute.java +++ b/slo-violation-detector/src/main/java/utility_beans/RealtimeMonitoringAttribute.java @@ -22,21 +22,34 @@ import static utility_beans.PredictedMonitoringAttribute.*; public class RealtimeMonitoringAttribute { protected String name; + private Integer upper_bound; + private Integer lower_bound; + private CircularFifoQueue actual_metric_values = new CircularFifoQueue<>(kept_values_per_metric); //the previous actual values of the metric - private CircularFifoQueue actual_metric_values = new CircularFifoQueue(kept_values_per_metric); //the previous actual values of the metric - + public RealtimeMonitoringAttribute(String name, Integer lower_bound, Integer upper_bound){ + this.name = name; + this.lower_bound = lower_bound; + this.upper_bound = upper_bound; + } public RealtimeMonitoringAttribute(String name, Collection values){ this.name = name; - values.stream().forEach(x -> actual_metric_values.add(x)); + this.lower_bound = 0; + this.upper_bound = 100; + //Equivalent to below: values.stream().forEach(x -> actual_metric_values.add(x)); + actual_metric_values.addAll(values); } public RealtimeMonitoringAttribute(String name, Double value){ this.name = name; + this.lower_bound = 0; + this.upper_bound = 100; actual_metric_values.add(value); } public RealtimeMonitoringAttribute(String name){ this.name = name; + this.lower_bound = 0; + this.upper_bound = 100; } public static Double get_metric_value(DetectorSubcomponent detector, String metric_name){ @@ -88,43 +101,16 @@ public class RealtimeMonitoringAttribute { } } - - /* - public static > void initialize_monitoring_attribute_min_values(T metric_names){ - initialize_attribute_value_hashmap(monitoring_attributes_min_values,metric_names); - } - - public static > void initialize_monitoring_attribute_max_values(T metric_names){ - initialize_attribute_value_hashmap(monitoring_attributes_max_values,metric_names); - } -*/ - private static > void initialize_attribute_value_hashmap(HashMap hashmap ,T metric_names){ - for (String metric_name: metric_names){ - hashmap.put(metric_name,0.0); + public static > void initialize_monitoring_attributes (DetectorSubcomponent detector, T metric_names_bounds){ + for (String metric_name : metric_names_bounds.keySet()) { + detector.getSubcomponent_state().getMonitoring_attributes_statistics().put(metric_name, new + MonitoringAttributeStatistics(metric_names_bounds.get(metric_name).lower_bound,metric_names_bounds.get(metric_name).upper_bound)); } } - -/* - public static HashMap getMonitoring_attributes_min_values() { - return monitoring_attributes_min_values; - } - - public static void setMonitoring_attributes_min_values(HashMap monitoring_attributes_min_values) { - RealtimeMonitoringAttribute.monitoring_attributes_min_values = monitoring_attributes_min_values; - } - - public static HashMap getMonitoring_attributes_max_values() { - return monitoring_attributes_max_values; - } - - public static void setMonitoring_attributes_max_values(HashMap monitoring_attributes_max_values) { - RealtimeMonitoringAttribute.monitoring_attributes_max_values = monitoring_attributes_max_values; - } -*/ - public static void update_monitoring_attributes_values_map(DetectorSubcomponent detector, HashMap input_data) { - for (HashMap.Entry entry: input_data.entrySet()){ - update_monitoring_attribute_value(detector, entry.getKey(),entry.getValue()); + private static > void initialize_attribute_value_hashmap(HashMap hashmap ,T metric_names){ + for (String metric_name: metric_names){ + hashmap.put(metric_name,0.0); } } @@ -144,5 +130,19 @@ public class RealtimeMonitoringAttribute { this.actual_metric_values = actual_metric_values; } + public Integer getUpper_bound() { + return upper_bound; + } + public void setUpper_bound(Integer upper_bound) { + this.upper_bound = upper_bound; + } + + public Integer getLower_bound() { + return lower_bound; + } + + public void setLower_bound(Integer lower_bound) { + this.lower_bound = lower_bound; + } } diff --git a/slo-violation-detector/src/test/java/DerivedMonitoringAttributeTests.java b/slo-violation-detector/src/test/java/DerivedMonitoringAttributeTests.java index 9060bc9..daa0e73 100644 --- a/slo-violation-detector/src/test/java/DerivedMonitoringAttributeTests.java +++ b/slo-violation-detector/src/test/java/DerivedMonitoringAttributeTests.java @@ -14,7 +14,9 @@ import utility_beans.RealtimeMonitoringAttribute; import utility_beans.PredictedMonitoringAttribute; import java.util.Arrays; +import java.util.List; +import static configuration.Constants.default_handled_application_name; import static configuration.Constants.roc_limit; import static utility_beans.PredictedMonitoringAttribute.getAttributes_maximum_rate_of_change; import static utility_beans.PredictedMonitoringAttribute.getAttributes_minimum_rate_of_change; @@ -23,13 +25,11 @@ import static utility_beans.RealtimeMonitoringAttribute.update_monitoring_attrib public class DerivedMonitoringAttributeTests { - DetectorSubcomponent detector = new DetectorSubcomponent(CharacterizedThread.CharacterizedThreadRunMode.detached); + DetectorSubcomponent detector = new DetectorSubcomponent(default_handled_application_name,CharacterizedThread.CharacterizedThreadRunMode.detached); @Test public void roc_calculation_test(){ - RealtimeMonitoringAttribute realtimeMonitoringAttribute = new RealtimeMonitoringAttribute("cpu"); - - simple_initialize_0_100_bounded_attributes(detector,Arrays.asList(new String[]{"cpu"})); + simple_initialize_0_100_bounded_attributes(detector, List.of("cpu")); update_monitoring_attribute_value(detector,"cpu",0.0); detector.getSubcomponent_state().getMonitoring_attributes_roc_statistics().put("cpu", new MonitoringAttributeStatistics()); //The rate of change of a metric, is a metric which itself should be monitored for its upper bound diff --git a/slo-violation-detector/src/test/java/SeverityTests.java b/slo-violation-detector/src/test/java/SeverityTests.java index f0533ed..8eb8eb1 100644 --- a/slo-violation-detector/src/test/java/SeverityTests.java +++ b/slo-violation-detector/src/test/java/SeverityTests.java @@ -17,9 +17,11 @@ import utility_beans.PredictedMonitoringAttribute; import java.util.ArrayList; +import static configuration.Constants.default_handled_application_name; + public class SeverityTests { - DetectorSubcomponent detector = new DetectorSubcomponent(CharacterizedThread.CharacterizedThreadRunMode.detached); + DetectorSubcomponent detector = new DetectorSubcomponent(default_handled_application_name, CharacterizedThread.CharacterizedThreadRunMode.detached); @Test public void all_metrics_Severity_test_1(){ diff --git a/slo-violation-detector/src/test/java/UnboundedMonitoringAttributeTests.java b/slo-violation-detector/src/test/java/UnboundedMonitoringAttributeTests.java index ddf2d3d..22deea8 100644 --- a/slo-violation-detector/src/test/java/UnboundedMonitoringAttributeTests.java +++ b/slo-violation-detector/src/test/java/UnboundedMonitoringAttributeTests.java @@ -68,8 +68,8 @@ public class UnboundedMonitoringAttributeTests { */ //private String metric_1_name = "custom_metric_1"; - private static Long targeted_prediction_time = 100000000000L; - private DetectorSubcomponent detector = new DetectorSubcomponent(detached); + private static final Long targeted_prediction_time = 100000000000L; + private final DetectorSubcomponent detector = new DetectorSubcomponent(default_handled_application_name,detached); @Test public void unbounded_monitoring_attribute_test_1() throws IOException, ParseException { unbounded_monitoring_attribute_test_core("src/main/resources/test_v3_custom_metric_1_simple.json","custom_metric_1",new Double[]{20.0,35.0},new Double[]{110.0,130.0},0.0,50,100, 90,10,0.80); @@ -105,7 +105,7 @@ public class UnboundedMonitoringAttributeTests { JSONObject rule_json = (JSONObject) new JSONParser().parse(String.join(EMPTY, Files.readAllLines(Paths.get(new File(json_file_name).getAbsolutePath())))); ArrayList slo_rules = new ArrayList<>(); - SLORule slo_rule = new SLORule(rule_json.toJSONString(), new ArrayList<>(Arrays.asList(new String[]{metric_1_name})),detector); + SLORule slo_rule = new SLORule(rule_json.toJSONString(), new ArrayList<>(Arrays.asList(metric_1_name)),detector); slo_rules.add(slo_rule); initialize_subrule_and_attribute_associations(slo_rules,new SynchronizedBoolean()); @@ -238,9 +238,7 @@ public class UnboundedMonitoringAttributeTests { metrics.add(custom_metric_1); for (MetricConfiguration metric: metrics) { - Thread publishing_thread = new Thread(() -> { - perpetual_metric_publisher(metric.name,metric.base_metric_value,metric.forecasted_metric_value,metric.confidence_interval,metric.probability, metric_max_value, publish_interval_in_milliseconds); - }); + Thread publishing_thread = new Thread(() -> perpetual_metric_publisher(metric.name,metric.base_metric_value,metric.forecasted_metric_value,metric.confidence_interval,metric.probability, metric_max_value, publish_interval_in_milliseconds)); publishing_thread.start(); } }