Skip to content

Filter results at term level and process the calc for pod count#1802

Open
bharathappali wants to merge 3 commits intokruize:mvp_demofrom
bharathappali:add-replicas
Open

Filter results at term level and process the calc for pod count#1802
bharathappali wants to merge 3 commits intokruize:mvp_demofrom
bharathappali:add-replicas

Conversation

@bharathappali
Copy link
Copy Markdown
Member

@bharathappali bharathappali commented Feb 13, 2026

Description

This PR adds the replica information at term level

Fixes #1801

Type of change

  • Bug fix
  • New feature
  • Docs update
  • Breaking change (What changes might users need to make in their application due to this PR?)
  • Requires DB changes

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.

  • New Test X
  • Functional testsuite

Test Configuration

  • Kubernetes clusters tested on:

Checklist 🎯

  • Followed coding guidelines
  • Comments added
  • Dependent changes merged
  • Documentation updated
  • Tests added or updated

Additional information

Include any additional information such as links, test results, screenshots here

Summary by Sourcery

Add term-level replica statistics to recommendation outputs and reuse the time-window-filtered metrics map across recommendation generation.

New Features:

  • Expose term-level replica counts (min, max, avg) in recommendation responses via a new term_replicas field.

Enhancements:

  • Compute pod statistics from filtered interval metrics and pass the filtered results map into model-level recommendation generation instead of recomputing it.
  • Introduce a shared Aggregates enum for max/min/avg and corresponding JSON key for term-level replica data.

@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai bot commented Feb 13, 2026

Reviewer's Guide

Implements term-level replica statistics in the recommendation engine by filtering interval results to the monitoring window, computing pod count aggregates, wiring them into term recommendations, and refactoring model-level recommendation generation to reuse the filtered results. Introduces JSON/constant support for term replica data.

Sequence diagram for term-level replica statistics computation and usage

sequenceDiagram
    participant RecommendationEngine
    participant ContainerData
    participant TermRecommendations
    participant RecommendationModel
    participant IntervalResults
    participant MetricResults
    participant MetricAggregationInfoResults

    RecommendationEngine->>ContainerData: getResults()
    ContainerData-->>RecommendationEngine: Map_Timestamp_IntervalResults_

    RecommendationEngine->>RecommendationEngine: filter results by monitoringStartTime and monitoringEndTime
    Note over RecommendationEngine: filteredResultsMap created

    RecommendationEngine->>RecommendationEngine: getPodStats(filteredResultsMap)
    loop for each IntervalResults in filteredResultsMap
        RecommendationEngine->>IntervalResults: getMetricResultsMap()
        IntervalResults-->>RecommendationEngine: Map_MetricName_MetricResults_

        alt cpuUsage present
            RecommendationEngine->>RecommendationEngine: extractPods(metrics, cpuUsage)
        else memoryUsage present
            RecommendationEngine->>RecommendationEngine: extractPods(metrics, memoryUsage)
        end

        RecommendationEngine->>MetricResults: getAggregationInfoResult()
        MetricResults-->>RecommendationEngine: MetricAggregationInfoResults
        RecommendationEngine->>MetricAggregationInfoResults: getSum(), getAvg()
        MetricAggregationInfoResults-->>RecommendationEngine: sum, avg
        RecommendationEngine->>RecommendationEngine: compute pods = round(sum / avg)
        RecommendationEngine->>RecommendationEngine: update min, max, total, count
    end
    RecommendationEngine->>RecommendationEngine: build Map_Aggregates_Integer_ podStats

    alt podStats not null
        RecommendationEngine->>TermRecommendations: setTermReplicas(podStats)
    end

    loop for each RecommendationModel
        RecommendationEngine->>RecommendationEngine: generateRecommendationBasedOnModel(monitoringStartTime, model, filteredResultsMap, monitoringEndTime, ...)
        Note over RecommendationEngine: reuse filteredResultsMap
    end
Loading

Class diagram for term-level replica stats and related types

classDiagram
    class RecommendationEngine {
        - static int getNumPods(Map_Timestamp_IntervalResults_ filteredResultsMap)
        - static Map_AnalyzerConstants_Aggregates_Integer_ getPodStats(Map_Timestamp_IntervalResults_ filteredResultsMap)
        - static Double extractPods(Map_AnalyzerConstants_MetricName_MetricResults_ metrics, AnalyzerConstants_MetricName metricName)
        + boolean generateRecommendationsBasedOnTerms(ContainerData containerData, KruizeObject kruizeObject)
        + MappedRecommendationForModel generateRecommendationBasedOnModel(Timestamp monitoringStartTime, RecommendationModel model, Map_Timestamp_IntervalResults_ filteredResultsMap, Timestamp monitoringEndTime, KruizeObject kruizeObject, MappedRecommendationForTerm mappedRecommendationForTerm)
    }

    class TermRecommendations {
        - Timestamp monitoringStartTime
        - Map_AnalyzerConstants_Aggregates_Integer_ termReplicas
        - HashMap_String_MappedRecommendationForModel_ recommendationForModelHashMap
        - PlotData_PlotsData_ plots
        + Map_AnalyzerConstants_Aggregates_Integer_ getTermReplicas()
        + void setTermReplicas(Map_AnalyzerConstants_Aggregates_Integer_ termReplicas)
    }

    class AnalyzerConstants {
    }

    class Aggregates {
        <<enumeration>>
        max
        min
        avg
    }

    class KruizeConstants_JSONKeys {
        <<static>> String TERM_REPLICAS
    }

    class MappedRecommendationForModel {
    }

    class MappedRecommendationForTerm {
    }

    class ContainerData {
        + Map_Timestamp_IntervalResults_ getResults()
    }

    class IntervalResults {
        + Map_AnalyzerConstants_MetricName_MetricResults_ getMetricResultsMap()
    }

    class MetricResults {
        + MetricAggregationInfoResults getAggregationInfoResult()
    }

    class MetricAggregationInfoResults {
        + Double getSum()
        + Double getAvg()
    }

    RecommendationEngine --> ContainerData : uses
    RecommendationEngine --> TermRecommendations : populates
    RecommendationEngine --> IntervalResults : uses
    RecommendationEngine --> MetricResults : uses
    RecommendationEngine --> MetricAggregationInfoResults : uses
    RecommendationEngine --> Aggregates : uses

    TermRecommendations ..|> MappedRecommendationForTerm
    TermRecommendations --> MappedRecommendationForModel : contains
    TermRecommendations --> Aggregates : termReplicas

    AnalyzerConstants --> Aggregates : defines
    KruizeConstants_JSONKeys --> TermRecommendations : TERM_REPLICAS key
Loading

File-Level Changes

Change Details Files
Compute pod replica statistics (min/max/avg) from interval metric results and expose them to callers.
  • Add getPodStats helper to scan filtered interval results, derive per-interval pod counts from CPU or memory metric aggregations, and compute min/max/avg across intervals.
  • Add extractPods helper to safely compute pod count as rounded sum/avg from MetricAggregationInfoResults, with null/zero checks.
src/main/java/com/autotune/analyzer/recommendations/engine/RecommendationEngine.java
Filter container results by monitoring window once at term level and reuse this filtered map for both pod calculations and per-model recommendations.
  • At term-level recommendation generation, build filteredResultsMap by constraining containerData.getResults() to timestamps between monitoringStartTime and monitoringEndTime.
  • Pass filteredResultsMap into generateRecommendationBasedOnModel instead of ContainerData so the model-level method can operate directly on the prefiltered data.
  • Remove duplicated filtering logic from generateRecommendationBasedOnModel and rely on the passed-in filteredResultsMap to set numPods via existing getNumPods.
src/main/java/com/autotune/analyzer/recommendations/engine/RecommendationEngine.java
Persist and serialize term-level replica aggregates in recommendation output.
  • Extend TermRecommendations with a termReplicas field keyed by AnalyzerConstants.Aggregates and annotate it with the TERM_REPLICAS JSON key.
  • Provide getters and setters for termReplicas so it can be populated from the engine and serialized in API responses.
  • Introduce AnalyzerConstants.Aggregates enum (max/min/avg) to standardize aggregate keys used for replicas.
  • Add KruizeConstants.JSONKeys.TERM_REPLICAS constant for consistent JSON field naming of term-level replica aggregates.
src/main/java/com/autotune/analyzer/recommendations/objects/TermRecommendations.java
src/main/java/com/autotune/analyzer/utils/AnalyzerConstants.java
src/main/java/com/autotune/utils/KruizeConstants.java
src/main/java/com/autotune/analyzer/recommendations/engine/RecommendationEngine.java

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • In getPodStats, consider initializing maxPods with Double.NEGATIVE_INFINITY instead of Double.MIN_VALUE to better reflect an empty maximum and avoid relying on the subtle semantics of Double.MIN_VALUE (smallest positive value).
  • Both getPodStats and extractPods heavily use boxed Double and return null to signal no data; you could simplify this by using primitives where possible and returning an empty map (or Optional) instead of null to reduce null-handling branches for callers.
  • If termReplicas is expected to always be present in the serialized output, consider initializing it to an empty map rather than leaving it null so consumers don’t have to handle both null and empty cases.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `getPodStats`, consider initializing `maxPods` with `Double.NEGATIVE_INFINITY` instead of `Double.MIN_VALUE` to better reflect an empty maximum and avoid relying on the subtle semantics of `Double.MIN_VALUE` (smallest positive value).
- Both `getPodStats` and `extractPods` heavily use boxed `Double` and return `null` to signal no data; you could simplify this by using primitives where possible and returning an empty map (or Optional) instead of `null` to reduce null-handling branches for callers.
- If `termReplicas` is expected to always be present in the serialized output, consider initializing it to an empty map rather than leaving it `null` so consumers don’t have to handle both `null` and empty cases.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

return null;
}

double minPods = Double.MAX_VALUE;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like minPods and maxPods values are interchanged.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review @kusumachalasani

Fixed it

Signed-off-by: bharathappali <abharath@redhat.com>
Signed-off-by: bharathappali <abharath@redhat.com>
Signed-off-by: bharathappali <abharath@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Under Review

Development

Successfully merging this pull request may close these issues.

3 participants