From 70780ea4e6a861543b473ca1565d3df8345afdd6 Mon Sep 17 00:00:00 2001 From: msvinaykumar Date: Fri, 21 Jul 2023 14:11:20 +0530 Subject: [PATCH] resolved conflicts Signed-off-by: msvinaykumar --- .../ResourceOptimizationOpenshiftImpl.java | 154 ++++++++++-------- .../services/UpdateRecommendations.java | 4 +- .../com/autotune/utils/KruizeConstants.java | 2 + 3 files changed, 92 insertions(+), 68 deletions(-) diff --git a/src/main/java/com/autotune/analyzer/performanceProfiles/PerformanceProfileInterface/ResourceOptimizationOpenshiftImpl.java b/src/main/java/com/autotune/analyzer/performanceProfiles/PerformanceProfileInterface/ResourceOptimizationOpenshiftImpl.java index 3effb6451..fd24e41be 100644 --- a/src/main/java/com/autotune/analyzer/performanceProfiles/PerformanceProfileInterface/ResourceOptimizationOpenshiftImpl.java +++ b/src/main/java/com/autotune/analyzer/performanceProfiles/PerformanceProfileInterface/ResourceOptimizationOpenshiftImpl.java @@ -21,12 +21,14 @@ import com.autotune.analyzer.recommendations.Recommendation; import com.autotune.analyzer.recommendations.RecommendationConstants; import com.autotune.analyzer.recommendations.RecommendationNotification; -import com.autotune.analyzer.utils.AnalyzerConstants; import com.autotune.analyzer.recommendations.engine.DurationBasedRecommendationEngine; import com.autotune.analyzer.recommendations.engine.KruizeRecommendationEngine; +import com.autotune.analyzer.utils.AnalyzerConstants; import com.autotune.common.data.result.ContainerData; import com.autotune.common.data.result.ExperimentResultData; import com.autotune.common.k8sObjects.K8sObject; +import com.autotune.database.service.ExperimentDBService; +import com.autotune.utils.KruizeConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,6 +36,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; /** * Util class to validate the performance profile metrics with the experiment results metrics. @@ -43,20 +46,20 @@ public class ResourceOptimizationOpenshiftImpl extends PerfProfileImpl { private static final Logger LOGGER = LoggerFactory.getLogger(ResourceOptimizationOpenshiftImpl.class); List kruizeRecommendationEngineList; + public ResourceOptimizationOpenshiftImpl() { + this.init(); + } + private void init() { // Add new engines kruizeRecommendationEngineList = new ArrayList(); // Create Duration based engine - DurationBasedRecommendationEngine durationBasedRecommendationEngine = new DurationBasedRecommendationEngine(); + DurationBasedRecommendationEngine durationBasedRecommendationEngine = new DurationBasedRecommendationEngine(); // TODO: Create profile based engine AnalyzerConstants.RegisterRecommendationEngineStatus _unused_status = registerEngine(durationBasedRecommendationEngine); // TODO: Add profile based once recommendation algos are available } - public ResourceOptimizationOpenshiftImpl() { - this.init(); - } - @Override public AnalyzerConstants.RegisterRecommendationEngineStatus registerEngine(KruizeRecommendationEngine kruizeRecommendationEngine) { if (null == kruizeRecommendationEngine) { @@ -77,73 +80,92 @@ public List getEngines() { } @Override - public void generateRecommendation(KruizeObject kruizeObject, ExperimentResultData experimentResultData) { + public void generateRecommendation(KruizeObject kruizeObject, List experimentResultDataList, Timestamp interval_start_time, Timestamp interval_end_time) throws Exception { + /* + To restrict the number of rows in the result set, the Load results operation involves locating the appropriate method and configuring the desired limitation. + It's important to note that in order for the Limit rows feature to function correctly, + the CreateExperiment API must adhere strictly to the trail settings' measurement duration and should not allow arbitrary values + */ + String experiment_name = kruizeObject.getExperimentName(); + int limitRows = (int) (( + KruizeConstants.RecommendationEngineConstants.DurationBasedEngine.DurationAmount.LONG_TERM_DURATION_DAYS * + KruizeConstants.DateFormats.MINUTES_FOR_DAY) + / kruizeObject.getTrial_settings().getMeasurement_durationMinutes_inDouble()); + Map mainKruizeExperimentMap = new HashMap<>(); + mainKruizeExperimentMap.put(experiment_name, kruizeObject); + new ExperimentDBService().loadResultsFromDBByName(mainKruizeExperimentMap, + experiment_name, + interval_end_time, + limitRows); + //TODO: Will be updated once algo is completed - if (null != kruizeObject && null != experimentResultData) { - RecommendationSettings recommendationSettings = kruizeObject.getRecommendation_settings(); + for (ExperimentResultData experimentResultData : experimentResultDataList) { + if (null != kruizeObject && null != experimentResultData) { + RecommendationSettings recommendationSettings = kruizeObject.getRecommendation_settings(); - for (K8sObject k8sObjectResultData : experimentResultData.getKubernetes_objects()) { - // We only support one K8sObject currently - K8sObject k8sObjectKruizeObject = kruizeObject.getKubernetes_objects().get(0); - for (String cName : k8sObjectResultData.getContainerDataMap().keySet()) { - ContainerData containerDataResultData = k8sObjectResultData.getContainerDataMap().get(cName); - if (null == containerDataResultData.getResults()) - continue; - if (containerDataResultData.getResults().isEmpty()) - continue; - // Get the monitoringEndTime from ResultData's ContainerData. Should have only one element - Timestamp monitoringEndTime = containerDataResultData.getResults().keySet().stream().max(Timestamp::compareTo).get(); - // Get the ContainerData from the KruizeObject and not from ResultData - ContainerData containerDataKruizeObject = k8sObjectKruizeObject.getContainerDataMap().get(cName); - for (KruizeRecommendationEngine engine : getEngines()) { - // Check if minimum data available to generate recommendation - if (!engine.checkIfMinDataAvailable(containerDataKruizeObject)) + for (K8sObject k8sObjectResultData : experimentResultData.getKubernetes_objects()) { + // We only support one K8sObject currently + K8sObject k8sObjectKruizeObject = kruizeObject.getKubernetes_objects().get(0); + for (String cName : k8sObjectResultData.getContainerDataMap().keySet()) { + ContainerData containerDataResultData = k8sObjectResultData.getContainerDataMap().get(cName); + if (null == containerDataResultData.getResults()) continue; - - // Now generate a new recommendation for the new data corresponding to the monitoringEndTime - HashMap recommendationHashMap = engine.generateRecommendation(containerDataKruizeObject, monitoringEndTime, recommendationSettings); - if (null == recommendationHashMap || recommendationHashMap.isEmpty()) + if (containerDataResultData.getResults().isEmpty()) continue; - ContainerRecommendations containerRecommendations = containerDataKruizeObject.getContainerRecommendations(); - // Just to make sure the container recommendations object is not empty - if (null == containerRecommendations) { - containerRecommendations = new ContainerRecommendations(); - } - // check if notification exists - boolean notificationExist = false; - if (containerRecommendations.getNotificationMap().containsKey(RecommendationConstants.NotificationCodes.INFO_DURATION_BASED_RECOMMENDATIONS_AVAILABLE)) - notificationExist = true; + // Get the monitoringEndTime from ResultData's ContainerData. Should have only one element + Timestamp monitoringEndTime = containerDataResultData.getResults().keySet().stream().max(Timestamp::compareTo).get(); + // Get the ContainerData from the KruizeObject and not from ResultData + ContainerData containerDataKruizeObject = k8sObjectKruizeObject.getContainerDataMap().get(cName); + for (KruizeRecommendationEngine engine : getEngines()) { + // Check if minimum data available to generate recommendation + if (!engine.checkIfMinDataAvailable(containerDataKruizeObject)) + continue; - // If there is no notification add one - if (!notificationExist) { - RecommendationNotification recommendationNotification = new RecommendationNotification( - RecommendationConstants.RecommendationNotification.INFO_DURATION_BASED_RECOMMENDATIONS_AVAILABLE - ); - containerRecommendations.getNotificationMap().put(recommendationNotification.getCode(), recommendationNotification); - } + // Now generate a new recommendation for the new data corresponding to the monitoringEndTime + HashMap recommendationHashMap = engine.generateRecommendation(containerDataKruizeObject, monitoringEndTime, recommendationSettings); + if (null == recommendationHashMap || recommendationHashMap.isEmpty()) + continue; + ContainerRecommendations containerRecommendations = containerDataKruizeObject.getContainerRecommendations(); + // Just to make sure the container recommendations object is not empty + if (null == containerRecommendations) { + containerRecommendations = new ContainerRecommendations(); + } + // check if notification exists + boolean notificationExist = false; + if (containerRecommendations.getNotificationMap().containsKey(RecommendationConstants.NotificationCodes.INFO_DURATION_BASED_RECOMMENDATIONS_AVAILABLE)) + notificationExist = true; - // Get the engine recommendation map for a time stamp if it exists else create one - HashMap>> timestampBasedRecommendationMap - = containerRecommendations.getData(); - if (null == timestampBasedRecommendationMap) { - timestampBasedRecommendationMap = new HashMap>>(); - } - // check if engines map exists else create one - HashMap> enginesRecommendationMap = null; - if (timestampBasedRecommendationMap.containsKey(monitoringEndTime)) { - enginesRecommendationMap = timestampBasedRecommendationMap.get(monitoringEndTime); - } else { - enginesRecommendationMap = new HashMap>(); + // If there is no notification add one + if (!notificationExist) { + RecommendationNotification recommendationNotification = new RecommendationNotification( + RecommendationConstants.RecommendationNotification.INFO_DURATION_BASED_RECOMMENDATIONS_AVAILABLE + ); + containerRecommendations.getNotificationMap().put(recommendationNotification.getCode(), recommendationNotification); + } + + // Get the engine recommendation map for a time stamp if it exists else create one + HashMap>> timestampBasedRecommendationMap + = containerRecommendations.getData(); + if (null == timestampBasedRecommendationMap) { + timestampBasedRecommendationMap = new HashMap>>(); + } + // check if engines map exists else create one + HashMap> enginesRecommendationMap = null; + if (timestampBasedRecommendationMap.containsKey(monitoringEndTime)) { + enginesRecommendationMap = timestampBasedRecommendationMap.get(monitoringEndTime); + } else { + enginesRecommendationMap = new HashMap>(); + } + // put recommendations tagging to engine + enginesRecommendationMap.put(engine.getEngineKey(), recommendationHashMap); + // put recommendations tagging to timestamp + timestampBasedRecommendationMap.put(monitoringEndTime, enginesRecommendationMap); + // set the data object to map + containerRecommendations.setData(timestampBasedRecommendationMap); + // set the container recommendations in container object + containerDataKruizeObject.setContainerRecommendations(containerRecommendations); } - // put recommendations tagging to engine - enginesRecommendationMap.put(engine.getEngineKey(), recommendationHashMap); - // put recommendations tagging to timestamp - timestampBasedRecommendationMap.put(monitoringEndTime, enginesRecommendationMap); - // set the data object to map - containerRecommendations.setData(timestampBasedRecommendationMap); - // set the container recommendations in container object - containerDataKruizeObject.setContainerRecommendations(containerRecommendations); - } + } } } } diff --git a/src/main/java/com/autotune/analyzer/services/UpdateRecommendations.java b/src/main/java/com/autotune/analyzer/services/UpdateRecommendations.java index 018f6555b..b326b94a5 100644 --- a/src/main/java/com/autotune/analyzer/services/UpdateRecommendations.java +++ b/src/main/java/com/autotune/analyzer/services/UpdateRecommendations.java @@ -17,10 +17,10 @@ import com.autotune.analyzer.experiment.ExperimentInitiator; import com.autotune.analyzer.kruizeObject.KruizeObject; +import com.autotune.analyzer.recommendations.RecommendationConstants; import com.autotune.analyzer.serviceObjects.ContainerAPIObject; import com.autotune.analyzer.serviceObjects.Converters; import com.autotune.analyzer.serviceObjects.ListRecommendationsAPIObject; -import com.autotune.analyzer.utils.AnalyzerConstants; import com.autotune.analyzer.utils.AnalyzerErrorConstants; import com.autotune.analyzer.utils.GsonUTCDateAdapter; import com.autotune.common.data.result.ContainerData; @@ -114,7 +114,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) if (success) sendSuccessResponse(response, kruizeObject, interval_end_time); else { - sendErrorResponse(response, null, HttpServletResponse.SC_BAD_REQUEST, AnalyzerConstants.RecommendationNotificationMsgConstant.NOT_ENOUGH_DATA); + sendErrorResponse(response, null, HttpServletResponse.SC_BAD_REQUEST, RecommendationConstants.RecommendationNotificationMsgConstant.NOT_ENOUGH_DATA); } } catch (Exception e) { e.printStackTrace(); diff --git a/src/main/java/com/autotune/utils/KruizeConstants.java b/src/main/java/com/autotune/utils/KruizeConstants.java index d40cbae2e..cdb744629 100644 --- a/src/main/java/com/autotune/utils/KruizeConstants.java +++ b/src/main/java/com/autotune/utils/KruizeConstants.java @@ -365,6 +365,8 @@ private DBConstants() { public static final class DateFormats { public static final String STANDARD_JSON_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; public static final String DB_EXTRACTION_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS"; + public static final long MILLI_SECONDS_FOR_DAY = 24 * 60 * 60 * 1000; + public static final long MINUTES_FOR_DAY = 24 * 60; private DateFormats() {