FrankChen021 commented on code in PR #19651:
URL: https://github.com/apache/druid/pull/19651#discussion_r3558728236


##########
extensions-contrib/prometheus-emitter/src/main/resources/defaultMetrics.json:
##########
@@ -134,6 +134,12 @@
   "ingest/notices/time" : { "dimensions" : ["dataSource"], "type" : "timer", 
"conversionFactor": 1000.0, "help": "Seconds taken to process a notice by the 
supervisor." },
   "ingest/pause/time" : { "dimensions" : ["dataSource"], "type" : "timer", 
"conversionFactor": 1000.0, "help": "Seconds spent by a task in a paused state 
without ingesting." },
   "ingest/handoff/time" : { "dimensions" : ["dataSource"], "type" : "timer", 
"conversionFactor": 1000.0, "help": "Total number of seconds taken to handoff a 
set of segments." },
+  "ingest/realtime/segmentUpgrade/count" : { "dimensions" : ["dataSource", 
"interval", "version"], "type" : "count", "help": "Number of pending segments 
upgraded by a concurrent replace." },

Review Comment:
   [P1] Avoid unbounded per-version Prometheus series
   
   The default exporter has no TTL unless `flushPeriod` is explicitly 
configured, and its collector retains every label tuple. `version`, `interval`, 
and `taskId` continually change across replacements and tasks, so recurring 
concurrent compaction makes these six default metrics accumulate series 
indefinitely on long-lived Overlord/supervisor processes, potentially 
exhausting heap. Keep high-cardinality identifiers out of the default mapping 
or enforce bounded expiry.



##########
indexing-service/src/main/java/org/apache/druid/indexing/common/actions/SegmentTransactionalReplaceAction.java:
##########
@@ -169,19 +173,45 @@ private void registerUpgradedPendingSegmentsOnSupervisor(
       List<PendingSegmentRecord> upgradedPendingSegments
   )
   {
+    // Emit one count per upgraded segment (rather than a single aggregate) 
regardless of whether a supervisor exists
+    // to receive them, so the total can be compared against the count 
actually announced by tasks and so each event
+    // carries the segment's interval and version.
+    for (PendingSegmentRecord upgradedPendingSegment : 
upgradedPendingSegments) {
+      final ServiceMetricEvent.Builder metricBuilder = new 
ServiceMetricEvent.Builder();
+      IndexTaskUtils.setTaskDimensions(metricBuilder, task);
+      SegmentUpgradeMetrics.setSegmentDimensions(metricBuilder, 
upgradedPendingSegment);
+      
toolbox.getEmitter().emit(metricBuilder.setMetric(SegmentUpgradeMetrics.COUNT, 
1));
+    }
+
     final SupervisorManager supervisorManager = toolbox.getSupervisorManager();
     final Optional<String> activeSupervisorIdWithAppendLock =
         
supervisorManager.getActiveSupervisorIdForDatasourceWithAppendLock(task.getDataSource());
 
     if (!activeSupervisorIdWithAppendLock.isPresent()) {
+      log.info("No active streaming supervisor for datasource[%s]; the [%d] 
upgraded pending segment(s) from task[%s]"
+               + " will become queryable when their tasks hand off.",
+                task.getDataSource(),
+                upgradedPendingSegments.size(),
+                task.getId()
+      );
       return;
     }
 
-    upgradedPendingSegments.forEach(
-        upgradedPendingSegment -> 
supervisorManager.registerUpgradedPendingSegmentOnSupervisor(
-            activeSupervisorIdWithAppendLock.get(),
-            upgradedPendingSegment
-        )
+    // Register each upgraded pending segment on the supervisor and summarize 
the whole batch in one log line,
+    // mapping each segment to the number of running tasks the supervisor 
notified.
+    final Map<String, Integer> notifiedTasksBySegment = new LinkedHashMap<>();
+    for (PendingSegmentRecord upgradedPendingSegment : 
upgradedPendingSegments) {
+      supervisorManager
+          
.registerUpgradedPendingSegmentOnSupervisor(activeSupervisorIdWithAppendLock.get(),
 upgradedPendingSegment)
+          .ifPresent(notified -> 
notifiedTasksBySegment.put(upgradedPendingSegment.getId().toString(), 
notified));
+    }
+    log.info(
+        "Registered [%d] upgraded pending segment(s) created by task[%s] on 
supervisor[%s]; tasks notified per"
+        + " segment[%s].",
+        notifiedTasksBySegment.size(),
+        task.getId(),
+        activeSupervisorIdWithAppendLock.get(),
+        notifiedTasksBySegment

Review Comment:
   [P2] Bound the per-segment INFO summary
   
   The upgraded-segment list is not capped, yet this builds and formats every 
segment ID into one INFO message. Broad compaction can produce thousands of 
entries and megabyte-scale log lines on the task-action path. Log aggregate 
counts with a bounded sample, reserving full detail for debug output.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to