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

capistrant 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 26301598f7e feat: Refactor names for tier segment cache usage to help 
with observability and monitoring (#20199)
26301598f7e is described below

commit 26301598f7e280cd3497bafbdda8a52af0206dda
Author: Lucas Capistrant <[email protected]>
AuthorDate: Fri Sep 11 06:09:23 2026 -0500

    feat: Refactor names for tier segment cache usage to help with 
observability and monitoring (#20199)
    
    Helps distinguish between actual disk usage and assignable cache usage. Now 
that virtual storage historical can advertise larger max assignable size than 
actual disk, the metrics needed some massaging to make sense in both worlds.
---
 docs/operations/metrics.md                         |  8 +++-
 .../embedded/query/QueryVirtualStorageTest.java    |  8 ++--
 .../src/main/resources/defaultMetrics.json         |  8 +++-
 .../main/resources/defaultMetricDimensions.json    |  4 ++
 .../resources/loggingEmitterAllowedMetrics.json    |  4 ++
 .../resources/loggingEmitterAllowedMetrics.json    |  4 ++
 .../duty/PrepareBalancerAndLoadQueues.java         | 15 ++++--
 .../loading/StrategicSegmentAssigner.java          |  5 +-
 .../druid/server/coordinator/stats/Stats.java      | 44 ++++++++++++++++-
 .../server/coordinator/duty/RunRulesTest.java      |  4 +-
 .../server/coordinator/rules/LoadRuleTest.java     | 10 ++--
 .../simulate/HistoricalTierAliasTest.java          | 56 +++++++++++++++++++---
 12 files changed, 143 insertions(+), 27 deletions(-)

diff --git a/docs/operations/metrics.md b/docs/operations/metrics.md
index 62d01316e6a..c30d34d14dc 100644
--- a/docs/operations/metrics.md
+++ b/docs/operations/metrics.md
@@ -474,8 +474,12 @@ These metrics are emitted by the Druid Coordinator in 
every run of the correspon
 |`tier/historical/clone/count`|Number of historical nodes in a tier which are 
a clone of another historical in the same or different tier. The `tierAlias` 
dimension is emitted only when the tier belongs to an alias configured via 
[`historicalTierAliases`](../configuration/index.md#dynamic-configuration), and 
can be used to aggregate metrics across the tiers in an alias.|`tier`, 
`tierAlias`|Varies|
 |`tier/historical/clone/synced`|Number of historical clones in a tier which 
are currently in sync with their source server. |`server`, `tier`|1 if synced, 
O if not synced|
 |`tier/replication/factor`|Configured maximum replication factor in each tier. 
The `tierAlias` dimension is emitted only when the tier belongs to an alias 
configured via 
[`historicalTierAliases`](../configuration/index.md#dynamic-configuration).|`tier`,
 `tierAlias`|Varies|
-|`tier/required/capacity`|Total capacity in bytes required in each tier. The 
`tierAlias` dimension is emitted only when the tier belongs to an alias 
configured via 
[`historicalTierAliases`](../configuration/index.md#dynamic-configuration).|`tier`,
 `tierAlias`|Varies|
-|`tier/total/capacity`|Total capacity in bytes available in each tier. The 
`tierAlias` dimension is emitted only when the tier belongs to an alias 
configured via 
[`historicalTierAliases`](../configuration/index.md#dynamic-configuration).|`tier`,
 `tierAlias`|Varies|
+|`tier/storage/required`|Segment storage in bytes that the load rules require 
in each tier, counting each replica at its full segment size. Compare against 
`tier/storage/capacity` to see how heavily the tier is subscribed. The 
`tierAlias` dimension is emitted only when the tier belongs to an alias 
configured via 
[`historicalTierAliases`](../configuration/index.md#dynamic-configuration).|`tier`,
 `tierAlias`|Varies|
+|`tier/storage/capacity`|Total segment storage in bytes that each tier 
advertises for segment assignment. Can be greater than the physical disk 
reported by `tier/segmentCache/capacity` if using virtual storage, so use that 
metric rather than this one to monitor physical capacity. The `tierAlias` 
dimension is emitted only when the tier belongs to an alias configured via 
[`historicalTierAliases`](../configuration/index.md#dynamic-configuration).|`tier`,
 `tierAlias`|Varies|
+|`tier/segmentCache/capacity`|Total physical size in bytes of the segment 
cache locations configured on the historicals in each tier. The `tierAlias` 
dimension is emitted only when the tier belongs to an alias configured via 
[`historicalTierAliases`](../configuration/index.md#dynamic-configuration).|`tier`,
 `tierAlias`|Varies|
+|`tier/segmentCache/used`|Bytes occupied on disk in each tier by the segments 
its historicals have announced. Partially loaded segments count only the bytes 
the historical reported loading, not their full size. Compare against 
`tier/segmentCache/capacity` to see how full the tier's disks are. The 
`tierAlias` dimension is emitted only when the tier belongs to an alias 
configured via 
[`historicalTierAliases`](../configuration/index.md#dynamic-configuration).|`tier`,
 `tierAlias`|Varies|
+|`tier/required/capacity`|Deprecated. Use `tier/storage/required` instead, 
which reports the same value under a name that groups it with the storage 
capacity it should be compared against. This metric will be removed in a future 
release.|`tier`, `tierAlias`|Varies|
+|`tier/total/capacity`|Deprecated. Use `tier/storage/capacity` instead, which 
reports the same value under a name that groups it with the required storage it 
should be compared against. This metric will be removed in a future 
release.|`tier`, `tierAlias`|Varies|
 |`compact/task/count`|Number of tasks issued in the auto compaction run.| 
|Varies|
 |`compactTask/maxSlot/count`|Maximum number of task slots available for auto 
compaction tasks in the auto compaction run.| |Varies|
 |`compactTask/availableSlot/count`|Number of currently vacant task slots out 
of the total slots allocated for auto compaction tasks. This value is computed 
as the difference between the total number of task slots allocated for auto 
compaction and the estimated number of task slots currently occupied by running 
compaction tasks. The number of sub-tasks of each compaction task is estimated 
to be `maxNumConcurrentSubTasks`.| |Varies|
diff --git 
a/embedded-tests/src/test/java/org/apache/druid/testing/embedded/query/QueryVirtualStorageTest.java
 
b/embedded-tests/src/test/java/org/apache/druid/testing/embedded/query/QueryVirtualStorageTest.java
index bc259097551..466f2cb9eb0 100644
--- 
a/embedded-tests/src/test/java/org/apache/druid/testing/embedded/query/QueryVirtualStorageTest.java
+++ 
b/embedded-tests/src/test/java/org/apache/druid/testing/embedded/query/QueryVirtualStorageTest.java
@@ -295,15 +295,15 @@ class QueryVirtualStorageTest extends 
EmbeddedClusterTestBase
     Assertions.assertEquals(0, 
emitter.getMetricEventLongSum(StorageMonitor.VSF_REJECT_COUNT));
     
Assertions.assertTrue(emitter.getLatestMetricEventValue(StorageMonitor.VSF_USED_BYTES,
 0).longValue() > 0);
 
-    coordinatorEmitter.waitForEvent(event -> 
event.hasMetricName(Stats.Tier.STORAGE_CAPACITY.getMetricName()));
+    coordinatorEmitter.waitForEvent(event -> 
event.hasMetricName(Stats.Tier.CACHE_CAPACITY.getMetricName()));
     Assertions.assertEquals(
         CACHE_SIZE,
-        
coordinatorEmitter.getLatestMetricEventValue(Stats.Tier.STORAGE_CAPACITY.getMetricName())
+        
coordinatorEmitter.getLatestMetricEventValue(Stats.Tier.CACHE_CAPACITY.getMetricName())
     );
-    coordinatorEmitter.waitForEvent(event -> 
event.hasMetricName(Stats.Tier.TOTAL_CAPACITY.getMetricName()));
+    coordinatorEmitter.waitForEvent(event -> 
event.hasMetricName(Stats.Tier.STORAGE_CAPACITY.getMetricName()));
     Assertions.assertEquals(
         MAX_SIZE,
-        
coordinatorEmitter.getLatestMetricEventValue(Stats.Tier.TOTAL_CAPACITY.getMetricName())
+        
coordinatorEmitter.getLatestMetricEventValue(Stats.Tier.STORAGE_CAPACITY.getMetricName())
     );
   }
 
diff --git 
a/extensions-contrib/prometheus-emitter/src/main/resources/defaultMetrics.json 
b/extensions-contrib/prometheus-emitter/src/main/resources/defaultMetrics.json
index 53492716265..57e4b8c7e99 100644
--- 
a/extensions-contrib/prometheus-emitter/src/main/resources/defaultMetrics.json
+++ 
b/extensions-contrib/prometheus-emitter/src/main/resources/defaultMetrics.json
@@ -188,8 +188,12 @@
   "segment/availableDeepStorageOnly/count" : { "dimensions" : ["dataSource", 
"tier"], "type" : "gauge", "help": "Number of unique segments that are only 
available for querying directly from deep storage."},
   "tier/historical/count" : { "dimensions" : ["tier", "tierAlias"], "type" : 
"count", "help": "Number of available historical nodes in each tier."},
   "tier/replication/factor" : { "dimensions" : ["tier", "tierAlias"], "type" : 
"count", "help": "Configured maximum replication factor in each tier."},
-  "tier/required/capacity" : { "dimensions" : ["tier", "tierAlias"], "type" : 
"count", "help": "Total capacity in bytes required in each tier."},
-  "tier/total/capacity" : { "dimensions" : ["tier", "tierAlias"], "type" : 
"count", "help": "Total capacity in bytes available in each tier."},
+  "tier/storage/required": { "dimensions" : ["tier", "tierAlias"], "type" : 
"gauge", "help": "Segment storage in bytes required in each tier."},
+  "tier/storage/capacity": { "dimensions" : ["tier", "tierAlias"], "type" : 
"gauge", "help": "Total segment storage in bytes available for assignment in 
each tier."},
+  "tier/segmentCache/capacity": { "dimensions" : ["tier", "tierAlias"], "type" 
: "gauge", "help": "Total physical capacity in bytes of the segment cache 
locations in each tier."},
+  "tier/segmentCache/used": { "dimensions" : ["tier", "tierAlias"], "type" : 
"gauge", "help": "Total bytes occupied on disk in each tier."},
+  "tier/required/capacity" : { "dimensions" : ["tier", "tierAlias"], "type" : 
"gauge", "help": "Deprecated. Use tier/storage/required instead."},
+  "tier/total/capacity" : { "dimensions" : ["tier", "tierAlias"], "type" : 
"gauge", "help": "Deprecated. Use tier/storage/capacity instead."},
   "compact/task/count" : { "dimensions" : [], "type" : "gauge", "help": 
"Number of tasks issued in the auto compaction run."},
   "compactTask/maxSlot/count" : { "dimensions" : [], "type" : "gauge", "help": 
"Maximum number of task slots available for auto compaction tasks in the auto 
compaction run."},
   "compactTask/availableSlot/count" : { "dimensions" : [], "type" : "gauge", 
"help": "Number of available task slots that can be used for auto compaction 
tasks in the auto compaction run."},
diff --git 
a/extensions-contrib/statsd-emitter/src/main/resources/defaultMetricDimensions.json
 
b/extensions-contrib/statsd-emitter/src/main/resources/defaultMetricDimensions.json
index 0b86e8efc5d..77f34f1da4e 100644
--- 
a/extensions-contrib/statsd-emitter/src/main/resources/defaultMetricDimensions.json
+++ 
b/extensions-contrib/statsd-emitter/src/main/resources/defaultMetricDimensions.json
@@ -182,6 +182,10 @@
   "coordinator/time" : { "dimensions" : [], "type" : "timer"},
   "coordinator/global/time" : { "dimensions" : ["dutyGroup"], "type" : 
"timer"},
 
+  "tier/storage/required": { "dimensions" : ["tier", "tierAlias"], "type" : 
"gauge"},
+  "tier/storage/capacity": { "dimensions" : ["tier", "tierAlias"], "type" : 
"gauge"},
+  "tier/segmentCache/capacity": { "dimensions" : ["tier", "tierAlias"], "type" 
: "gauge"},
+  "tier/segmentCache/used": { "dimensions" : ["tier", "tierAlias"], "type" : 
"gauge"},
   "tier/required/capacity" : { "dimensions" : ["tier", "tierAlias"], "type" : 
"gauge" },
   "tier/total/capacity" : { "dimensions" : ["tier", "tierAlias"], "type" : 
"gauge" },
   "tier/replication/factor" : { "dimensions" : ["tier", "tierAlias"], "type" : 
"gauge" },
diff --git a/processing/src/main/resources/loggingEmitterAllowedMetrics.json 
b/processing/src/main/resources/loggingEmitterAllowedMetrics.json
index e0d89fac679..a421c96021f 100644
--- a/processing/src/main/resources/loggingEmitterAllowedMetrics.json
+++ b/processing/src/main/resources/loggingEmitterAllowedMetrics.json
@@ -249,6 +249,10 @@
     "tier/replication/factor": [],
     "tier/required/capacity": [],
     "tier/total/capacity": [],
+    "tier/storage/required": [],
+    "tier/storage/capacity":  [],
+    "tier/segmentCache/used":  [],
+    "tier/segmentCache/capacity":  [],
     "zk/connected": [],
     "zk/reconnect/time": []
 }
diff --git a/processing/src/test/resources/loggingEmitterAllowedMetrics.json 
b/processing/src/test/resources/loggingEmitterAllowedMetrics.json
index 5818ed2d36a..b9451f0fcf9 100644
--- a/processing/src/test/resources/loggingEmitterAllowedMetrics.json
+++ b/processing/src/test/resources/loggingEmitterAllowedMetrics.json
@@ -248,6 +248,10 @@
   "tier/replication/factor": [],
   "tier/required/capacity": [],
   "tier/total/capacity": [],
+  "tier/storage/required": [],
+  "tier/storage/capacity":  [],
+  "tier/segmentCache/used":  [],
+  "tier/segmentCache/capacity":  [],
   "zk/connected": [],
   "zk/reconnect/time": []
 }
diff --git 
a/server/src/main/java/org/apache/druid/server/coordinator/duty/PrepareBalancerAndLoadQueues.java
 
b/server/src/main/java/org/apache/druid/server/coordinator/duty/PrepareBalancerAndLoadQueues.java
index 0ad2c1cb199..02f428cbd48 100644
--- 
a/server/src/main/java/org/apache/druid/server/coordinator/duty/PrepareBalancerAndLoadQueues.java
+++ 
b/server/src/main/java/org/apache/druid/server/coordinator/duty/PrepareBalancerAndLoadQueues.java
@@ -184,20 +184,27 @@ public class PrepareBalancerAndLoadQueues implements 
CoordinatorDuty
                             : RowKey.with(Dimension.TIER, 
tier).and(Dimension.TIER_ALIAS, alias);
       stats.add(Stats.Tier.HISTORICAL_COUNT, rowKey, historicals.size());
 
-      long totalCapacity = 0;
       long storageCapacity = 0;
+      long cacheCapacity = 0;
+      long cacheUsed = 0;
       long cloneCount = 0;
       for (ServerHolder holder : historicals) {
         if (holder.isUnmanaged()) {
           cloneCount += 1;
         } else {
-          totalCapacity += holder.getMaxSize();
-          storageCapacity += holder.getStorageSize();
+          storageCapacity += holder.getMaxSize();
+          cacheCapacity += holder.getStorageSize();
+          // getCurrSize(), not getSizeUsed(): queued loads are counted at 
full segment size, which would overstate
+          // disk usage on a tier serving partial loads for the duration of 
every load
+          cacheUsed += holder.getServer().getCurrSize();
         }
       }
       stats.add(Stats.Tier.CLONE_COUNT, rowKey, cloneCount);
-      stats.add(Stats.Tier.TOTAL_CAPACITY, rowKey, totalCapacity);
       stats.add(Stats.Tier.STORAGE_CAPACITY, rowKey, storageCapacity);
+      // Deprecated alias of tier/storage/capacity, emitted until the 
deprecation period is over
+      stats.add(Stats.Tier.TOTAL_CAPACITY, rowKey, storageCapacity);
+      stats.add(Stats.Tier.CACHE_CAPACITY, rowKey, cacheCapacity);
+      stats.add(Stats.Tier.CACHE_USED, rowKey, cacheUsed);
     });
   }
 
diff --git 
a/server/src/main/java/org/apache/druid/server/coordinator/loading/StrategicSegmentAssigner.java
 
b/server/src/main/java/org/apache/druid/server/coordinator/loading/StrategicSegmentAssigner.java
index 42cb7d3ab2c..89e51f99660 100644
--- 
a/server/src/main/java/org/apache/druid/server/coordinator/loading/StrategicSegmentAssigner.java
+++ 
b/server/src/main/java/org/apache/druid/server/coordinator/loading/StrategicSegmentAssigner.java
@@ -780,8 +780,11 @@ public class StrategicSegmentAssigner implements 
SegmentActionHandler
   private void reportTierCapacityStats(DataSegment segment, int 
requiredReplicas, String tier)
   {
     final RowKey rowKey = tierRowKey(tier);
+    final long requiredStorage = segment.getSize() * requiredReplicas;
     stats.updateMax(Stats.Tier.REPLICATION_FACTOR, rowKey, requiredReplicas);
-    stats.add(Stats.Tier.REQUIRED_CAPACITY, rowKey, segment.getSize() * 
requiredReplicas);
+    stats.add(Stats.Tier.REQUIRED_STORAGE, rowKey, requiredStorage);
+    // Deprecated alias of tier/storage/required, emitted until the 
deprecation period is over
+    stats.add(Stats.Tier.REQUIRED_CAPACITY, rowKey, requiredStorage);
   }
 
   /**
diff --git 
a/server/src/main/java/org/apache/druid/server/coordinator/stats/Stats.java 
b/server/src/main/java/org/apache/druid/server/coordinator/stats/Stats.java
index 138d7068189..c2f763dbb6f 100644
--- a/server/src/main/java/org/apache/druid/server/coordinator/stats/Stats.java
+++ b/server/src/main/java/org/apache/druid/server/coordinator/stats/Stats.java
@@ -108,12 +108,52 @@ public class Stats
 
   public static class Tier
   {
+    // Segment storage of a tier, denominated in full segment size. These are 
the assignment ledger: REQUIRED_STORAGE
+    // is the demand the rules place on the tier, STORAGE_CAPACITY the supply 
it advertises. Under virtual storage a
+    // tier can address more storage than it has disk, so both may exceed 
CACHE_CAPACITY.
+
+    /**
+     * The demand the rules place on the tier to full load all segments.
+     */
+    public static final CoordinatorStat REQUIRED_STORAGE
+        = CoordinatorStat.toDebugAndEmit("reqdStorage", 
"tier/storage/required");
+    /**
+     * The total storage the tier advertises for assignment, defined by 
summing the configured max size of all servers
+     * in the tier.
+     */
+    public static final CoordinatorStat STORAGE_CAPACITY
+        = CoordinatorStat.toDebugAndEmit("storageCap", 
"tier/storage/capacity");
+    /**
+     * Superseded by {@link #REQUIRED_STORAGE}, which carries the same value 
under a name that groups it with the
+     * storage capacity it should be compared against. Still emitted so 
existing dashboards keep working; remove
+     * after deprecation.
+     */
+    @Deprecated
     public static final CoordinatorStat REQUIRED_CAPACITY
         = CoordinatorStat.toDebugAndEmit("reqdCap", "tier/required/capacity");
+    /**
+     * Superseded by {@link #STORAGE_CAPACITY}, which carries the same value 
under a name that groups it with the
+     * required storage it should be compared against. Still emitted so 
existing dashboards keep working; remove after
+     * deprecation.
+     */
+    @Deprecated
     public static final CoordinatorStat TOTAL_CAPACITY
         = CoordinatorStat.toDebugAndEmit("totalCap", "tier/total/capacity");
-    public static final CoordinatorStat STORAGE_CAPACITY
-        = CoordinatorStat.toDebugAndEmit("storageCap", 
"tier/storage/capacity");
+
+    // Physical segment cache of a tier: the size of the segment cache 
locations configured on its historicals and the
+    // bytes actually occupied on them. Named for 
druid.segmentCache.locations, which is what these measure.
+
+    /**
+     * Aggregate physical disk capacity of the tier's segment cache locations.
+     */
+    public static final CoordinatorStat CACHE_CAPACITY
+        = CoordinatorStat.toDebugAndEmit("cacheCap", 
"tier/segmentCache/capacity");
+    /**
+     * Actual physical disk consumed by the tier. Only reports realized bytes 
on disk, so partial loads when using
+     * virtual storage report their true loaded size, which can be less than 
the full segment size.
+     */
+    public static final CoordinatorStat CACHE_USED
+        = CoordinatorStat.toDebugAndEmit("cacheUsed", 
"tier/segmentCache/used");
     public static final CoordinatorStat REPLICATION_FACTOR
         = CoordinatorStat.toDebugAndEmit("maxRepFactor", 
"tier/replication/factor");
     public static final CoordinatorStat HISTORICAL_COUNT
diff --git 
a/server/src/test/java/org/apache/druid/server/coordinator/duty/RunRulesTest.java
 
b/server/src/test/java/org/apache/druid/server/coordinator/duty/RunRulesTest.java
index 67ffe445343..8ba9cec03a5 100644
--- 
a/server/src/test/java/org/apache/druid/server/coordinator/duty/RunRulesTest.java
+++ 
b/server/src/test/java/org/apache/druid/server/coordinator/duty/RunRulesTest.java
@@ -1126,7 +1126,7 @@ public class RunRulesTest
     final RowKey tierRowKey = RowKey.of(Dimension.TIER, 
DruidServer.DEFAULT_TIER);
     Assertions.assertEquals(
         dataSegment.getSize() * numReplicants,
-        stats.get(Stats.Tier.REQUIRED_CAPACITY, tierRowKey)
+        stats.get(Stats.Tier.REQUIRED_STORAGE, tierRowKey)
     );
 
     // Verify that primary assignment failed
@@ -1181,7 +1181,7 @@ public class RunRulesTest
     final RowKey tierRowKey = RowKey.of(Dimension.TIER, 
DruidServer.DEFAULT_TIER);
     Assertions.assertEquals(
         dataSegment.getSize() * numReplicants,
-        stats.get(Stats.Tier.REQUIRED_CAPACITY, tierRowKey)
+        stats.get(Stats.Tier.REQUIRED_STORAGE, tierRowKey)
     );
     Assertions.assertEquals(0L, stats.getSegmentStat(Stats.Segments.ASSIGNED, 
DruidServer.DEFAULT_TIER, DATASOURCE));
     Assertions.assertFalse(stats.hasStat(Stats.Segments.DROPPED));
diff --git 
a/server/src/test/java/org/apache/druid/server/coordinator/rules/LoadRuleTest.java
 
b/server/src/test/java/org/apache/druid/server/coordinator/rules/LoadRuleTest.java
index 344c140d844..cdb4f136070 100644
--- 
a/server/src/test/java/org/apache/druid/server/coordinator/rules/LoadRuleTest.java
+++ 
b/server/src/test/java/org/apache/druid/server/coordinator/rules/LoadRuleTest.java
@@ -588,15 +588,19 @@ public class LoadRuleTest
         )
     );
 
-    // Required capacity is reported against the physical tier AND tagged with 
the alias
+    // Required storage is reported against the physical tier AND tagged with 
the alias
     final RowKey t2WithAlias = RowKey.with(Dimension.TIER, 
Tier.T2).and(Dimension.TIER_ALIAS, Tier.T1);
     final RowKey t3WithAlias = RowKey.with(Dimension.TIER, 
Tier.T3).and(Dimension.TIER_ALIAS, Tier.T1);
+    Assertions.assertEquals(segment.getSize(), 
stats.get(Stats.Tier.REQUIRED_STORAGE, t2WithAlias));
+    Assertions.assertEquals(segment.getSize(), 
stats.get(Stats.Tier.REQUIRED_STORAGE, t3WithAlias));
+
+    // The deprecated tier/required/capacity carries the same value while it 
is still emitted
     Assertions.assertEquals(segment.getSize(), 
stats.get(Stats.Tier.REQUIRED_CAPACITY, t2WithAlias));
     Assertions.assertEquals(segment.getSize(), 
stats.get(Stats.Tier.REQUIRED_CAPACITY, t3WithAlias));
 
     // The same stat without the alias dimension is a different row and must 
be absent
-    Assertions.assertEquals(0L, stats.get(Stats.Tier.REQUIRED_CAPACITY, 
RowKey.of(Dimension.TIER, Tier.T2)));
-    Assertions.assertEquals(0L, stats.get(Stats.Tier.REQUIRED_CAPACITY, 
RowKey.of(Dimension.TIER, Tier.T3)));
+    Assertions.assertEquals(0L, stats.get(Stats.Tier.REQUIRED_STORAGE, 
RowKey.of(Dimension.TIER, Tier.T2)));
+    Assertions.assertEquals(0L, stats.get(Stats.Tier.REQUIRED_STORAGE, 
RowKey.of(Dimension.TIER, Tier.T3)));
   }
 
   /**
diff --git 
a/server/src/test/java/org/apache/druid/server/coordinator/simulate/HistoricalTierAliasTest.java
 
b/server/src/test/java/org/apache/druid/server/coordinator/simulate/HistoricalTierAliasTest.java
index 33edcc1d032..ca33c5ee5e2 100644
--- 
a/server/src/test/java/org/apache/druid/server/coordinator/simulate/HistoricalTierAliasTest.java
+++ 
b/server/src/test/java/org/apache/druid/server/coordinator/simulate/HistoricalTierAliasTest.java
@@ -38,6 +38,7 @@ import java.util.Set;
 public class HistoricalTierAliasTest extends CoordinatorSimulationBaseTest
 {
   private static final long SIZE_1TB = 1_000_000;
+  private static final long SEGMENT_SIZE = 500_000_000;
   private static final String ALIAS = "hot";
 
   private DruidServer historicalT1;
@@ -79,18 +80,22 @@ public class HistoricalTierAliasTest extends 
CoordinatorSimulationBaseTest
 
     final long expectedCapacity = SIZE_1TB << 20;
 
-    // tier/total/capacity is emitted per physical tier AND tagged with the 
alias
+    // tier/storage/capacity is emitted per physical tier AND tagged with the 
alias
     verifyValue(
-        Stats.Tier.TOTAL_CAPACITY.getMetricName(),
-        Map.of(Dimension.TIER.reportedName(), Tier.T1, 
Dimension.TIER_ALIAS.reportedName(), ALIAS),
+        Stats.Tier.STORAGE_CAPACITY.getMetricName(),
+        aliasedTier(Tier.T1),
         expectedCapacity
     );
     verifyValue(
-        Stats.Tier.TOTAL_CAPACITY.getMetricName(),
-        Map.of(Dimension.TIER.reportedName(), Tier.T2, 
Dimension.TIER_ALIAS.reportedName(), ALIAS),
+        Stats.Tier.STORAGE_CAPACITY.getMetricName(),
+        aliasedTier(Tier.T2),
         expectedCapacity
     );
 
+    // The deprecated tier/total/capacity carries the same value while it is 
still emitted
+    verifyValue(Stats.Tier.TOTAL_CAPACITY.getMetricName(), 
aliasedTier(Tier.T1), expectedCapacity);
+    verifyValue(Stats.Tier.TOTAL_CAPACITY.getMetricName(), 
aliasedTier(Tier.T2), expectedCapacity);
+
     // tier/historical/count carries the alias too, so it can be summed across 
the pair
     verifyValue(
         Stats.Tier.HISTORICAL_COUNT.getMetricName(),
@@ -104,6 +109,43 @@ public class HistoricalTierAliasTest extends 
CoordinatorSimulationBaseTest
     );
   }
 
+  @Test
+  public void testUsedStorageReportsOnlyBytesLoadedAndAnnounced()
+  {
+    // tier/segmentCache/used does not report bytes consumed until historicals 
have actually loaded and announced the segments. It only reports the actual 
realized bytes of loaded segments.
+    final CoordinatorSimulation sim =
+        CoordinatorSimulation.builder()
+                             .withSegments(Segments.WIKI_10X1D)
+                             .withServers(historicalT1, historicalT2)
+                             .withRules(datasource, Load.on(ALIAS, 
1).forever())
+                             .withDynamicConfig(
+                                 CoordinatorDynamicConfig.builder()
+                                                         
.withHistoricalTierAliases(
+                                                             Map.of(ALIAS, 
Set.of(Tier.T1, Tier.T2))
+                                                         )
+                                                         
.withSmartSegmentLoading(true)
+                                                         .build()
+                             )
+                             .withImmediateSegmentLoading(true)
+                             .build();
+
+    startSimulation(sim);
+
+    runCoordinatorCycle();
+    verifyValue(Stats.Tier.CACHE_USED.getMetricName(), aliasedTier(Tier.T1), 
0L);
+    verifyValue(Stats.Tier.CACHE_USED.getMetricName(), aliasedTier(Tier.T2), 
0L);
+
+    runCoordinatorCycle();
+    final long loadedBytes = 10 * SEGMENT_SIZE;
+    verifyValue(Stats.Tier.CACHE_USED.getMetricName(), aliasedTier(Tier.T1), 
loadedBytes);
+    verifyValue(Stats.Tier.CACHE_USED.getMetricName(), aliasedTier(Tier.T2), 
loadedBytes);
+  }
+
+  private static Map<String, Object> aliasedTier(String tier)
+  {
+    return Map.of(Dimension.TIER.reportedName(), tier, 
Dimension.TIER_ALIAS.reportedName(), ALIAS);
+  }
+
   @Test
   public void testCapacityMetricsHaveNoAliasWhenNotConfigured()
   {
@@ -127,12 +169,12 @@ public class HistoricalTierAliasTest extends 
CoordinatorSimulationBaseTest
 
     // Without an alias configured, capacity is reported against the physical 
tier only
     verifyValue(
-        Stats.Tier.TOTAL_CAPACITY.getMetricName(),
+        Stats.Tier.STORAGE_CAPACITY.getMetricName(),
         filterByTier(Tier.T1),
         expectedCapacity
     );
     verifyValue(
-        Stats.Tier.TOTAL_CAPACITY.getMetricName(),
+        Stats.Tier.STORAGE_CAPACITY.getMetricName(),
         filterByTier(Tier.T2),
         expectedCapacity
     );


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

Reply via email to