This is an automated email from the ASF dual-hosted git repository.

kfaraz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git


The following commit(s) were added to refs/heads/master by this push:
     new 9c26bb75430 minor: Add metrics to costBased auto-scaler (#19631)
9c26bb75430 is described below

commit 9c26bb75430dd2e853d666ba67707647e61f392e
Author: Kashif Faraz <[email protected]>
AuthorDate: Fri Jun 26 15:03:14 2026 +0530

    minor: Add metrics to costBased auto-scaler (#19631)
    
    Changes
    ---------
    - Add metric `task/autoScaler/costBased/avgProcessingRate`
    - Add metric `task/autoScaler/costBased/avgPollIdleRatio`
    - Add metric `task/autoScaler/costBased/lagWeight`
    - Add metric `task/autoScaler/costBased/costWeight`
    - Remove metric `task/autoScaler/costBased/lagCost`
    - Remove metric `task/autoScaler/costBased/idleCost`
    - Minor cleanup
---
 docs/ingestion/supervisor.md                       |  2 --
 docs/operations/metrics.md                         |  6 ++--
 .../supervisor/autoscaler/CostBasedAutoScaler.java | 16 +++++++----
 .../autoscaler/CostBasedAutoScalerConfig.java      | 32 +++++++---------------
 .../autoscaler/CostBasedAutoScalerConfigTest.java  | 12 ++++----
 5 files changed, 30 insertions(+), 38 deletions(-)

diff --git a/docs/ingestion/supervisor.md b/docs/ingestion/supervisor.md
index 4579532e09d..b642aefec45 100644
--- a/docs/ingestion/supervisor.md
+++ b/docs/ingestion/supervisor.md
@@ -204,8 +204,6 @@ The sweet spot is roughly 25% idle, giving headroom to 
absorb traffic spikes wit
 
 At every evaluation interval, Druid computes the score for each candidate task 
count and picks the one with the lowest total cost.
 
-Note: Kinesis is not supported yet, support is in progress.
-
 The following table outlines the configuration properties related to the 
`costBased` autoscaler strategy:
 
 | Property | Description | Required | Default                   |
diff --git a/docs/operations/metrics.md b/docs/operations/metrics.md
index 31c6813be6c..4ce8e85061f 100644
--- a/docs/operations/metrics.md
+++ b/docs/operations/metrics.md
@@ -318,8 +318,10 @@ batch ingestion emit the following metrics. These metrics 
are deltas for each em
 |`task/autoScaler/requiredCount`|Count of required tasks based on the 
calculations of the auto scaler.|`supervisorId`, `dataSource`, `stream`, 
`scalingSkipReason`|Depends on auto scaler config.|
 |`task/autoScaler/scaleActionTime`|Time taken in milliseconds to complete the 
scale action.|`supervisorId`, `dataSource`, `stream`, `tags`|Depends on auto 
scaler config.|
 |`task/autoScaler/costBased/optimalTaskCount`|Optimal task count computed by 
the cost-based auto scaler.|`supervisorId`, `dataSource`, `stream`|Depends on 
auto scaler config.|
-|`task/autoScaler/costBased/lagCost`|Lag cost component of the cost-based auto 
scaler's cost function.|`supervisorId`, `dataSource`, `stream`|Depends on auto 
scaler config.|
-|`task/autoScaler/costBased/idleCost`|Idle cost component of the cost-based 
auto scaler's cost function.|`supervisorId`, `dataSource`, `stream`|Depends on 
auto scaler config.|
+|`task/autoScaler/costBased/lagWeight`|Lag weight used in the cost function 
for the auto scaler.|`supervisorId`, `dataSource`, `stream`|Depends on auto 
scaler config.|
+|`task/autoScaler/costBased/idleWeight`|Idle weight used in the cost function 
for the auto scaler.|`supervisorId`, `dataSource`, `stream`|Depends on auto 
scaler config.|
+|`task/autoScaler/costBased/avgProcessingRate`|Windowed average rate of 
processing records across all tasks in the supervisor.|`supervisorId`, 
`dataSource`, `stream`|Depends on rate of incoming data and processing capacity 
of the tasks.|
+|`task/autoScaler/costBased/avgPollIdleRatio`|Poll-to-idle-ratio as reported 
by the streaming consumer averaged across all tasks in the supervisor. 
Currently supported only with Kafka supervisors.|`supervisorId`, `dataSource`, 
`stream`|0 if the consumer is never idle, 1 if the consumer is always idle, -1 
if ratio is not available.|
 
 If the JVM does not support CPU time measurement for the current thread, 
`ingest/merge/cpu` and `ingest/persists/cpu` will be 0.
 
diff --git 
a/indexing-service/src/main/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScaler.java
 
b/indexing-service/src/main/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScaler.java
index 7dc9dd0c2d6..32efeadd4c7 100644
--- 
a/indexing-service/src/main/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScaler.java
+++ 
b/indexing-service/src/main/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScaler.java
@@ -61,10 +61,12 @@ public class CostBasedAutoScaler implements 
SupervisorTaskAutoScaler
 {
   private static final EmittingLogger log = new 
EmittingLogger(CostBasedAutoScaler.class);
 
-  public static final String LAG_COST_METRIC = 
"task/autoScaler/costBased/lagCost";
-  public static final String IDLE_COST_METRIC = 
"task/autoScaler/costBased/idleCost";
+  public static final String LAG_WEIGHT_METRIC = 
"task/autoScaler/costBased/lagWeight";
+  public static final String IDLE_WEIGHT_METRIC = 
"task/autoScaler/costBased/idleWeight";
   public static final String OPTIMAL_TASK_COUNT_METRIC = 
"task/autoScaler/costBased/optimalTaskCount";
   public static final String INVALID_METRICS_COUNT = 
"task/autoScaler/costBased/invalidMetrics";
+  public static final String AVG_PROCESSING_RATE_METRIC = 
"task/autoScaler/costBased/avgProcessingRate";
+  public static final String AVG_POLL_IDLE_RATIO = 
"task/autoScaler/costBased/avgPollIdleRatio";
 
   /**
    * Maximum number of candidate task counts to evaluate above or below the 
current task count
@@ -255,14 +257,14 @@ public class CostBasedAutoScaler implements 
SupervisorTaskAutoScaler
     int startIndex = 0;
     int endIndex = validTaskCounts.length - 1;
 
-    if (config.shouldUseTaskCountBoundariesOnScaleUp()) {
+    if (config.isUseTaskCountBoundariesOnScaleUp()) {
       int currentTaskCountIndex = Arrays.binarySearch(validTaskCounts, 
currentTaskCount);
       endIndex = currentTaskCountIndex >= 0
                  ? Math.min(currentTaskCountIndex + 
BOUNDARY_LIMIT_IN_PARTITIONS_PER_TASK, endIndex)
                  : endIndex;
     }
 
-    if (config.shouldUseTaskCountBoundariesOnScaleDown()) {
+    if (config.isUseTaskCountBoundariesOnScaleDown()) {
       int currentTaskCountIndex = Arrays.binarySearch(validTaskCounts, 
currentTaskCount);
       startIndex = currentTaskCountIndex >= 0
                    ? Math.max(currentTaskCountIndex - 
BOUNDARY_LIMIT_IN_PARTITIONS_PER_TASK, startIndex)
@@ -282,8 +284,10 @@ public class CostBasedAutoScaler implements 
SupervisorTaskAutoScaler
     }
 
     emitter.emit(getMetricBuilder().setMetric(OPTIMAL_TASK_COUNT_METRIC, 
(long) optimalTaskCount));
-    emitter.emit(getMetricBuilder().setMetric(LAG_COST_METRIC, 
optimalCost.lagCost()));
-    emitter.emit(getMetricBuilder().setMetric(IDLE_COST_METRIC, 
optimalCost.idleCost()));
+    emitter.emit(getMetricBuilder().setMetric(LAG_WEIGHT_METRIC, 
optimalCost.lagCost()));
+    emitter.emit(getMetricBuilder().setMetric(IDLE_WEIGHT_METRIC, 
optimalCost.idleCost()));
+    emitter.emit(getMetricBuilder().setMetric(AVG_PROCESSING_RATE_METRIC, 
metrics.getAvgProcessingRate()));
+    emitter.emit(getMetricBuilder().setMetric(AVG_POLL_IDLE_RATIO, 
metrics.getPollIdleRatio()));
 
     if (optimalTaskCount != currentTaskCount) {
       log.info(
diff --git 
a/indexing-service/src/main/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScalerConfig.java
 
b/indexing-service/src/main/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScalerConfig.java
index 68f9f5a5ad7..7987c935b8e 100644
--- 
a/indexing-service/src/main/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScalerConfig.java
+++ 
b/indexing-service/src/main/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScalerConfig.java
@@ -85,8 +85,6 @@ public class CostBasedAutoScalerConfig implements 
AutoScalerConfig
       @Nullable @JsonProperty("scaleActionPeriodMillis") Long 
scaleActionPeriodMillis,
       @Nullable @JsonProperty("lagWeight") Double lagWeight,
       @Nullable @JsonProperty("idleWeight") Double idleWeight,
-      @Nullable @JsonProperty("useTaskCountBoundaries") Boolean 
useTaskCountBoundaries,
-      @Nullable @JsonProperty("highLagThreshold") Integer highLagThreshold,
       @Nullable @JsonProperty("useTaskCountBoundariesOnScaleUp") Boolean 
useTaskCountBoundariesOnScaleUp,
       @Nullable @JsonProperty("useTaskCountBoundariesOnScaleDown") Boolean 
useTaskCountBoundariesOnScaleDown,
       @Nullable @JsonProperty("minScaleUpDelay") Duration minScaleUpDelay,
@@ -118,14 +116,6 @@ public class CostBasedAutoScalerConfig implements 
AutoScalerConfig
     this.scaleDownDuringTaskRolloverOnly = 
Configs.valueOrDefault(scaleDownDuringTaskRolloverOnly, false);
 
     if (this.enableTaskAutoScaler) {
-      if (useTaskCountBoundaries != null) {
-        LOG.warn("useTaskCountBoundaries is removed, "
-                 + "use useTaskCountBoundariesOnScaleUp and 
useTaskCountBoundariesOnScaleDown instead");
-      }
-      if (highLagThreshold != null) {
-        LOG.warn("highLagThreshold is removed, the autoscaler behavior is good 
enough just with cost function");
-      }
-
       Preconditions.checkNotNull(taskCountMax, "taskCountMax is required when 
enableTaskAutoScaler is true");
       Preconditions.checkNotNull(taskCountMin, "taskCountMin is required when 
enableTaskAutoScaler is true");
       Preconditions.checkArgument(taskCountMax >= taskCountMin, "taskCountMax 
must be >= taskCountMin");
@@ -231,23 +221,23 @@ public class CostBasedAutoScalerConfig implements 
AutoScalerConfig
   }
 
   /**
-   * Enables or disables the task-count evaluation window when considering 
scale-up candidates.
-   * If enabled, the optimizer only evaluates a small number of candidate task 
counts above the current count,
-   * which prevents large scale-up jumps.
+   * If true, the auto-scaler evaluates a small number of candidate task counts
+   * (dictated by {@link 
CostBasedAutoScaler#BOUNDARY_LIMIT_IN_PARTITIONS_PER_TASK})
+   * above the current count, which prevents large scale-up jumps.
    */
-  @JsonProperty("useTaskCountBoundariesOnScaleUp")
-  public boolean shouldUseTaskCountBoundariesOnScaleUp()
+  @JsonProperty
+  public boolean isUseTaskCountBoundariesOnScaleUp()
   {
     return useTaskCountBoundariesOnScaleUp;
   }
 
   /**
-   * Enables or disables the task-count evaluation window when considering 
scale-down candidates.
-   * If enabled, the optimizer only evaluates a small number of candidate task 
counts below the current count,
-   * which prevents large scale-down drops.
+   * If true, the auto-scaler evaluates a small number of candidate task counts
+   * (dictated by {@link 
CostBasedAutoScaler#BOUNDARY_LIMIT_IN_PARTITIONS_PER_TASK})
+   * below the current count, which prevents large scale-down drops.
    */
-  @JsonProperty("useTaskCountBoundariesOnScaleDown")
-  public boolean shouldUseTaskCountBoundariesOnScaleDown()
+  @JsonProperty
+  public boolean isUseTaskCountBoundariesOnScaleDown()
   {
     return useTaskCountBoundariesOnScaleDown;
   }
@@ -479,8 +469,6 @@ public class CostBasedAutoScalerConfig implements 
AutoScalerConfig
           scaleActionPeriodMillis,
           lagWeight,
           idleWeight,
-          null,
-          null,
           useTaskCountBoundariesOnScaleUp,
           useTaskCountBoundariesOnScaleDown,
           minScaleUpDelay,
diff --git 
a/indexing-service/src/test/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScalerConfigTest.java
 
b/indexing-service/src/test/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScalerConfigTest.java
index 4755b3cf496..5a1c6ec98fc 100644
--- 
a/indexing-service/src/test/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScalerConfigTest.java
+++ 
b/indexing-service/src/test/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScalerConfigTest.java
@@ -67,8 +67,8 @@ public class CostBasedAutoScalerConfigTest
     Assert.assertEquals(Duration.standardMinutes(5), 
config.getMinScaleUpDelay());
     Assert.assertEquals(Duration.standardMinutes(10), 
config.getMinScaleDownDelay());
     Assert.assertTrue(config.isScaleDownOnTaskRolloverOnly());
-    Assert.assertFalse(config.shouldUseTaskCountBoundariesOnScaleUp());
-    Assert.assertTrue(config.shouldUseTaskCountBoundariesOnScaleDown());
+    Assert.assertFalse(config.isUseTaskCountBoundariesOnScaleUp());
+    Assert.assertTrue(config.isUseTaskCountBoundariesOnScaleDown());
 
     // Test serialization back to JSON
     String serialized = mapper.writeValueAsString(config);
@@ -101,8 +101,8 @@ public class CostBasedAutoScalerConfigTest
     Assert.assertEquals(Duration.millis(DEFAULT_SCALE_ACTION_PERIOD_MILLIS), 
config.getMinScaleUpDelay());
     Assert.assertEquals(DEFAULT_MIN_SCALE_DELAY, 
config.getMinScaleDownDelay());
     Assert.assertFalse(config.isScaleDownOnTaskRolloverOnly());
-    Assert.assertFalse(config.shouldUseTaskCountBoundariesOnScaleUp());
-    Assert.assertTrue(config.shouldUseTaskCountBoundariesOnScaleDown());
+    Assert.assertFalse(config.isUseTaskCountBoundariesOnScaleUp());
+    Assert.assertTrue(config.isUseTaskCountBoundariesOnScaleDown());
     Assert.assertNull(config.getTaskCountStart());
     Assert.assertNull(config.getStopTaskCountRatio());
   }
@@ -200,8 +200,8 @@ public class CostBasedAutoScalerConfigTest
     Assert.assertEquals(60000L, config.getScaleActionPeriodMillis());
     Assert.assertEquals(0.6, config.getLagWeight(), 0.001);
     Assert.assertEquals(0.4, config.getIdleWeight(), 0.001);
-    Assert.assertTrue(config.shouldUseTaskCountBoundariesOnScaleUp());
-    Assert.assertTrue(config.shouldUseTaskCountBoundariesOnScaleDown());
+    Assert.assertTrue(config.isUseTaskCountBoundariesOnScaleUp());
+    Assert.assertTrue(config.isUseTaskCountBoundariesOnScaleDown());
     Assert.assertEquals(Duration.standardMinutes(5), 
config.getMinScaleUpDelay());
     Assert.assertEquals(Duration.standardMinutes(10), 
config.getMinScaleDownDelay());
     Assert.assertTrue(config.isScaleDownOnTaskRolloverOnly());


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to