diff --git a/grouping/PPO_cg.py b/grouping/PPO_cg.py index f64153e76864b6929e3a15737f01d53d4e5e86ea..26c6ef37a7f129b84d14fde8f5bc18d724afed89 100644 --- a/grouping/PPO_cg.py +++ b/grouping/PPO_cg.py @@ -4,9 +4,8 @@ from tensorflow.keras import layers import scipy.signal import time from threading import Thread -import json, os, time,uvicorn, requests, sys, logging +import json, os, time,uvicorn, requests, logging from fastapi import FastAPI -from test_application import UtilitySimulator from pydantic import BaseModel from action_creator import prepareX, makeY_, find_solutions, final_list from gym import Env @@ -17,7 +16,6 @@ import random import requests from random import shuffle import string -from collections import deque import tensorflow as tf from tensorflow.keras import layers from itertools import combinations diff --git a/grouping/requirements.txt b/grouping/requirements.txt index 3284d8f065fbece58411972f6c9ecdf3172bfbc8..29d23cf4af42e658a71e0c8f385dc1ab290b0c00 100644 --- a/grouping/requirements.txt +++ b/grouping/requirements.txt @@ -1,11 +1,11 @@ -tensorflow==2.6.0 -keras==2.6.0 -scipy==1.7.2 +tensorflow +keras +scipy uvicorn -fastapi==0.73.0 -pydantic==1.9.0 +fastapi +pydantic stomp.py slugify -gym==0.17.3 -numpy>=1.19.2 -requests==2.26.0 \ No newline at end of file +gym +numpy +requests diff --git a/morphemic-forecasting-exponentialsmoothing/src/requirements.txt b/morphemic-forecasting-exponentialsmoothing/src/requirements.txt index 8e4f9183c0903f9f69f41f155534bc8473ac0eab..342c42d9e5dc991b51559d7dee45ce02a386c7e3 100644 --- a/morphemic-forecasting-exponentialsmoothing/src/requirements.txt +++ b/morphemic-forecasting-exponentialsmoothing/src/requirements.txt @@ -4,3 +4,5 @@ jproperties requests msgpack numpy +pandas +influxdb \ No newline at end of file diff --git a/morphemic-persistent-storage/database/inputapi/requirements.txt b/morphemic-persistent-storage/database/inputapi/requirements.txt index 6bf935bd10389e09c76729f7d32c8c150c8d3a89..220c4e2052b682cbf4aaa6b6669779a5c24da943 100644 --- a/morphemic-persistent-storage/database/inputapi/requirements.txt +++ b/morphemic-persistent-storage/database/inputapi/requirements.txt @@ -1,4 +1,5 @@ influxdb stomp.py requests -python-slugify \ No newline at end of file +python-slugify +chardet \ No newline at end of file diff --git a/morphemic-slo-severity-calculator/Dockerfile b/morphemic-slo-severity-calculator/Dockerfile index 6a304b53695209ce95c3d69d0c73e523616c655b..e60b40f0f5151723863a385a0a266029308e8dc2 100644 --- a/morphemic-slo-severity-calculator/Dockerfile +++ b/morphemic-slo-severity-calculator/Dockerfile @@ -9,4 +9,4 @@ COPY src/main/resources/config/eu.morphemic.slo_violation_detector.properties /h COPY src/main/resources/config/eu.melodic.event.brokerclient.properties /home/src/main/resources/config/eu.melodic.event.brokerclient.properties COPY target/SLOSeverityCalculator-4.0-SNAPSHOT.jar /home/SLOSeverityCalculator-4.0-SNAPSHOT.jar WORKDIR /home -CMD ["/bin/sh","-c","java -jar SLOSeverityCalculator-4.0-SNAPSHOT.jar > $LOG_FILE"] +CMD ["/bin/sh","-c","java -jar SLOSeverityCalculator-4.0-SNAPSHOT.jar > $LOG_FILE 2>&1"] diff --git a/morphemic-slo-severity-calculator/src/main/java/configuration/Constants.java b/morphemic-slo-severity-calculator/src/main/java/configuration/Constants.java index c8c7789cdbabe075a7fbd282898b7bd4f9db27b5..cc850ada1372309d91fdcd51be55f977b292d03b 100644 --- a/morphemic-slo-severity-calculator/src/main/java/configuration/Constants.java +++ b/morphemic-slo-severity-calculator/src/main/java/configuration/Constants.java @@ -36,6 +36,7 @@ public class Constants { public static String configuration_file_location = "src/main/resources/config/eu.morphemic.slo_violation_detector.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 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"; public static boolean self_publish_rule_file = false; //default value to be overriden diff --git a/morphemic-slo-severity-calculator/src/main/java/metric_retrieval/AttributeSubscription.java b/morphemic-slo-severity-calculator/src/main/java/metric_retrieval/AttributeSubscription.java index 19522878670d20fb4d1c68b528c6209a833dd099..fcf378b2eae69d0f3e52ff9aa842f10946d24f95 100644 --- a/morphemic-slo-severity-calculator/src/main/java/metric_retrieval/AttributeSubscription.java +++ b/morphemic-slo-severity-calculator/src/main/java/metric_retrieval/AttributeSubscription.java @@ -87,7 +87,15 @@ public class AttributeSubscription { double forecasted_value = ((Number)((JSONObject)new JSONParser().parse(message)).get(EventFields.PredictionMetricEventFields.metric_value)).doubleValue(); double probability_confidence = 100*((Number)((JSONObject)new JSONParser().parse(message)).get(EventFields.PredictionMetricEventFields.probability)).doubleValue(); JSONArray json_array_confidence_interval = ((JSONArray)((JSONObject)new JSONParser().parse(message)).get(EventFields.PredictionMetricEventFields.confidence_interval)); - double confidence_interval = ((Number)json_array_confidence_interval.get(1)).doubleValue() - ((Number)json_array_confidence_interval.get(0)).doubleValue(); + + double confidence_interval; + try{ + confidence_interval = ((Number) json_array_confidence_interval.get(1)).doubleValue() - ((Number) json_array_confidence_interval.get(0)).doubleValue(); + }catch (ClassCastException | NumberFormatException c){ + Logger.getAnonymousLogger().log(info_logging_level,"Catching exception successfully"); + c.printStackTrace(); + confidence_interval = Double.NEGATIVE_INFINITY; + } long timestamp = ((Number)((JSONObject)new JSONParser().parse(message)).get(EventFields.PredictionMetricEventFields.timestamp)).longValue(); long targeted_prediction_time = ((Number)((JSONObject)new JSONParser().parse(message)).get(EventFields.PredictionMetricEventFields.prediction_time)).longValue(); Logger.getAnonymousLogger().log(info_logging_level,"RECEIVED message with predicted value for "+predicted_attribute_name+" equal to "+ forecasted_value); @@ -110,13 +118,16 @@ public class AttributeSubscription { PREDICTION_EXISTS.setValue(true); PREDICTION_EXISTS.notifyAll(); } - }else{ - if(adaptation_times.contains(targeted_prediction_time)){ + }else { + if (adaptation_times.contains(targeted_prediction_time)) { Logger.getAnonymousLogger().log(info_logging_level, "Could not add the new targeted prediction time " + targeted_prediction_time + " from topic " + topic + " as it is already present"); - }else if (!adaptation_times_pending_processing.contains(targeted_prediction_time)){ - Logger.getAnonymousLogger().log(info_logging_level, "Could not add the new targeted prediction time " + targeted_prediction_time + " from topic " + topic + " as it is already pending processing"); - }else if (targeted_prediction_time * 1000 - time_horizon_seconds * 1000L - (Clock.systemUTC()).millis()<=0) { + } else if (!adaptation_times_pending_processing.contains(targeted_prediction_time)) { + if (targeted_prediction_time * 1000 - time_horizon_seconds * 1000L - (Clock.systemUTC()).millis() <= 0) { Logger.getAnonymousLogger().log(info_logging_level, "Could not add the new targeted prediction time " + targeted_prediction_time + " from topic " + topic + " as it would expire in " + (targeted_prediction_time * 1000 - System.currentTimeMillis()) + " milliseconds and the prediction horizon is " + time_horizon_seconds * 1000L + " milliseconds"); + }else{ + Logger.getAnonymousLogger().log(info_logging_level,"Adding new prediction time "+targeted_prediction_time+" which expires in " + (targeted_prediction_time * 1000 - System.currentTimeMillis())); + adaptation_times_pending_processing.add(targeted_prediction_time); + } } } ADAPTATION_TIMES_MODIFY.setValue(true); @@ -150,6 +161,8 @@ public class AttributeSubscription { p.printStackTrace(); } catch (InterruptedException e) { Logger.getAnonymousLogger().log(info_logging_level,"Monitoring attribute subscription thread for prediction attribute "+predicted_attribute_name+" is stopped"); + } catch (ClassCastException | NumberFormatException n){ + Logger.getAnonymousLogger().log(info_logging_level,"Error while trying to parse message\n"+message); } return message; }; diff --git a/morphemic-slo-severity-calculator/src/main/java/runtime/Main.java b/morphemic-slo-severity-calculator/src/main/java/runtime/Main.java index 47f858c9e271f35e9e86be8b70a0972bbe672662..0b60069c5837031e8e002ddc929b76739d35dafd 100644 --- a/morphemic-slo-severity-calculator/src/main/java/runtime/Main.java +++ b/morphemic-slo-severity-calculator/src/main/java/runtime/Main.java @@ -11,12 +11,13 @@ package runtime; import eu.melodic.event.brokerclient.BrokerPublisher; import eu.melodic.event.brokerclient.BrokerSubscriber; import metric_retrieval.AttributeSubscription; +import org.apache.commons.collections4.queue.CircularFifoQueue; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; import slo_processing.SLORule; import slo_processing.SLOSubRule; +import utilities.DebugDataSubscription; import utilities.MathUtils; import utility_beans.*; @@ -56,6 +57,8 @@ public class Main { public static Long current_slo_rules_version = -1L;//initialization public static final AtomicBoolean slo_rule_arrived = new AtomicBoolean(false); public static final SynchronizedBoolean can_modify_slo_rules = new SynchronizedBoolean(false); + + public static CircularFifoQueue slo_violation_event_recording_queue = new CircularFifoQueue<>(50); private static Properties prop = new Properties(); public static void main(String[] args) { @@ -91,6 +94,7 @@ public class Main { single_slo_rule_active = Boolean.parseBoolean(prop.getProperty("single_slo_rule_active")); time_horizon_seconds = Integer.parseInt(prop.getProperty("time_horizon_seconds")); + 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")); ArrayList unbounded_metric_strings = new ArrayList(Arrays.asList(prop.getProperty("metrics_bounds").split(","))); @@ -218,6 +222,7 @@ public class Main { } stop_all_running_threads(); + DebugDataSubscription.initiate(prop.getProperty("broker_ip_url"),prop.getProperty("broker_username"), prop.getProperty("broker_password")); initialize_monitoring_datastructures_with_empty_data(slo_rules); // initialize_subrule_and_attribute_associations(slo_rules); @@ -570,15 +575,18 @@ public class Main { double rule_severity = process_rule_value(rule.getRule_representation(), targeted_prediction_time, rule.getRule_format()); double slo_violation_probability = determine_slo_violation_probability(rule_severity); Logger.getAnonymousLogger().log(info_logging_level, "The overall " + slo_violation_determination_method + " severity - calculated from real data - for adaptation time " + targeted_prediction_time + " ( " + (new Date((new Timestamp(targeted_prediction_time * 1000)).getTime())) + " ) is " + rule_severity + " and is calculated " + time_horizon_seconds + " seconds beforehand"); - Logger.getAnonymousLogger().log(info_logging_level, "The probability of an SLO violation is " + ((int) (slo_violation_probability * 100)) + "%" + (slo_violation_probability<0.5?" so it will not be published":" and it will be published")); + Logger.getAnonymousLogger().log(info_logging_level, "The probability of an SLO violation is " + ((int) (slo_violation_probability * 100)) + "%" + (slo_violation_probability< slo_violation_probability_threshold ?" so it will not be published":" and it will be published")); - if (slo_violation_probability>=0.5) { + if (slo_violation_probability>= slo_violation_probability_threshold) { JSONObject severity_json = new JSONObject(); severity_json.put("severity", rule_severity); severity_json.put("probability", slo_violation_probability); severity_json.put("predictionTime", targeted_prediction_time); persistent_publisher.publish(severity_json.toJSONString()); } + + slo_violation_event_recording_queue.add(System.currentTimeMillis()); + //Probably not necessary to synchronize the line below as each removal will happen only once in a reconfiguration interval, and reconfiguration intervals are assumed to have a duration of minutes. //Necessary to synchronize because another severity calculation thread might invoke clean_data above, and then a concurrent modification exception may arise synchronized (ADAPTATION_TIMES_MODIFY){ @@ -666,12 +674,16 @@ public class Main { public static double determine_slo_violation_probability(double rule_severity) { if (slo_violation_determination_method.equals("all-metrics")) { //39.64 is the mean severity value when examining all integer severity values for roc x probability x confidence_interval x delta_value in (-100,100)x(0,100)x(0,100)x(-100,100) + /* if (rule_severity >= 40) { return Math.min((50 + 50*(rule_severity - 40) / 60)/100,1); // in case we desire the probability to start from 50% // return Math.min((100*(rule_severity - 40) / 60)/100,1); // in case we desire the probability to start from 0% } else { return 0; } + + */ + return Math.min(rule_severity/100,100); }else if (slo_violation_determination_method.equals("prconf-delta")){ //Logger.getAnonymousLogger().log(warning_logging_level,"The calculation of probability for the prconf-delta method needs to be implemented"); //return 0; diff --git a/morphemic-slo-severity-calculator/src/main/java/slo_processing/SLORule.java b/morphemic-slo-severity-calculator/src/main/java/slo_processing/SLORule.java index 0b5a8338b07d0bf0320c38937cd74c86c0f4fb31..460a0823548fdac342b477eafcdaff738e936ba9 100644 --- a/morphemic-slo-severity-calculator/src/main/java/slo_processing/SLORule.java +++ b/morphemic-slo-severity-calculator/src/main/java/slo_processing/SLORule.java @@ -90,7 +90,12 @@ public class SLORule { } else { String attribute = (String) rule_json.get("attribute"); String threshold = (String) rule_json.get("threshold"); - subrules.add(new SLOSubRule(attribute, rule_operator, Double.parseDouble(threshold), Integer.parseInt(rule_id))); + if (rule_operator.equals("<>")) { + subrules.add(new SLOSubRule(attribute, "<", Double.parseDouble(threshold), Integer.parseInt(rule_id))); + subrules.add(new SLOSubRule(attribute, ">", Double.parseDouble(threshold), Integer.parseInt(rule_id)+1000000)); //assuming that there are less than 1000000 subrules + } else { + subrules.add(new SLOSubRule(attribute, rule_operator, Double.parseDouble(threshold), Integer.parseInt(rule_id))); + } } } //newer format @@ -104,14 +109,19 @@ public class SLORule { } else { String attribute = (String) rule_json.get("metric"); Double threshold = (Double) rule_json.get("threshold"); - subrules.add(new SLOSubRule(attribute, rule_operator, threshold,get_id_for(attribute))); + if (is_composite_rule_from_threshold_operator(rule_operator)) { + subrules.add(new SLOSubRule(attribute, ">", threshold,get_id_for(attribute))); + subrules.add(new SLOSubRule(attribute, "<", threshold,get_id_for(attribute))); //TODO perhaps here change the id + }else{ + subrules.add(new SLOSubRule(attribute, rule_operator, threshold,get_id_for(attribute))); + } } } return subrules; } /** - *This method is used to create a mapping between attribute names and id's in the case of 'newer' format SLO definitions + *This method is used to assign id's to attribute names and create a mapping between them, in the case of 'newer' format SLO definitions * @param attribute The name of the monitoring metric (attribute) for which the rule is formulated * @return An Integer identifier */ @@ -128,9 +138,11 @@ public class SLORule { String rule_id = (String)rule_json.get("id"); String rule_operator = (String)rule_json.get("operator"); String rule_metric = (String)rule_json.get("metric"); + Double rule_threshold = (Double)rule_json.get("threshold"); JSONArray subrules_json_array = new JSONArray(); boolean composite_rule = false; + boolean special_operator_subrule = false; //older format if ((rule_format.equals(SLOFormatVersion.older)) && is_composite_rule_from_id(rule_id)) { subrules_json_array = (JSONArray) rule_json.get(rule_id); @@ -141,6 +153,24 @@ public class SLORule { subrules_json_array = (JSONArray) rule_json.get("constraints"); composite_rule = true; } + else if (is_composite_rule_from_threshold_operator(rule_operator)){ + subrules_json_array = new JSONArray(); + composite_rule = true; + special_operator_subrule = true; + // operator, metric, name (unnecessary), threshold + //create simple json object for the two deterministic subrules (the greater-than and the less-than) + JSONObject first_simple_subrule_json = new JSONObject(); + JSONObject second_simple_subrule_json = new JSONObject(); + first_simple_subrule_json.put("operator",">"); + first_simple_subrule_json.put("threshold",rule_threshold); + first_simple_subrule_json.put("metric",rule_metric); + second_simple_subrule_json.put("operator","<"); + second_simple_subrule_json.put("threshold",rule_threshold); + second_simple_subrule_json.put("metric",rule_metric); + subrules_json_array.add(first_simple_subrule_json); + subrules_json_array.add(second_simple_subrule_json); + //subrules_json_array.add + } if (composite_rule){ ArrayList individual_severity_contributions = new ArrayList<>(); boolean and_subrules_invalidated = false; @@ -154,6 +184,9 @@ public class SLORule { }else if (rule_format.equals(SLOFormatVersion.newer)){ logical_operator = rule_operator.toLowerCase(); } + if (special_operator_subrule){ + logical_operator = "or"; + } if (logical_operator.equals("and")){ if (subrule_result<0){ //return -1; //all other rules are invalidated @@ -184,7 +217,7 @@ public class SLORule { else{ //String attribute_name = (String) rule_json.get("attribute"); //String operator = (String) rule_json.get("operator"); - //boolean greater_than_rule = operator.equals(">") || operator.equals(">="); + boolean is_greater_than_rule = rule_operator.equals(">") || rule_operator.equals(">="); //double threshold = Double.parseDouble((String) rule_json.get("threshold")); Integer subrule_id=0; if (rule_format.equals(SLOFormatVersion.older)) { @@ -198,14 +231,14 @@ public class SLORule { } PredictedMonitoringAttribute new_prediction_attribute = getPredicted_monitoring_attributes().get(subrule_id).get(targeted_prediction_time); - if (new_prediction_attribute==null || !new_prediction_attribute.isInitialized() || new_prediction_attribute.getDelta() e.equals(lowercase_operator))); } + private static boolean is_composite_rule_from_threshold_operator (String operator){ + return operator.equals("<>"); + } + private static String get_logical_operator_part(String rule_id) { return rule_id.split("-")[0]; //possibly contains the name of a logical operator } diff --git a/morphemic-slo-severity-calculator/src/main/java/slo_processing/SLOSubRule.java b/morphemic-slo-severity-calculator/src/main/java/slo_processing/SLOSubRule.java index 13ed657eb05455f150cf81d787c72584fffc198e..c5cd5ca4c78771838cb4abdcab44807caa3cd2b6 100644 --- a/morphemic-slo-severity-calculator/src/main/java/slo_processing/SLOSubRule.java +++ b/morphemic-slo-severity-calculator/src/main/java/slo_processing/SLOSubRule.java @@ -61,4 +61,9 @@ public class SLOSubRule { public void setAssociated_predicted_monitoring_attribute(PredictedMonitoringAttribute associated_predicted_monitoring_attribute) { this.associated_predicted_monitoring_attribute = associated_predicted_monitoring_attribute; } + + @Override + public String toString(){ + return ("The rule is "+metric+operator+threshold+"\n+ The associated Predicted Monitoring Attribute is "+associated_predicted_monitoring_attribute.toString()); + } } diff --git a/morphemic-slo-severity-calculator/src/main/java/utilities/DebugDataSubscription.java b/morphemic-slo-severity-calculator/src/main/java/utilities/DebugDataSubscription.java new file mode 100644 index 0000000000000000000000000000000000000000..0d273930e23ab85e6ddc107eab2c8273f0167ef8 --- /dev/null +++ b/morphemic-slo-severity-calculator/src/main/java/utilities/DebugDataSubscription.java @@ -0,0 +1,116 @@ +package utilities; + +import eu.melodic.event.brokerclient.BrokerPublisher; +import eu.melodic.event.brokerclient.BrokerSubscriber; +import org.apache.commons.collections4.queue.CircularFifoQueue; +import runtime.Main; +import slo_processing.SLOSubRule; +import utility_beans.RealtimeMonitoringAttribute; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiFunction; +import java.util.logging.Logger; + +import static configuration.Constants.amq_library_configuration_location; +import static configuration.Constants.info_logging_level; +import static runtime.Main.running_threads; +import static runtime.Main.slo_violation_event_recording_queue; + +/** + * The objective of this class is to allow a structured synopsis of the current state of the SLO Violation Detector to be created, as a response to a request sent to it through an appropriate topic. + */ +public class DebugDataSubscription { + + private static String debug_data_trigger_topic_name = "sloviolationdetector.debug"; + private static String debug_data_output_topic_name = "sloviolationdetector.debug_output"; + private static String broker_username,broker_password,broker_ip_address; + static BiFunction debug_data_generation = (topic, message) ->{ + + String output_debug_data = ""; + StringBuilder intermediate_debug_string = new StringBuilder(); + intermediate_debug_string = new StringBuilder(intermediate_debug_string + "The following threads are currently running" + "\n"); + + boolean flag_first_element_iterated = true; + for (String s : running_threads.keySet()){ + if (flag_first_element_iterated) { + intermediate_debug_string.append(s); + flag_first_element_iterated = false; + }else{ + intermediate_debug_string.append(",\n").append(s); + } + } + intermediate_debug_string.append("\n"); + output_debug_data = output_debug_data+intermediate_debug_string; + intermediate_debug_string = new StringBuilder(); + + flag_first_element_iterated = true; + intermediate_debug_string.append("The following Monitoring Attribute values are currently stored:\n"); + for ( Map.Entry entry :RealtimeMonitoringAttribute.getMonitoring_attributes().entrySet() ){ + if (flag_first_element_iterated){ + intermediate_debug_string.append("Metric name: ").append(entry.getKey()); + flag_first_element_iterated = false; + }else{ + intermediate_debug_string.append("\nMetric name: ").append(entry.getKey()); + } + + Double metric_value = RealtimeMonitoringAttribute.get_metric_value(entry.getKey()); + CircularFifoQueue metric_values = entry.getValue().getActual_metric_values(); + if (metric_value.isNaN()){ + intermediate_debug_string.append(" - value was determined as NaN, individual collected values are ").append(metric_values).append("\n"); + } + else if (metric_value.isInfinite()){ + intermediate_debug_string.append(" - value was determined as infinite, individual collected values are ").append(metric_values).append("\n"); + } else { + intermediate_debug_string.append(" - value from individual values").append(metric_values).append(" is ").append(metric_value).append("\n"); + } + + } + output_debug_data = output_debug_data+intermediate_debug_string; + intermediate_debug_string = new StringBuilder(); + + intermediate_debug_string.append("The following subrules have been parsed and are stored:\n"); + for (Map.Entry> entry : SLOSubRule.getSlo_subrules_per_monitoring_attribute().entrySet()){ + intermediate_debug_string.append("Metric name: ").append(entry.getKey()); + for (SLOSubRule rule : entry.getValue()) { + intermediate_debug_string.append("\n").append(rule.toString()); + } + intermediate_debug_string.append("\n"); + } + output_debug_data = output_debug_data+intermediate_debug_string; + intermediate_debug_string = new StringBuilder(); + + output_debug_data = output_debug_data+"\nShowing the adaptation times that pend processing:\n"+ Main.adaptation_times_pending_processing; + intermediate_debug_string.append("\nThese are the timestamps of the latest adaptation events\n").append(slo_violation_event_recording_queue); + + Logger.getGlobal().log(info_logging_level,"Debug data generated:\n"+output_debug_data); + BrokerPublisher publisher = new BrokerPublisher(debug_data_output_topic_name, broker_ip_address, broker_username, broker_password, amq_library_configuration_location); + publisher.publish(output_debug_data); + return output_debug_data; + }; + public static void initiate(String broker_ip_address, String broker_username, String broker_password) { + BrokerSubscriber debug_data_subscriber = new BrokerSubscriber(debug_data_trigger_topic_name, broker_ip_address, broker_username, broker_password, amq_library_configuration_location); + Thread debug_data_subscription_thread = new Thread(() -> { + try { + synchronized (Main.HAS_MESSAGE_ARRIVED.get_synchronized_boolean(debug_data_trigger_topic_name)) { + //if (Main.HAS_MESSAGE_ARRIVED.get_synchronized_boolean(debug_data_topic_name).getValue()) + debug_data_subscriber.subscribe(debug_data_generation, Main.stop_signal); + } + if (Thread.interrupted()) { + throw new InterruptedException(); + } + } catch (Exception i) { + Logger.getAnonymousLogger().log(info_logging_level, "Possible interruption of debug data subscriber thread for " + debug_data_trigger_topic_name + " - if not stacktrace follows"); + if (!(i instanceof InterruptedException)) { + i.printStackTrace(); + } + } finally { + Logger.getAnonymousLogger().log(info_logging_level, "Removing debug data subscriber thread for " + debug_data_trigger_topic_name); + running_threads.remove("debug_data_subscription_thread_" + debug_data_trigger_topic_name); + } + }); + running_threads.put("debug_data_subscription_thread_" + debug_data_trigger_topic_name, debug_data_subscription_thread); + debug_data_subscription_thread.start(); + } +} diff --git a/morphemic-slo-severity-calculator/src/main/java/utilities/SLOViolationCalculator.java b/morphemic-slo-severity-calculator/src/main/java/utilities/SLOViolationCalculator.java index cb4699d16c7248eed00fef6f6d58c3c9b342e8f9..c8be900ca6b97537ba2a6928469fcd8a21856292 100644 --- a/morphemic-slo-severity-calculator/src/main/java/utilities/SLOViolationCalculator.java +++ b/morphemic-slo-severity-calculator/src/main/java/utilities/SLOViolationCalculator.java @@ -17,10 +17,12 @@ import static configuration.Constants.warning_logging_level; public class SLOViolationCalculator { - public static double get_Severity_all_metrics_method(PredictedMonitoringAttribute predictionAttribute){ + public static double get_Severity_all_metrics_method(PredictedMonitoringAttribute predictionAttribute,boolean is_greater_than_rule){ - Double roc_sign = predictionAttribute.getRate_of_change()/Math.abs(predictionAttribute.getRate_of_change()); - Double delta_sign = predictionAttribute.getDelta()/Math.abs(predictionAttribute.getDelta()); + double all_metrics_method_attribute_severity; + if (is_greater_than_rule){ + Double roc_sign = predictionAttribute.getRate_of_change_for_greater_than_rule()/Math.abs(predictionAttribute.getRate_of_change_for_greater_than_rule()); + Double delta_sign = predictionAttribute.getDelta_for_greater_than_rule()/Math.abs(predictionAttribute.getDelta_for_greater_than_rule()); if (delta_sign.isNaN()){ delta_sign = 1.0; } @@ -28,22 +30,50 @@ public class SLOViolationCalculator { roc_sign = 1.0; } - double rate_of_change_factor = roc_sign*predictionAttribute.getRate_of_change()*predictionAttribute.getRate_of_change(); + double rate_of_change_factor = roc_sign*predictionAttribute.getRate_of_change_for_greater_than_rule()*predictionAttribute.getRate_of_change_for_greater_than_rule(); double probability_confidence_factor = predictionAttribute.getProbability_confidence()* predictionAttribute.getProbability_confidence()* (100-predictionAttribute.getNormalizedConfidenceIntervalWidth())* (100-predictionAttribute.getNormalizedConfidenceIntervalWidth())/ (100*100);//to normalize values - double delta_factor = delta_sign*predictionAttribute.getDelta()*predictionAttribute.getDelta(); + double delta_factor = delta_sign*predictionAttribute.getDelta_for_greater_than_rule()*predictionAttribute.getDelta_for_greater_than_rule(); double severity_sum = rate_of_change_factor+probability_confidence_factor+delta_factor; - double all_metrics_method_attribute_severity = Math.sqrt(severity_sum)/Math.sqrt(3); + all_metrics_method_attribute_severity = Math.sqrt(severity_sum)/Math.sqrt(3); - Logger.getAnonymousLogger().log(info_logging_level,"The all-metrics attribute severity for " + predictionAttribute.getName() + " based on a (roc,prconf,normalized_interval,delta) quadraplet of (" + predictionAttribute.getRate_of_change() + "," + predictionAttribute.getProbability_confidence()+ "," + predictionAttribute.getNormalizedConfidenceIntervalWidth()+","+predictionAttribute.getDelta() + ") is " + all_metrics_method_attribute_severity); + Logger.getAnonymousLogger().log(info_logging_level,"The all-metrics attribute severity for a greater-than rule related to attribute " + predictionAttribute.getName() + " based on a (roc,prconf,normalized_interval,delta) quadraplet of (" + predictionAttribute.getRate_of_change_for_greater_than_rule() + "," + predictionAttribute.getProbability_confidence()+ "," + predictionAttribute.getNormalizedConfidenceIntervalWidth()+","+predictionAttribute.getDelta_for_greater_than_rule() + ") is " + all_metrics_method_attribute_severity); if (severity_sum<0){ Logger.getAnonymousLogger().log(info_logging_level,"The NaN severity value is produced due to the root of a negative severity sum"); } + } + else{ + Double roc_sign = predictionAttribute.getRate_of_change_for_less_than_rule()/Math.abs(predictionAttribute.getRate_of_change_for_less_than_rule()); + Double delta_sign = predictionAttribute.getDelta_for_less_than_rule()/Math.abs(predictionAttribute.getDelta_for_less_than_rule()); + if (delta_sign.isNaN()){ + delta_sign = 1.0; + } + if (roc_sign.isNaN()){ + roc_sign = 1.0; + } + + double rate_of_change_factor = roc_sign*predictionAttribute.getRate_of_change_for_less_than_rule()*predictionAttribute.getRate_of_change_for_less_than_rule(); + double probability_confidence_factor = + predictionAttribute.getProbability_confidence()* + predictionAttribute.getProbability_confidence()* + (100-predictionAttribute.getNormalizedConfidenceIntervalWidth())* + (100-predictionAttribute.getNormalizedConfidenceIntervalWidth())/ + (100*100);//to normalize values + double delta_factor = delta_sign*predictionAttribute.getDelta_for_less_than_rule()*predictionAttribute.getDelta_for_less_than_rule(); + + double severity_sum = rate_of_change_factor+probability_confidence_factor+delta_factor; + all_metrics_method_attribute_severity = Math.sqrt(severity_sum)/Math.sqrt(3); + + Logger.getAnonymousLogger().log(info_logging_level,"The all-metrics attribute severity for a less-than rule related to attribute " + predictionAttribute.getName() + " based on a (roc,prconf,normalized_interval,delta) quadraplet of (" + predictionAttribute.getRate_of_change_for_less_than_rule() + "," + predictionAttribute.getProbability_confidence()+ "," + predictionAttribute.getNormalizedConfidenceIntervalWidth()+","+predictionAttribute.getDelta_for_less_than_rule() + ") is " + all_metrics_method_attribute_severity); + if (severity_sum<0){ + Logger.getAnonymousLogger().log(info_logging_level,"The NaN severity value is produced due to the root of a negative severity sum"); + } + } if (Double.isNaN(all_metrics_method_attribute_severity) || ( all_metrics_method_attribute_severity<0)){ Logger.getAnonymousLogger().log(warning_logging_level,"Negative or NaN severity produced: "+all_metrics_method_attribute_severity+" using 0 instead"); @@ -54,11 +84,16 @@ public class SLOViolationCalculator { } } - public static double get_Severity_prconf_delta_method(PredictedMonitoringAttribute predictionAttribute){ - - double severity_sum = (predictionAttribute.getDelta()*predictionAttribute.getProbability_confidence()*(100-predictionAttribute.getNormalizedConfidenceIntervalWidth()/100))/(100*100*100); //dividing by 10000 to normalize; - Logger.getAnonymousLogger().log(info_logging_level,"The prconf-delta attribute severity for " + predictionAttribute.getName() + " based on a (prconf,delta,confidence_interval) triplet of (" + predictionAttribute.getProbability_confidence() + "," + predictionAttribute.getDelta() +","+predictionAttribute.getConfidence_interval_width()+ ") is " + severity_sum); + public static double get_Severity_prconf_delta_method(PredictedMonitoringAttribute predictionAttribute,boolean is_greater_than_rule){ + double severity_sum; + if (is_greater_than_rule) { + severity_sum = (predictionAttribute.getDelta_for_greater_than_rule() * predictionAttribute.getProbability_confidence() * (100 - predictionAttribute.getNormalizedConfidenceIntervalWidth() / 100)) / (100 * 100 * 100); //dividing by 10000 to normalize; + Logger.getAnonymousLogger().log(info_logging_level, "The prconf-delta attribute severity for a greater-than rule related to attribute " + predictionAttribute.getName() + " based on a (prconf,delta,confidence_interval) triplet of (" + predictionAttribute.getProbability_confidence() + "," + predictionAttribute.getDelta_for_greater_than_rule() + "," + predictionAttribute.getConfidence_interval_width() + ") is " + severity_sum); + }else{ + severity_sum = (predictionAttribute.getDelta_for_less_than_rule() * predictionAttribute.getProbability_confidence() * (100 - predictionAttribute.getNormalizedConfidenceIntervalWidth() / 100)) / (100 * 100 * 100); //dividing by 10000 to normalize; + Logger.getAnonymousLogger().log(info_logging_level, "The prconf-delta attribute severity for a less-than rule related to attribute " + predictionAttribute.getName() + " based on a (prconf,delta,confidence_interval) triplet of (" + predictionAttribute.getProbability_confidence() + "," + predictionAttribute.getDelta_for_less_than_rule() + "," + predictionAttribute.getConfidence_interval_width() + ") is " + severity_sum); + } if (severity_sum<0){ Logger.getAnonymousLogger().log(info_logging_level,"A NaN severity value may be produced due to the root of a negative severity sum - returning zero instead for severity sum"); severity_sum = 0; diff --git a/morphemic-slo-severity-calculator/src/main/java/utility_beans/PredictedMonitoringAttribute.java b/morphemic-slo-severity-calculator/src/main/java/utility_beans/PredictedMonitoringAttribute.java index a1934cc30fe0df0dc0a41bb272017e4834d756c9..9bc6053ff2852948f10151d99b4889811555ab54 100644 --- a/morphemic-slo-severity-calculator/src/main/java/utility_beans/PredictedMonitoringAttribute.java +++ b/morphemic-slo-severity-calculator/src/main/java/utility_beans/PredictedMonitoringAttribute.java @@ -25,9 +25,11 @@ public class PredictedMonitoringAttribute { private String name; private boolean initialized = false; - private double delta; + private double delta_for_greater_than_rule; + private double delta_for_less_than_rule; private double threshold; - private double rate_of_change; // the rate of change for the metric + private double rate_of_change_for_greater_than_rule; // the rate of change for the metric + private double rate_of_change_for_less_than_rule; // the rate of change for the metric private double probability_confidence; //the probability confidence for the prediction private double confidence_interval_width; private long timestamp; @@ -48,43 +50,44 @@ public class PredictedMonitoringAttribute { this.initialized = false; return; } - this.rate_of_change = getRateOfChange(forecasted_value, current_value,name); - if (greater_than_rule) { - - if(getMonitoring_attributes_statistics().get(name).getUpper_bound()>threshold){ - this.delta = 100*(forecasted_value - threshold)/(getMonitoring_attributes_statistics().get(name).getUpper_bound()-threshold); - }else /*if (getMonitoring_attributes_statistics().get(name).getUpper_bound()<=threshold)*/{ - if (forecasted_value>threshold){ - this.delta = 100; - }else if (forecasted_value==threshold){ - this.delta = 0; - }else{ - this.delta = -100; - } + this.rate_of_change_for_greater_than_rule = getRateOfChange(forecasted_value, current_value,name); + this.rate_of_change_for_less_than_rule = -this.rate_of_change_for_greater_than_rule; //inversion necessary, as when a rate of change is positive, it means that the metric is increasing and thus not directed towards the interval in which a less-than rule is fired. + + //Calculations for greater_than rule delta metric + + if(getMonitoring_attributes_statistics().get(name).getUpper_bound()>threshold){ + this.delta_for_greater_than_rule = 100*(forecasted_value - threshold)/(getMonitoring_attributes_statistics().get(name).getUpper_bound()-threshold); + }else /*if (getMonitoring_attributes_statistics().get(name).getUpper_bound()<=threshold)*/{ + if (forecasted_value>threshold){ + this.delta_for_greater_than_rule = 100; + }else if (forecasted_value==threshold){ + this.delta_for_greater_than_rule = 0; + }else{ + this.delta_for_greater_than_rule = -100; } + } + this.delta_for_greater_than_rule = Math.min(Math.max(this.delta_for_greater_than_rule,-100),100); + //this.previous_delta = 100*Math.abs(current_value - threshold)/(getMonitoring_attributes_statistics().get(name).getUpper_bound()-threshold); - //this.previous_delta = 100*Math.abs(current_value - threshold)/(getMonitoring_attributes_statistics().get(name).getUpper_bound()-threshold); - }else{ - this.rate_of_change = -this.rate_of_change; //inversion necessary, as when a rate of change is positive, it means that the metric is increasing and thus not directed towards the interval in which a less-than rule is fired. + //Calculations for less_than rule delta metric - if(threshold>getMonitoring_attributes_statistics().get(name).getLower_bound()) { + if(threshold>getMonitoring_attributes_statistics().get(name).getLower_bound()) { - this.delta = 100 * (threshold - forecasted_value) / (threshold - getMonitoring_attributes_statistics().get(name).getLower_bound()); + this.delta_for_less_than_rule = 100 * (threshold - forecasted_value) / (threshold - getMonitoring_attributes_statistics().get(name).getLower_bound()); - //this.previous_delta = 100*Math.abs(current_value-threshold)/(threshold-getMonitoring_attributes_statistics().get(name).getLower_bound()); + //this.previous_delta = 100*Math.abs(current_value-threshold)/(threshold-getMonitoring_attributes_statistics().get(name).getLower_bound()); + }else{ + if (threshold>forecasted_value){ + this.delta_for_less_than_rule = 100; + }else if (threshold==forecasted_value){ + this.delta_for_less_than_rule = 0; }else{ - if (threshold>forecasted_value){ - this.delta = 100; - }else if (threshold==forecasted_value){ - this.delta = 0; - }else{ - this.delta = -100; - } + this.delta_for_less_than_rule = -100; } - - //this.previous_delta = 100*Math.abs(current_value-threshold)/(threshold-getMonitoring_attributes_statistics().get(name).getLower_bound()); } - this.delta = Math.min(Math.max(this.delta,-100),100); + this.delta_for_less_than_rule = Math.min(Math.max(this.delta_for_less_than_rule,-100),100); + //this.previous_delta = 100*Math.abs(current_value-threshold)/(threshold-getMonitoring_attributes_statistics().get(name).getLower_bound()); + this.probability_confidence = probability_confidence; this.confidence_interval_width = confidence_interval_width; //actual_metric_values = get_last_n_actual_values(Constants.elements_considered_in_prediction, MonitoringAttribute.get_monitoring_attributes_values_map().get(name),true); @@ -201,14 +204,20 @@ public class PredictedMonitoringAttribute { return new_values; } - public double getDelta() { - return delta; + public double getDelta_for_greater_than_rule() { + return delta_for_greater_than_rule; + } + public double getDelta_for_less_than_rule() { + return delta_for_less_than_rule; } - public void setDelta(double delta) { - this.delta = delta; + public void setDelta_for_greater_than_rule(double delta) { + this.delta_for_greater_than_rule = delta_for_greater_than_rule; } + public void setDelta_for_less_than_rule(double delta) { + this.delta_for_less_than_rule = delta_for_less_than_rule; + } public double getThreshold() { return threshold; } @@ -217,12 +226,19 @@ public class PredictedMonitoringAttribute { this.threshold = threshold; } - public double getRate_of_change() { - return rate_of_change; + public double getRate_of_change_for_greater_than_rule() { + return rate_of_change_for_greater_than_rule; + } + public double getRate_of_change_for_less_than_rule() { + return rate_of_change_for_less_than_rule; + } + + public void setRate_of_change_for_greater_than_rule(double rate_of_change_for_greater_than_rule) { + this.rate_of_change_for_greater_than_rule = rate_of_change_for_greater_than_rule; } - public void setRate_of_change(double rate_of_change) { - this.rate_of_change = rate_of_change; + public void setRate_of_change_for_less_than_rule(double rate_of_change_for_less_than_rule) { + this.rate_of_change_for_less_than_rule = rate_of_change_for_less_than_rule; } public double getProbability_confidence() { @@ -263,4 +279,12 @@ public class PredictedMonitoringAttribute { public void setTimestamp(long timestamp) { this.timestamp = timestamp; } + + @Override + public String toString(){ + String output = ""; + output="{"+name+" deltas: "+delta_for_greater_than_rule+","+delta_for_less_than_rule+" ROCs: "+rate_of_change_for_greater_than_rule+","+rate_of_change_for_less_than_rule+" PrConf:"+probability_confidence+" Confidence Interval: "+confidence_interval_width+"Prediction Timestamp: "+timestamp+"}"; + return output; + } + } diff --git a/morphemic-slo-severity-calculator/src/main/resources/config/eu.morphemic.slo_violation_detector.properties b/morphemic-slo-severity-calculator/src/main/resources/config/eu.morphemic.slo_violation_detector.properties index 917e6caf8bfb5d4a56b4c29a675a806dfa6503c1..4891a40b31908dcf221dfac8c7fd331635bf02bc 100644 --- a/morphemic-slo-severity-calculator/src/main/resources/config/eu.morphemic.slo_violation_detector.properties +++ b/morphemic-slo-severity-calculator/src/main/resources/config/eu.morphemic.slo_violation_detector.properties @@ -8,6 +8,7 @@ broker_ip_url = tcp://localhost:61616?wireFormat.maxInactivityDuration=0 broker_username = morphemic broker_password = morphemic +slo_violation_probability_threshold = 0.1 slo_violation_determination_method = prconf-delta time_horizon_seconds = 120 maximum_acceptable_forward_predictions = 30 \ No newline at end of file diff --git a/morphemic-slo-severity-calculator/src/test/java/DerivedMonitoringAttributeTests.java b/morphemic-slo-severity-calculator/src/test/java/DerivedMonitoringAttributeTests.java index 81c5aeb4a7d5edea2eba4c682be231fc4bec9782..295d550815324dcc427c60d88463194c5158d8e6 100644 --- a/morphemic-slo-severity-calculator/src/test/java/DerivedMonitoringAttributeTests.java +++ b/morphemic-slo-severity-calculator/src/test/java/DerivedMonitoringAttributeTests.java @@ -32,6 +32,6 @@ public class DerivedMonitoringAttributeTests { PredictedMonitoringAttribute prediction_attribute = new PredictedMonitoringAttribute("cpu",true,70,1,100.0,100,1,System.currentTimeMillis(),System.currentTimeMillis()+20000); - assert prediction_attribute.getRate_of_change() == 100.0; + assert prediction_attribute.getRate_of_change_for_greater_than_rule() == 100.0; } } diff --git a/morphemic-slo-severity-calculator/src/test/java/SeverityTests.java b/morphemic-slo-severity-calculator/src/test/java/SeverityTests.java index aeff7ea8e14736966fdfc62301a4115addf3678f..feac881967f748068ff19f66f6393dd6c34f679d 100644 --- a/morphemic-slo-severity-calculator/src/test/java/SeverityTests.java +++ b/morphemic-slo-severity-calculator/src/test/java/SeverityTests.java @@ -35,11 +35,11 @@ public class SeverityTests { PredictedMonitoringAttribute prediction_attribute = new PredictedMonitoringAttribute("cpu",true,70,1,100.0,100,10,System.currentTimeMillis(),System.currentTimeMillis()+20000); - assert (prediction_attribute.getRate_of_change() < 100.0000000001 && prediction_attribute.getRate_of_change()>99.9999999999); //maximum value + assert (prediction_attribute.getRate_of_change_for_greater_than_rule() < 100.0000000001 && prediction_attribute.getRate_of_change_for_greater_than_rule()>99.9999999999); //maximum value assert (prediction_attribute.getConfidence_interval_width() <10.000000000001 && prediction_attribute.getConfidence_interval_width()>9.9999999999); assert(prediction_attribute.getProbability_confidence()<100.0000000001 && prediction_attribute.getProbability_confidence()>99.99999999); - assert(prediction_attribute.getDelta()<100.0000000001 && prediction_attribute.getDelta()>99.99999999); - assert Math.floor(SLOViolationCalculator.get_Severity_all_metrics_method(prediction_attribute)*100) == 9678; + assert(prediction_attribute.getDelta_for_greater_than_rule()<100.0000000001 && prediction_attribute.getDelta_for_greater_than_rule()>99.99999999); + assert Math.floor(SLOViolationCalculator.get_Severity_all_metrics_method(prediction_attribute,true)*100) == 9678; } @Test @@ -60,11 +60,11 @@ public class SeverityTests { PredictedMonitoringAttribute prediction_attribute = new PredictedMonitoringAttribute("cpu",true,70,1,80.0,90,5,System.currentTimeMillis(),System.currentTimeMillis()+20000); - assert (prediction_attribute.getRate_of_change() > 99.99999999 && prediction_attribute.getRate_of_change()< 100.00000001); //zero value + assert (prediction_attribute.getRate_of_change_for_greater_than_rule() > 99.99999999 && prediction_attribute.getRate_of_change_for_greater_than_rule()< 100.00000001); //zero value assert (prediction_attribute.getConfidence_interval_width() <5.000000000001 && prediction_attribute.getConfidence_interval_width()>4.9999999999); assert (prediction_attribute.getProbability_confidence()<90.0000000001 && prediction_attribute.getProbability_confidence()>89.99999999); - assert (prediction_attribute.getDelta()<33.3333333334 && prediction_attribute.getDelta()>33.3333333332); - assert Math.floor(SLOViolationCalculator.get_Severity_all_metrics_method(prediction_attribute)*100) == 7836; + assert (prediction_attribute.getDelta_for_greater_than_rule()<33.3333333334 && prediction_attribute.getDelta_for_greater_than_rule()>33.3333333332); + assert Math.floor(SLOViolationCalculator.get_Severity_all_metrics_method(prediction_attribute,true)*100) == 7836; } @Test @@ -85,11 +85,11 @@ public class SeverityTests { PredictedMonitoringAttribute prediction_attribute = new PredictedMonitoringAttribute("cpu",true,75,1,92.0,88,7.8,System.currentTimeMillis(),System.currentTimeMillis()+20000); - assert (prediction_attribute.getRate_of_change()> 6.97674418604 && prediction_attribute.getRate_of_change()< 6.97674418605 ); //zero value + assert (prediction_attribute.getRate_of_change_for_greater_than_rule()> 6.97674418604 && prediction_attribute.getRate_of_change_for_greater_than_rule()< 6.97674418605 ); //zero value assert (prediction_attribute.getConfidence_interval_width() >7.7999999 && prediction_attribute.getConfidence_interval_width()<7.8000001); assert (prediction_attribute.getProbability_confidence()<88.0000000001 && prediction_attribute.getProbability_confidence()>87.99999999); - assert (prediction_attribute.getDelta()<68.0000000001 && prediction_attribute.getDelta()>67.99999999); - assert Math.floor(SLOViolationCalculator.get_Severity_all_metrics_method(prediction_attribute)*100) == 6125; + assert (prediction_attribute.getDelta_for_greater_than_rule()<68.0000000001 && prediction_attribute.getDelta_for_greater_than_rule()>67.99999999); + assert Math.floor(SLOViolationCalculator.get_Severity_all_metrics_method(prediction_attribute,true)*100) == 6125; } diff --git a/morphemic-slo-severity-calculator/src/test/java/UnboundedMonitoringAttributeTests.java b/morphemic-slo-severity-calculator/src/test/java/UnboundedMonitoringAttributeTests.java index f9da72a58059c431f17dc653f22c626ab7facabd..d9be7f41a32d36179274df81ccbcf75577166128 100644 --- a/morphemic-slo-severity-calculator/src/test/java/UnboundedMonitoringAttributeTests.java +++ b/morphemic-slo-severity-calculator/src/test/java/UnboundedMonitoringAttributeTests.java @@ -63,7 +63,7 @@ class MetricConfiguration{ public class UnboundedMonitoringAttributeTests { /** - * This 30-second test assumes the availability of a broker, which is configured in the standard configuration file location employed by the Main method. It also assumes that random input of a custom metric centered around 75 is provided (using an independent data provider). Based on this constant input, the standard deviation and mean is calculated, and the lower/upper bounds are estimated - it is assumed that the metric is upwards and downwards unbounded. The assertions of the test are estimations based on repeated iterations with 100-sample data. + * This 30-second test assumes the availability of a broker, which is configured in the standard configuration file location employed by the Main method. It also assumes that random input of a custom metric centered around a value (75 for the first test) is provided (using an independent data provider). Based on this constant input, the standard deviation and mean is calculated, and the lower/upper bounds are estimated - in the case of the first test it is assumed that the metric is upwards and downwards unbounded. The assertions of the test are estimations based on repeated iterations with 100-sample data. */ //private String metric_1_name = "custom_metric_1"; @@ -71,11 +71,15 @@ public class UnboundedMonitoringAttributeTests { @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); + 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); + } + @Test + public void unbounded_monitoring_attribute_test_2() throws IOException, ParseException { + unbounded_monitoring_attribute_test_core("src/main/resources/test_v3_custom_metric_unequal.json","number_of_users",new Double[]{-50.0,0.0},new Double[]{0.0,50.0},0.0,-25,20,5,0.3,0.90); } - public void unbounded_monitoring_attribute_test_core(String json_file_name, String metric_1_name, Double[] metric_lower_bound_range, Double[] metric_upper_bound_range, Double severity_lower_bound) throws IOException, ParseException { + public void unbounded_monitoring_attribute_test_core(String json_file_name, String metric_1_name, Double[] metric_lower_bound_range, Double[] metric_upper_bound_range, double severity_lower_bound, double base_metric_value, double metric_max_value, double forecasted_metric_value,double generated_data_confidence_interval, double probability) throws IOException, ParseException { Main.can_modify_slo_rules.setValue(true); Properties prop = new Properties(); @@ -105,7 +109,7 @@ public class UnboundedMonitoringAttributeTests { slo_rules.add(slo_rule); initialize_subrule_and_attribute_associations(slo_rules); - data_publisher_for_unbounded_test_1(metric_1_name); + data_publisher_for_unbounded_test(metric_1_name, metric_max_value, base_metric_value,forecasted_metric_value,generated_data_confidence_interval,probability); ArrayList running = new ArrayList<>(); for (String metric_name : metric_names) { @@ -141,7 +145,7 @@ public class UnboundedMonitoringAttributeTests { HashMap> predicted_attributes = getPredicted_monitoring_attributes(); try { double forecasted_value = ((Number)((JSONObject)new JSONParser().parse(message)).get(EventFields.PredictionMetricEventFields.metric_value)).doubleValue(); - double probability_confidence = ((Number)((JSONObject)new JSONParser().parse(message)).get(EventFields.PredictionMetricEventFields.probability)).doubleValue(); + double probability_confidence = 100*((Number)((JSONObject)new JSONParser().parse(message)).get(EventFields.PredictionMetricEventFields.probability)).doubleValue(); //double confidence_interval = ((Number)((JSONObject)new JSONParser().parse(message)).get(EventFields.PredictionMetricEventFields.confidence_interval)).doubleValue(); JSONArray json_array_confidence_interval = ((JSONArray)((JSONObject)new JSONParser().parse(message)).get(EventFields.PredictionMetricEventFields.confidence_interval)); double confidence_interval = ((Number)json_array_confidence_interval.get(1)).doubleValue() - ((Number)json_array_confidence_interval.get(0)).doubleValue(); @@ -220,10 +224,10 @@ public class UnboundedMonitoringAttributeTests { } - public void data_publisher_for_unbounded_test_1(String metric_name){ + public void data_publisher_for_unbounded_test(String metric_name, double metric_max_value, double base_metric_value, double forecasted_metric_value, double confidence_interval, double probability ){ int publish_interval_in_milliseconds = 100; - MetricConfiguration custom_metric_1 = new MetricConfiguration(metric_name,50,90,10,0.80); + MetricConfiguration custom_metric_1 = new MetricConfiguration(metric_name,base_metric_value,forecasted_metric_value,confidence_interval,probability); //MetricConfiguration ram_metric = new MetricConfiguration("ram",90,100,5,100); @@ -232,13 +236,13 @@ public class UnboundedMonitoringAttributeTests { 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,publish_interval_in_milliseconds); + 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(); } } - private static void perpetual_metric_publisher(String metric_name, double base_metric_value, double forecasted_metric_value, double confidence_interval, double probability, int publish_interval_in_milliseconds) { + private static void perpetual_metric_publisher(String metric_name, double base_metric_value, double forecasted_metric_value, double confidence_interval, double probability, double metric_max_value, int publish_interval_in_milliseconds) { BrokerPublisher realtime_data_publisher = new BrokerPublisher(metric_name, "tcp://localhost:61616", "admin", "admin","src/main/resources/config/eu.melodic.event.brokerclient.properties"); BrokerPublisher forecasted_data_publisher = new BrokerPublisher("prediction."+metric_name, "tcp://localhost:61616", "admin", "admin","src/main/resources/config/eu.melodic.event.brokerclient.properties"); @@ -247,7 +251,7 @@ public class UnboundedMonitoringAttributeTests { JSONObject realtime_metric_json_object = new JSONObject(); //Create values centered around 82.5 double random_value = ThreadLocalRandom.current().nextDouble(); - realtime_metric_json_object.put("metricValue", base_metric_value+random_value*(100-base_metric_value)); + realtime_metric_json_object.put("metricValue", base_metric_value+random_value*(metric_max_value-base_metric_value)); realtime_metric_json_object.put("timestamp",System.currentTimeMillis()); realtime_data_publisher.publish(realtime_metric_json_object.toJSONString()); diff --git a/polymorphic_solver/src/ml_models/env.py b/polymorphic_solver/src/ml_models/env.py index 1c66ae0529a78983976e21a9f037c32ced2041d8..9aba2e58313faa7519d980002fa3f5197e95572a 100644 --- a/polymorphic_solver/src/ml_models/env.py +++ b/polymorphic_solver/src/ml_models/env.py @@ -91,7 +91,7 @@ prefix_predicted_metric = os.environ.get("PREFIX_PREDICTED_METRIC","Predictions" polymorphic_solver_topic = os.environ.get("POLYMORPHIC_TOPIC","polymorphic_solver") min_deployment_size_analysis = int(os.environ.get("MINIMUM_COLLECTION_SIZE_ANALYSIS","100")) -exploring_period = int(os.environ.get("EXPLORE_PERIOD","600")) +exploring_period = int(os.environ.get("EXPLORE_PERIOD","900")) def get_value_from_name(name, _type): name = str(name) diff --git a/polymorphic_solver/src/morphemic.py b/polymorphic_solver/src/morphemic.py index 0c479af769303ee3295ba5d2eaada6392be1f111..f9069eb659d99072897707fd0fb35dda02a9e525 100644 --- a/polymorphic_solver/src/morphemic.py +++ b/polymorphic_solver/src/morphemic.py @@ -343,13 +343,13 @@ class MorphemicArchetypeManager(): if self.best_camel_utility == None or best_performance > self.best_camel_utility: filename = self.camel_transformer.archetypesToCamels(best_group, self.camel_version, self.current_grouping) if filename: - self.camel_version +=1 print("Current camel model performance = {0}".format(best_performance)) logging.info("Current camel model performance = {0}".format(best_performance)) self.best_camel_utility = best_performance if self.importNewCamel(filename): self.notifyMorphemic(filename) self.polymorphic_solver.setCurrentDeploymentConfiguration(best_group) + self.camel_version +=1 self.cleanAllArchetypes() def importNewCamel(self, filename): @@ -379,39 +379,20 @@ class MorphemicArchetypeManager(): return {"status": "SUCCESS", "errorCode":"", "errorDescription":""} def notifyMorphemic(self, camel_name): - if self.camel_version == 0: - data = { - "applicationId": self.application_id + "Ver"+ str(self.camel_version), - "camel_model": camel_name, - "grouping": self.current_grouping, - "watermark": self.getWatermark(), - "result": self.getResultNotification() - } - try: - response = requests.post(mule_hostname+self.uri_notification,data=json.dumps(data), verify=config_folder+"/"+truststore_filename, headers={"Content-Type": "application/json"}) - print('*************Mule**************') - logging.info("Camel model version {0} created ".format(self.camel_version)) - print(response.text) - print("*******************************") - except Exception as e: - print(e) - else: - data = { - "applicationId": self.application_id + "Ver"+ str(self.camel_version), - "username": morphemic_camunda_username, - "password": morphemic_camunda_password, - "useExistingCP": False, - "isSimulation": False, - "cdoResourcePath": self.application_id + "Ver"+ str(self.camel_version), - "watermark": self.getWatermark() - } - try: - response = requests.post(mule_hostname+camunda_endpoint_redeployment,data=json.dumps(data), verify=config_folder+"/"+truststore_filename, headers={"Content-Type": "application/json"}) - print('*************Mule**************') - print(response.text) - print("*******************************") - except Exception as e: - print(e) + data = { + "applicationId": self.application_id + "Ver"+ str(self.camel_version), + "camel_model": camel_name, + "grouping": self.current_grouping, + "watermark": self.getWatermark(), + "result": self.getResultNotification() + } + try: + response = requests.post(mule_hostname+self.uri_notification,data=json.dumps(data), verify=config_folder+"/"+truststore_filename, headers={"Content-Type": "application/json"}) + print('*************Mule**************') + print(response.text) + print("*******************************") + except Exception as e: + print(e) class CamelTransformer(): diff --git a/prediction_orchestrator/src/main/java/eu/morphemic/prediction_orchestrator/service/Coordinator.java b/prediction_orchestrator/src/main/java/eu/morphemic/prediction_orchestrator/service/Coordinator.java index cca588b61f201d485fdf83af254491bf745e7f60..c34b8b96ed98c12da44776b942271c00a28e9e58 100644 --- a/prediction_orchestrator/src/main/java/eu/morphemic/prediction_orchestrator/service/Coordinator.java +++ b/prediction_orchestrator/src/main/java/eu/morphemic/prediction_orchestrator/service/Coordinator.java @@ -51,13 +51,19 @@ public class Coordinator { //Communication 5 and 1 synchronized void publishIfPooledValuesProvidedForAllMetrics(long predictionTime, int lastValueUpdate, String callingMetricHandler) { - //metricName -> predictionAvailability + /metricName -> predictionAvailability HashMap isPooledPredictionAvailable = new HashMap<>(); - metricHandlers.forEach((metricName, metricHandler) -> - isPooledPredictionAvailable.put(metricName, metricHandler.containsPooledPrediction(predictionTime))); + metricHandlers.forEach((metricName, metricHandler) -> { + boolean isAvailable = metricHandler.containsPooledPrediction(predictionTime); + isPooledPredictionAvailable.put(metricName, isAvailable); + log.debug("Checking pooled prediction for metric {}: {}", metricName, isAvailable ? "Available" : "Not Available"); + }); boolean entireVectorIsReady = isPooledPredictionAvailable.entrySet().stream() - .allMatch(Map.Entry::getValue); + .allMatch(Map.Entry::getValue); + log.debug("Entire vector readiness status: {}", entireVectorIsReady ? "Ready" : "Not Ready"); + + if (entireVectorIsReady) { log.info("Starting publishing pooled predictions for metrics for {} ", PredictionTimeFormatter.rawDateFormat(predictionTime));