feat: Add lag/idle plot simulator for cost-based autoscaler - #19687
feat: Add lag/idle plot simulator for cost-based autoscaler#19687kfaraz wants to merge 16 commits into
Conversation
| } | ||
|
|
||
| @GET | ||
| @Path("/{id}/autoscaler") |
There was a problem hiding this comment.
We will rename this API based on what we decide the final result set to look like:
| @Path("/{id}/autoscaler") | |
| @Path("/{id}/autoscaler/simulate") |
| @QueryParam("taskCountMin") int taskCountMin, | ||
| @QueryParam("taskCountMax") int taskCountMax, | ||
| @QueryParam("maxProcessingRatePerTask") int maxProcessingRatePerTask, | ||
| @QueryParam("optimalTaskIdleRatio") double optimalTaskIdleRatio, | ||
| @QueryParam("criticalLag") int criticalLag, |
There was a problem hiding this comment.
Instead of multiple query params, we should just be able to send a POST payload object as a CostBasedAutoScalerConfig.
| @QueryParam("maxProcessingRatePerTask") int maxProcessingRatePerTask, | ||
| @QueryParam("criticalLag") int criticalLag, | ||
| @QueryParam("currentTaskCount") Integer currentTaskCount, | ||
| @Context HttpServletRequest request |
FrankChen021
left a comment
There was a problem hiding this comment.
| Severity | Findings |
|---|---|
| P0 | 0 |
| P1 | 1 |
| P2 | 2 |
| P3 | 0 |
| Total | 3 |
Reviewed 11 of 11 changed files.
This is an automated review by Codex GPT-5.6-Sol
| requestedTaskCount, | ||
| ((SeekableStreamSupervisor<?, ?, ?>) supervisor).getIoConfig().getTaskCount() | ||
| ); | ||
| InvalidInput.conditionalException( |
There was a problem hiding this comment.
[P1] Bound the simulation task counts at the API boundary
The request body can set taskCountMin to zero, which the config constructor accepts; with a positive live task count this reaches computeValidTaskCounts and divides by zero. It can also set an arbitrarily large taskCountMax, which is reused as partitionCount and makes each of the 40 samples scan linearly through that range, allowing an authorized request to monopolize the Overlord CPU. Require a positive minimum and impose a practical maximum before running the simulation.
| ); | ||
|
|
||
| // Assumption: enough partitions to reach taskCountMax. | ||
| final int partitionCount = config.getTaskCountMax(); |
There was a problem hiding this comment.
[P2] Simulate the supervisor's actual topology
The live cost scaler uses supervisor.getPartitionCount() and the supervisor IO config's task duration, but this endpoint substitutes taskCountMax and a hard-coded hour. For example, a two-partition supervisor configured with a maximum of ten is shown recommendations that cannot run, and a custom task duration changes the lag-recovery cost curve. Read both values from the selected supervisor so the chart predicts what its scaler would actually choose.
There was a problem hiding this comment.
It is under user control; let them play.
There was a problem hiding this comment.
These values are not currently user-controlled: the panel/API do not expose partition count or task duration; they derive partition count from taskCountMax and fix duration at 3600 seconds. Thus a two-partition supervisor can still show impossible recommendations up to 10 tasks, and non-hour task durations produce a different curve. Please either read both from the selected supervisor, or expose them as explicit simulator inputs and label the assumptions.
Reviewed 11 of 11 changed files.
| final int lagStepSize = criticalLag / 20; | ||
| final CostBasedAutoScaler autoscaleSimulator = CostBasedAutoScaler.createSimulator(config, supervisorId); | ||
| for (int i = 0; i < 40; ++i) { | ||
| final double observedAggregateLag = lagStepSize * i * 1.0; |
There was a problem hiding this comment.
[P2] Avoid overflowing the generated lag values
lagStepSize * i is evaluated as int before conversion to double. Large but valid criticalLag query values therefore wrap to negative lag in later samples, producing nonsensical task-count recommendations. Promote either operand before multiplying, or keep the calculation in long/double throughout.
FrankChen021
left a comment
There was a problem hiding this comment.
| Severity | Findings |
|---|---|
| P0 | 0 |
| P1 | 0 |
| P2 | 1 |
| P3 | 0 |
| Total | 1 |
The task-count bounds and lag-overflow findings are addressed. A separate inline reply covers the remaining topology-assumption discussion.
Reviewed 11 of 11 changed files.
This is an automated review by Codex GPT-5.6-Sol
| avgProcessingRatePerTask, | ||
| maxProcessingRatePerTask * 1.0 | ||
| ); | ||
| final int optimalTaskCount = autoscaleSimulator.computeOptimalTaskCount(costMetrics); |
There was a problem hiding this comment.
[P2] Suppress production logs for simulation samples
computeOptimalTaskCount emits an INFO metrics line on every call and often a second candidate-table INFO line. This loop calls it 40 times per API request, while the panel issues requests after debounced edits, so ordinary simulator use floods Overlord logs with at least 40 entries per edit. Gate these logs for simulator instances as metrics already are.
There was a problem hiding this comment.
Thanks—the panel's default payload now suppresses the original computation/candidate logs and metrics. One INFO path remains outside !isSimulation at CostBasedAutoScaler.java:380: a positive minCostDropPercentForScaling can still log for simulation samples. Please gate that log too.
Reviewed 11 of 11 changed files.
|
@Fly-Style , there is a merge conflict. Also, the patch currently seems broken. The request being sent by the web-console is a malformed JSON and throws a 400 error. Would you be able to take a look? |
FrankChen021
left a comment
There was a problem hiding this comment.
| Severity | Findings |
|---|---|
| P0 | 0 |
| P1 | 1 |
| P2 | 1 |
| P3 | 0 |
| Total | 2 |
Reviewed 11 of 11 changed files.
This is an automated review by Codex GPT-5.6-Sol
|
@vogievetsky please review :) |
|
Please don't merge this just yet, there are a few more tweaks required in the API. |
FrankChen021
left a comment
There was a problem hiding this comment.
| Severity | Findings |
|---|---|
| P0 | 0 |
| P1 | 0 |
| P2 | 2 |
| P3 | 0 |
| Total | 2 |
Reviewed 11 of 11 changed files. Both prior critical-lag findings are resolved; this update still has read-only authorization and simulation log-volume problems.
This is an automated review by Codex GPT-5.6-Sol
| @Path("/{id}/autoscaler") | ||
| @Consumes(MediaType.APPLICATION_JSON) | ||
| @Produces(MediaType.APPLICATION_JSON) | ||
| @ResourceFilters(SupervisorResourceFilter.class) |
There was a problem hiding this comment.
[P2] Authorize the read-only simulation as READ
SupervisorResourceFilter derives authorization from the HTTP method, so this POST requires DATASOURCE WRITE permission. The endpoint only computes and returns a plot, while the new tab is exposed to users who can view Kafka supervisors; read-only operators therefore see the tab but every simulation request is rejected. Use a READ-specific authorization path or filter for this read-only POST.
| avgProcessingRatePerTask, | ||
| maxProcessingRatePerTask * 1.0 | ||
| ); | ||
| final int optimalTaskCount = autoscaleSimulator.computeOptimalTaskCountInternal(costMetrics, true); |
There was a problem hiding this comment.
[P2] Suppress threshold logs during simulation
Passing true suppresses the main computation log and metrics, but computeOptimalTaskCountInternal still emits INFO messages for every high- or critical-lag point. With the 40-row sweep and the submitted threshold, a single request emits roughly 25 INFO lines, and the UI issues another request after each debounced input change. Guard the high/critical threshold logs with simulation mode as well.
Description
Tuning the lag-based auto-scaler can sometimes be a little involved.
This patch aims to allow making the process simpler by simulating the optimal task count chosen by the auto-scaler under different conditions.
Changes currently in this PR
CostBasedAutoScalerin "simulate" mode and generates the optimal task count for various input values of lag (based on criticalLag)Web-console screenshot
Other required changes
autoscalerConfigmay be sent as payloadautoscalerConfigand vice versataskIdleRatiofield to accept decimal numbers, currently the field resets to integersThis PR has: