-
Notifications
You must be signed in to change notification settings - Fork 62
Add Layers core data structure for runtimes - PR 1 #1716
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: mvp_demo
Are you sure you want to change the base?
Conversation
bharathappali
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs some changes related to copyrights comment and some abstractions
| @@ -0,0 +1,125 @@ | |||
| package com.autotune.analyzer.kruizeLayer; | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR @bhanvimenghani
Please kindly add the copyrights comment as this is a new file.
| // For query-based detection | ||
| private String datasource; | ||
| private String query; | ||
| private String key; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is key required?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The key has same value for all queries. But this was mentioned in the reference yaml hence i added it https://github.com/kruize/autotune/blob/master/manifests/autotune/autotune-configs/hotspot-micrometer-config.yaml
| private String query; | ||
| private String key; | ||
|
|
||
| // For label-based detection |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel this class would be populating either a datasource, query attributes or the name and value attributes. Would it be a good idea to maintain an interface which holds the getType which can either be a query based implementation or a label based implementation, so that we can create a particular class implementation based on the type, rather than deciding at runtime by check if certain attributes are null.
Please let me know your thoughts on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, we can have an interface, just thinking if i should create a separate pr for it so that this one does not gets too long.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah a adding changes in a new PR makes more sense. Will approve this one and we can make changes on top of it
| @@ -0,0 +1,82 @@ | |||
| package com.autotune.analyzer.kruizeLayer; | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please kindly add the copyright comment.
| @@ -0,0 +1,21 @@ | |||
| package com.autotune.analyzer.kruizeLayer; | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please kindly add the copyright comment.
|
|
||
|
|
||
| public class LayerMetadata { | ||
| private String name; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see a high level field name in the Layer class, Are both these names the same?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes both metadata > name and layer_name have the same value I am following this yaml to create the fields https://github.com/kruize/autotune/blob/master/manifests/autotune/autotune-configs/openj9-actuator-config.yaml
| @@ -0,0 +1,63 @@ | |||
| package com.autotune.analyzer.kruizeLayer; | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please kindly add the copyright comment.
| @@ -0,0 +1,88 @@ | |||
| package com.autotune.analyzer.kruizeLayer; | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please kindly add the copyright comment.
bharathappali
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed to add the structural changes as a different PR, LGTM
|
@sourcery-ai review |
Reviewer's GuideIntroduces a new generic Kruize Layer core model with metadata, presence detection, and tunable definitions to support runtime-agnostic layer configuration, including detectors for both label- and query-based discovery. Class diagram for new Kruize Layer core data modelclassDiagram
class Layer {
+String apiVersion
+String kind
+LayerMetadata metadata
+String name
+String layerName
+Integer layerLevel
+String details
+LayerPresence layerPresence
+List~LayerTunable~ tunables
+Layer()
+Layer(apiVersion String, kind String, metadata LayerMetadata, layerPresence LayerPresence, tunables List~LayerTunable~)
+String getApiVersion()
+void setApiVersion(apiVersion String)
+String getKind()
+void setKind(kind String)
+LayerMetadata getMetadata()
+void setMetadata(metadata LayerMetadata)
+LayerPresence getLayerPresence()
+void setLayerPresence(layerPresence LayerPresence)
+List~LayerTunable~ getTunables()
+void setTunables(tunables List~LayerTunable~)
+String getName()
+void setName(name String)
+String getLayerName()
+void setLayerName(layerName String)
+Integer getLayerLevel()
+void setLayerLevel(layerLevel Integer)
+String getDetails()
+void setDetails(details String)
+String toString()
}
class LayerMetadata {
+String name
+String getName()
+void setName(name String)
+String toString()
}
class LayerPresence {
+String presence
+List~LayerDetector~ labels
+List~LayerDetector~ queries
+LayerPresence()
+String getPresence()
+void setPresence(presence String)
+List~LayerDetector~ getLabels()
+void setLabels(labels List~LayerDetector~)
+List~LayerDetector~ getQueries()
+void setQueries(queries List~LayerDetector~)
+List~LayerDetector~ getActiveDetectors()
+String toString()
}
class LayerDetector {
+String datasource
+String query
+String key
+String name
+String value
+LayerDetector()
+LayerDetector(datasource String, query String, key String)
+LayerDetector(name String, value String)
+String getDatasource()
+void setDatasource(datasource String)
+String getQuery()
+void setQuery(query String)
+String getKey()
+void setKey(key String)
+String getName()
+void setName(name String)
+String getValue()
+void setValue(value String)
+String toString()
}
class LayerTunable {
+String name
+String description
+String valueType
+List~String~ choices
+String upperBound
+String lowerBound
+Double step
+String getName()
+void setName(name String)
+String getDescription()
+void setDescription(description String)
+String getValueType()
+void setValueType(valueType String)
+List~String~ getChoices()
+void setChoices(choices List~String~)
+String getUpperBound()
+void setUpperBound(upperBound String)
+String getLowerBound()
+void setLowerBound(lowerBound String)
+Double getStep()
+void setStep(step Double)
+String toString()
}
Layer "1" --> "1" LayerMetadata : has
Layer "1" --> "1" LayerPresence : has
Layer "1" --> "*" LayerTunable : defines
LayerPresence "1" --> "*" LayerDetector : labels
LayerPresence "1" --> "*" LayerDetector : queries
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey there - I've reviewed your changes - here's some feedback:
- In
Layer, there are multiple fields that represent a name (name,layerName, andmetadata.name); consider consolidating or clearly distinguishing their responsibilities to avoid ambiguity and inconsistent usage later. - The
LayerDetectorclass mixes query-based and label-based detection fields in a single type; introducing an explicit discriminator (e.g., an enum detector type or separate subclasses) would make it harder to create invalid combinations and simplify downstream logic. - In
LayerPresence#getActiveDetectors, consider returningCollections.emptyList()instead of allocating a newArrayListon the empty case to reduce unnecessary allocations.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `Layer`, there are multiple fields that represent a name (`name`, `layerName`, and `metadata.name`); consider consolidating or clearly distinguishing their responsibilities to avoid ambiguity and inconsistent usage later.
- The `LayerDetector` class mixes query-based and label-based detection fields in a single type; introducing an explicit discriminator (e.g., an enum detector type or separate subclasses) would make it harder to create invalid combinations and simplify downstream logic.
- In `LayerPresence#getActiveDetectors`, consider returning `Collections.emptyList()` instead of allocating a new `ArrayList` on the empty case to reduce unnecessary allocations.
## Individual Comments
### Comment 1
<location> `src/main/java/com/autotune/analyzer/kruizeLayer/Layer.java:24` </location>
<code_context>
+ private String details;
+ @SerializedName("layer_presence")
+ private LayerPresence layerPresence;
+ private List<LayerTunable> tunables;
+
+
</code_context>
<issue_to_address>
**suggestion:** Consider default-initializing `tunables` to an empty list to reduce null-handling overhead.
As it stands, `tunables` may be `null` when using the no-arg constructor or when deserialization omits the field, forcing callers to add null checks before iterating or adding elements. Initializing it to `Collections.emptyList()` or a mutable empty list (if mutation is expected) makes the type safer to consume and avoids this extra defensive code.
Suggested implementation:
```java
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
```
```java
@SerializedName("layer_level")
private Integer layerLevel;
private String details;
@SerializedName("layer_presence")
private LayerPresence layerPresence;
private List<LayerTunable> tunables = new ArrayList<>();
```
</issue_to_address>
### Comment 2
<location> `src/main/java/com/autotune/analyzer/kruizeLayer/LayerPresence.java:61-68` </location>
<code_context>
+ * Returns the active list of detectors regardless of whether
+ * they came from 'label' or 'queries'.
+ */
+ public List<LayerDetector> getActiveDetectors() {
+ if (labels != null && !labels.isEmpty()) {
+ return labels;
+ }
+ if (queries != null && !queries.isEmpty()) {
+ return queries;
+ }
+ return new java.util.ArrayList<>(); // Return empty list to prevent NullPointerExceptions
+ }
+
</code_context>
<issue_to_address>
**suggestion:** Align `getActiveDetectors` behavior and consider returning an unmodifiable or shared empty list.
Currently, when `labels`/`queries` are non-empty you return the backing list, but when both are empty you return a new mutable list unrelated to the object’s state. That semantic mismatch can be confusing. Consider returning `Collections.emptyList()` (or another unmodifiable view) to avoid extra allocations and make it clear the result should be treated as read-only and not used for in-place updates.
Suggested implementation:
```java
import com.google.gson.annotations.SerializedName;
import java.util.Collections;
import java.util.List;
```
```java
/**
* Returns the active list of detectors regardless of whether
* they came from 'label' or 'queries'.
* <p>
* When no detectors are present, this returns a shared, unmodifiable empty list.
*/
public List<LayerDetector> getActiveDetectors() {
if (labels != null && !labels.isEmpty()) {
return labels;
}
if (queries != null && !queries.isEmpty()) {
return queries;
}
// Return a shared unmodifiable empty list to avoid allocations and clarify read-only semantics
return Collections.emptyList();
}
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| public List<LayerDetector> getActiveDetectors() { | ||
| if (labels != null && !labels.isEmpty()) { | ||
| return labels; | ||
| } | ||
| if (queries != null && !queries.isEmpty()) { | ||
| return queries; | ||
| } | ||
| return new java.util.ArrayList<>(); // Return empty list to prevent NullPointerExceptions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Align getActiveDetectors behavior and consider returning an unmodifiable or shared empty list.
Currently, when labels/queries are non-empty you return the backing list, but when both are empty you return a new mutable list unrelated to the object’s state. That semantic mismatch can be confusing. Consider returning Collections.emptyList() (or another unmodifiable view) to avoid extra allocations and make it clear the result should be treated as read-only and not used for in-place updates.
Suggested implementation:
import com.google.gson.annotations.SerializedName;
import java.util.Collections;
import java.util.List; /**
* Returns the active list of detectors regardless of whether
* they came from 'label' or 'queries'.
* <p>
* When no detectors are present, this returns a shared, unmodifiable empty list.
*/
public List<LayerDetector> getActiveDetectors() {
if (labels != null && !labels.isEmpty()) {
return labels;
}
if (queries != null && !queries.isEmpty()) {
return queries;
}
// Return a shared unmodifiable empty list to avoid allocations and clarify read-only semantics
return Collections.emptyList();
}
Description
This PR introduces the foundational Layer data structure for Kruize's runtime recommendations feature.
New Layer Core Components
Removed old layer implementations. These are replaced by the new generic Layer data structure that can represent any layer type through configuration.
Fixes # (issue)
Type of change
How has this been tested?
Please describe the tests that were run to verify your changes and steps to reproduce. Please specify any test configuration required.
Test Configuration
Checklist 🎯
Additional information
Include any additional information such as links, test results, screenshots here
Summary by Sourcery
Introduce a new core data model for Kruize layers to support configurable runtime layer definitions and tunables.
New Features: