Skip to content

Commit

Permalink
Merge pull request #1430 from shekhar316/listExp
Browse files Browse the repository at this point in the history
Fixing ListExperiments API Not Listing Recommendations
  • Loading branch information
chandrams authored Dec 19, 2024
2 parents 9fa48b2 + 271ecb0 commit f6f51f5
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 89 deletions.
162 changes: 83 additions & 79 deletions src/main/java/com/autotune/analyzer/serviceObjects/Converters.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,86 +142,9 @@ public static ListRecommendationsAPIObject convertKruizeObjectToListRecommendati
kubernetesAPIObject = new KubernetesAPIObject(k8sObject.getName(), k8sObject.getType(), k8sObject.getNamespace());
// namespace recommendations experiment type
if (kruizeObject.isNamespaceExperiment()) {
NamespaceAPIObject namespaceAPIObject;
NamespaceData clonedNamespaceData = Utils.getClone(k8sObject.getNamespaceData(), NamespaceData.class);

if (null != clonedNamespaceData) {
HashMap<Timestamp, MappedRecommendationForTimestamp> namespaceRecommendations = clonedNamespaceData.getNamespaceRecommendations().getData();
LOGGER.info("Namespace Recommendations: " + namespaceRecommendations.toString());
clonedNamespaceData.getNamespaceRecommendations().setData(namespaceRecommendations);
namespaceAPIObject = new NamespaceAPIObject(clonedNamespaceData.getNamespace_name(), clonedNamespaceData.getNamespaceRecommendations(), null);
kubernetesAPIObject.setNamespaceAPIObject(namespaceAPIObject);
}
}

HashMap<String, ContainerData> containerDataMap = new HashMap<>();
List<ContainerAPIObject> containerAPIObjects = new ArrayList<>();
for (ContainerData containerData : k8sObject.getContainerDataMap().values()) {
ContainerAPIObject containerAPIObject;
// if a Time stamp is passed it holds the priority than latest
if (checkForTimestamp) {
// This step causes a performance degradation, need to be replaced with a better flow of creating SO's
ContainerData clonedContainerData = Utils.getClone(containerData, ContainerData.class);
if (null != clonedContainerData) {
HashMap<Timestamp, MappedRecommendationForTimestamp> recommendations
= clonedContainerData.getContainerRecommendations().getData();
if (null != monitoringEndTime && recommendations.containsKey(monitoringEndTime)) {
List<Timestamp> tempList = new ArrayList<>();
for (Timestamp timestamp : recommendations.keySet()) {
if (!timestamp.equals(monitoringEndTime))
tempList.add(timestamp);
}
for (Timestamp timestamp : tempList) {
recommendations.remove(timestamp);
}
clonedContainerData.getContainerRecommendations().setData(recommendations);
containerAPIObject = new ContainerAPIObject(clonedContainerData.getContainer_name(),
clonedContainerData.getContainer_image_name(),
clonedContainerData.getContainerRecommendations(),
null);
containerAPIObjects.add(containerAPIObject);
}
}
} else if (getLatest) {
// This step causes a performance degradation, need to be replaced with a better flow of creating SO's
ContainerData clonedContainerData = Utils.getClone(containerData, ContainerData.class);
if (null != clonedContainerData) {
HashMap<Timestamp, MappedRecommendationForTimestamp> recommendations
= clonedContainerData.getContainerRecommendations().getData();
Timestamp latestTimestamp = null;
List<Timestamp> tempList = new ArrayList<>();
for (Timestamp timestamp : recommendations.keySet()) {
if (null == latestTimestamp) {
latestTimestamp = timestamp;
} else {
if (timestamp.after(latestTimestamp)) {
tempList.add(latestTimestamp);
latestTimestamp = timestamp;
} else {
tempList.add(timestamp);
}
}
}
for (Timestamp timestamp : tempList) {
recommendations.remove(timestamp);
}
clonedContainerData.getContainerRecommendations().setData(recommendations);
containerAPIObject = new ContainerAPIObject(clonedContainerData.getContainer_name(),
clonedContainerData.getContainer_image_name(),
clonedContainerData.getContainerRecommendations(),
null);
containerAPIObjects.add(containerAPIObject);
}
} else {
containerAPIObject = new ContainerAPIObject(containerData.getContainer_name(),
containerData.getContainer_image_name(),
containerData.getContainerRecommendations(),
null);
containerAPIObjects.add(containerAPIObject);
containerDataMap.put(containerData.getContainer_name(), containerData);
}
processNamespaceRecommendations(k8sObject, kubernetesAPIObject, checkForTimestamp, getLatest, monitoringEndTime);
}
kubernetesAPIObject.setContainerAPIObjects(containerAPIObjects);
processContainerRecommendations(k8sObject, kubernetesAPIObject, checkForTimestamp, getLatest, monitoringEndTime);
kubernetesAPIObjects.add(kubernetesAPIObject);
}
listRecommendationsAPIObject.setKubernetesObjects(kubernetesAPIObjects);
Expand All @@ -231,6 +154,87 @@ public static ListRecommendationsAPIObject convertKruizeObjectToListRecommendati
return listRecommendationsAPIObject;
}

private static void processNamespaceRecommendations(K8sObject k8sObject, KubernetesAPIObject kubernetesAPIObject,
boolean checkForTimestamp, boolean getLatest, Timestamp monitoringEndTime) {
NamespaceData clonedNamespaceData = Utils.getClone(k8sObject.getNamespaceData(), NamespaceData.class);
if (clonedNamespaceData != null) {
HashMap<Timestamp, MappedRecommendationForTimestamp> namespaceRecommendations = clonedNamespaceData.getNamespaceRecommendations().getData();

if (checkForTimestamp) {
filterRecommendationsByTimestamp(namespaceRecommendations, monitoringEndTime);
} else if (getLatest) {
filterRecommendationsByLatest(namespaceRecommendations);
}

NamespaceAPIObject namespaceAPIObject = new NamespaceAPIObject(
clonedNamespaceData.getNamespace_name(),
clonedNamespaceData.getNamespaceRecommendations(),
null);
kubernetesAPIObject.setNamespaceAPIObject(namespaceAPIObject);
}
}

private static void processContainerRecommendations(K8sObject k8sObject, KubernetesAPIObject kubernetesAPIObject,
boolean checkForTimestamp, boolean getLatest, Timestamp monitoringEndTime) {
List<ContainerAPIObject> containerAPIObjects = new ArrayList<>();

for (ContainerData containerData : k8sObject.getContainerDataMap().values()) {
ContainerData clonedContainerData = Utils.getClone(containerData, ContainerData.class);

if (clonedContainerData != null) {
HashMap<Timestamp, MappedRecommendationForTimestamp> recommendations = clonedContainerData.getContainerRecommendations().getData();

if (checkForTimestamp) {
filterRecommendationsByTimestamp(recommendations, monitoringEndTime);
} else if (getLatest) {
filterRecommendationsByLatest(recommendations);
}

ContainerAPIObject containerAPIObject = new ContainerAPIObject(
clonedContainerData.getContainer_name(),
clonedContainerData.getContainer_image_name(),
clonedContainerData.getContainerRecommendations(),
null);
containerAPIObjects.add(containerAPIObject);
} else {
containerAPIObjects.add(new ContainerAPIObject(
containerData.getContainer_name(),
containerData.getContainer_image_name(),
containerData.getContainerRecommendations(),
null));
}
}

kubernetesAPIObject.setContainerAPIObjects(containerAPIObjects);
}

private static void filterRecommendationsByTimestamp(HashMap<Timestamp, MappedRecommendationForTimestamp> recommendations,
Timestamp monitoringEndTime) {
if (monitoringEndTime != null && recommendations.containsKey(monitoringEndTime)) {
recommendations.keySet().removeIf(timestamp -> !timestamp.equals(monitoringEndTime));
}
}

private static void filterRecommendationsByLatest(HashMap<Timestamp, MappedRecommendationForTimestamp> recommendations) {
Timestamp latestTimestamp = null;
List<Timestamp> timestampsToRemove = new ArrayList<>();

for (Timestamp timestamp : recommendations.keySet()) {
if (latestTimestamp == null || timestamp.after(latestTimestamp)) {
if (latestTimestamp != null) {
timestampsToRemove.add(latestTimestamp);
}
latestTimestamp = timestamp;
} else {
timestampsToRemove.add(timestamp);
}
}

for (Timestamp timestamp : timestampsToRemove) {
recommendations.remove(timestamp);
}
}

/**
* @param containerData
*/
Expand Down
36 changes: 26 additions & 10 deletions src/main/java/com/autotune/analyzer/services/ListExperiments.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.autotune.common.data.metrics.MetricResults;
import com.autotune.common.data.result.ContainerData;
import com.autotune.common.data.result.IntervalResults;
import com.autotune.common.data.result.NamespaceData;
import com.autotune.common.data.system.info.device.DeviceDetails;
import com.autotune.common.k8sObjects.K8sObject;
import com.autotune.common.target.kubernetes.service.KubernetesServices;
Expand Down Expand Up @@ -85,6 +86,15 @@ private static List<K8sObject> convertKubernetesAPIObjectListToK8sObjectList(Lis
containerDataMap.put(containerAPIObject.getContainer_name(), containerData);
}
k8sObject.setContainerDataMap(containerDataMap);

// adding namespace recommendations to K8sObject
NamespaceData namespaceData = new NamespaceData();
if (kubernetesAPIObject.getNamespaceAPIObjects() != null && kubernetesAPIObject.getNamespaceAPIObjects().getnamespaceRecommendations() != null) {
namespaceData.setNamespace_name(kubernetesAPIObject.getNamespace());
namespaceData.setNamespaceRecommendations(kubernetesAPIObject.getNamespaceAPIObjects().getnamespaceRecommendations());
k8sObject.setNamespaceData(namespaceData);
}

k8sObjectList.add(k8sObject);
}
return k8sObjectList;
Expand Down Expand Up @@ -181,7 +191,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t
Gson gsonObj = createGsonObject();

// Modify the JSON response here based on query params.
gsonStr = buildResponseBasedOnQuery(mKruizeExperimentMap, gsonObj, results, recommendations, latest, experimentName);
gsonStr = buildResponseBasedOnQuery(mKruizeExperimentMap, gsonObj, results, recommendations, latest, experimentName, rmTable);
if (gsonStr.isEmpty()) {
gsonStr = generateDefaultResponse();
}
Expand Down Expand Up @@ -364,7 +374,7 @@ private void checkPercentileInfo(Map<String, KruizeObject> mainKruizeExperimentM
}

private String buildResponseBasedOnQuery(Map<String, KruizeObject> mKruizeExperimentMap, Gson gsonObj, String results,
String recommendations, String latest, String experimentName) {
String recommendations, String latest, String experimentName, boolean rmTable) {
// Case : default
// return the response without results or recommendations
if (results.equalsIgnoreCase(AnalyzerConstants.BooleanString.FALSE) && recommendations.equalsIgnoreCase(AnalyzerConstants.BooleanString.FALSE)) {
Expand All @@ -376,7 +386,7 @@ private String buildResponseBasedOnQuery(Map<String, KruizeObject> mKruizeExperi
AnalyzerConstants.BooleanString.TRUE)) {
// Case: results=true , recommendations=true
// fetch results and recomm. from the DB
loadRecommendations(mKruizeExperimentMap, experimentName);
loadRecommendations(mKruizeExperimentMap, experimentName, rmTable);
buildRecommendationsResponse(mKruizeExperimentMap, latest);
loadResults(mKruizeExperimentMap, experimentName);

Expand All @@ -398,7 +408,7 @@ private String buildResponseBasedOnQuery(Map<String, KruizeObject> mKruizeExperi
return gsonObj.toJson(new ArrayList<>(mKruizeExperimentMap.values()));
} else {
// Case: results=false , recommendations=true
loadRecommendations(mKruizeExperimentMap, experimentName);
loadRecommendations(mKruizeExperimentMap, experimentName, rmTable);
buildRecommendationsResponse(mKruizeExperimentMap, latest);
return gsonObj.toJson(new ArrayList<>(mKruizeExperimentMap.values()));
}
Expand All @@ -421,13 +431,19 @@ private void loadResults(Map<String, KruizeObject> mKruizeExperimentMap, String
}
}

private void loadRecommendations(Map<String, KruizeObject> mKruizeExperimentMap, String experimentName) {
private void loadRecommendations(Map<String, KruizeObject> mKruizeExperimentMap, String experimentName, boolean rmTable) {
try {
if (experimentName == null || experimentName.isEmpty())
new ExperimentDBService().loadAllRecommendations(mKruizeExperimentMap);
else
new ExperimentDBService().loadRecommendationsFromDBByName(mKruizeExperimentMap, experimentName);

if (rmTable) {
if (experimentName == null || experimentName.isEmpty())
new ExperimentDBService().loadAllRecommendations(mKruizeExperimentMap);
else
new ExperimentDBService().loadRecommendationsFromDBByName(mKruizeExperimentMap, experimentName);
} else {
if (experimentName == null || experimentName.isEmpty())
new ExperimentDBService().loadAllLMRecommendations(mKruizeExperimentMap);
else
new ExperimentDBService().loadLMRecommendationsFromDBByName(mKruizeExperimentMap, experimentName);
}
} catch (Exception e) {
LOGGER.error("Failed to load saved recommendations data: {} ", e.getMessage());
}
Expand Down

0 comments on commit f6f51f5

Please sign in to comment.