voonhous commented on code in PR #19575:
URL: https://github.com/apache/hudi/pull/19575#discussion_r3862767500


##########
hudi-client/hudi-client-common/src/main/java/org/apache/hudi/metrics/ExecutorMetrics.java:
##########
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hudi.metrics;
+
+import org.apache.hudi.common.metrics.Registry;
+import org.apache.hudi.common.util.Option;
+import org.apache.hudi.config.HoodieWriteConfig;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Commit-boundary drain for executor-collected metrics, generic over {@link 
ExecutorMetricRegistry}. On
+ * the shared commit path, so it covers Spark DataSource, Spark SQL and 
DeltaStreamer alike.
+ */
+public class ExecutorMetrics {
+
+  private ExecutorMetrics() {
+  }
+
+  /**
+   * Snapshots into commit metadata without consuming. Split from {@link 
#publishAndRelease} so a commit
+   * that never lands neither loses its counters nor publishes gauges for 
rolled-back work. An all-zero
+   * registry is skipped to keep residue off the timeline; zeros are otherwise 
kept, since an explicit
+   * {@code misses=0} is meaningful.
+   */
+  public static DrainedCounters snapshotIntoCommitMetadata(Map<String, String> 
commitMetadata,
+                                                           HoodieWriteConfig 
config) {
+    return snapshotIntoCommitMetadata(commitMetadata, config, 
Arrays.asList(ExecutorMetricRegistry.values()));
+  }
+
+  /** Visible for testing the collection machinery against a group it does not 
ship with. */
+  static DrainedCounters snapshotIntoCommitMetadata(Map<String, String> 
commitMetadata,
+                                                    HoodieWriteConfig config,
+                                                    Collection<? extends 
ExecutorMetricGroup> groups) {
+    List<Drained> drained = new ArrayList<>();
+    for (ExecutorMetricGroup metricRegistry : groups) {
+      if (!metricRegistry.isEnabled(config)) {
+        continue;
+      }
+      Registry registry = Registry.REGISTRY_MAP.get(
+          Registry.makeKey(config.getTableName(), 
metricRegistry.scopedName(config.getBasePath())));
+      if (registry == null) {
+        continue;
+      }
+      Map<String, Long> counts = new HashMap<>();
+      boolean recordedSomething = false;
+      for (Map.Entry<String, Long> counter : 
registry.getAllCounts(false).entrySet()) {
+        if (counter.getValue() == null) {
+          continue;
+        }
+        counts.put(counter.getKey(), counter.getValue());
+        recordedSomething |= counter.getValue() != 0L;
+      }
+      if (!recordedSomething) {
+        continue;
+      }
+      counts.forEach((name, value) ->
+          commitMetadata.put(metricRegistry.commitMetadataPrefix() + name, 
String.valueOf(value)));
+      drained.add(new Drained(metricRegistry, registry, counts));
+    }
+    return drained.isEmpty() ? DrainedCounters.EMPTY : new 
DrainedCounters(drained);
+  }
+
+  /**
+   * Release subtracts what was published rather than clearing, so a straggler 
task's update arriving after
+   * the snapshot survives. Publishing here rather than letting the reporter 
scrape is what lets both sinks
+   * work at once: {@link Registry#getAllMetrics} consumes the registry when 
it scrapes.
+   */
+  public static void publishAndRelease(DrainedCounters counters, HoodieMetrics 
hoodieMetrics) {

Review Comment:
   The DataSource half holds only because `DefaultSource:194` calls 
`Metrics.shutdownAllMetrics()` after every write. 
`UpdateHoodieTableCommand:71`, `MergeIntoHoodieTableCommand:509` and 
`StreamSync` call `HoodieSparkSqlWriter.write` / the client directly and never 
shut metrics down between commits, so on those paths an abandoned attempt's 
counters still land on the next successful commit, and the flipped test runs 
the DataSource path only. Could we clear the group's registry at `startCommit` 
(your `dd4a48c`), which makes the guarantee path-independent, and run the 
failed-commit case once on the SQL class?
   



-- 
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]

Reply via email to