gaborgsomogyi commented on code in PR #28427:
URL: https://github.com/apache/flink/pull/28427#discussion_r3734252292


##########
flink-core/src/main/java/org/apache/flink/core/fs/FileSystem.java:
##########
@@ -316,6 +318,53 @@ public static List<FileSystemFactory> 
getRegisteredFileSystemFactories() {
         }
     }
 
+    /**
+     * Hands a runtime-owned, process-level {@link MetricGroup} to every 
registered {@link
+     * FileSystemFactory} that opts into metrics via {@link MetricsAware}.
+     *
+     * <p>This is the second phase of file system initialization. {@link 
#initialize(Configuration,
+     * PluginManager)} runs at process startup, before the {@code 
MetricRegistry} exists; this
+     * method is therefore invoked separately, once the registry and a 
process-level {@link
+     * MetricGroup} are available. It is called from the TaskManager and 
JobManager entrypoints
+     * only. Contexts without a process-level {@link MetricGroup} (CLI, 
HistoryServer, YARN client)
+     * simply never call it, and their file system plugins continue to operate 
without emitting
+     * metrics.
+     *
+     * <p>The call is idempotent: factories receive a child group {@code 
<process>.filesystem}, and
+     * {@link MetricGroup#addGroup} returns the same child on repeated calls 
with the same parent,
+     * so re-invocation does not register duplicate metrics. Factories that do 
not implement {@link
+     * MetricsAware} are skipped.
+     *
+     * @param processMetricGroup the process-level metric group to register 
file system metrics
+     *     under.
+     */
+    @Internal
+    public static void attachMetrics(MetricGroup processMetricGroup) {
+        checkNotNull(processMetricGroup, "processMetricGroup");
+        LOCK.lock();
+        try {
+            final MetricGroup fsGroup = 
processMetricGroup.addGroup("filesystem");
+            for (FileSystemFactory factory : FS_FACTORIES.values()) {
+                // Plugin-loaded factories are wrapped in a 
PluginFileSystemFactory, which is itself
+                // MetricsAware and forwards setMetricGroup to the inner 
factory under the plugin
+                // classloader, so this plain instanceof reaches both wrapped 
and direct factories.
+                if (factory instanceof MetricsAware) {
+                    try {
+                        ((MetricsAware) factory).setMetricGroup(fsGroup);
+                    } catch (Exception e) {
+                        // A misbehaving plugin must never break process 
startup.
+                        LOG.warn(
+                                "Failed to attach metrics to file system 
factory {}",
+                                factory.getClass().getName(),
+                                e);
+                    }

Review Comment:
   If it's `MetricsAware` instance then why do we treat exception as acceptable 
warning? I mean if the user configured metrics then it's a fair expectation to 
work, right?



##########
flink-core/src/main/java/org/apache/flink/core/fs/metrics/FileSystemMetricOptions.java:
##########
@@ -0,0 +1,76 @@
+/*
+ * 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.flink.core.fs.metrics;
+
+import org.apache.flink.annotation.Internal;
+import org.apache.flink.configuration.ConfigOption;
+import org.apache.flink.configuration.ConfigOptions;
+import org.apache.flink.metrics.SlidingWindowHistogram;
+import org.apache.flink.util.Preconditions;
+
+import java.util.List;
+
+/** Creates filesystem metric options under a cloud-specific configuration 
prefix. */
+@Internal
+public final class FileSystemMetricOptions {
+
+    private FileSystemMetricOptions() {}
+
+    public static ConfigOption<Boolean> metricsEnabled(String 
configurationPrefix) {
+        final String prefix = validatePrefix(configurationPrefix);
+        return ConfigOptions.key(prefix + ".metrics.enabled")
+                .booleanType()
+                .defaultValue(true)
+                .withDescription(
+                        "Master switch for publishing "
+                                + prefix
+                                + " filesystem operation metrics to Flink's 
metric system.");
+    }
+
+    public static ConfigOption<List<String>> metricsAllowlist(String 
configurationPrefix) {
+        final String prefix = validatePrefix(configurationPrefix);
+        return ConfigOptions.key(prefix + ".metrics.allowlist")
+                .stringType()
+                .asList()
+                
.defaultValues(FileSystemMetricRecorder.DEFAULT_ALLOWLIST.toArray(new 
String[0]))
+                .withDescription(
+                        "Names of "
+                                + prefix
+                                + " filesystem metrics to register. Replaces 
the default list; use "
+                                + "\"*\" to register every emitted metric. An 
empty list is invalid. "
+                                + "The iops metric is derived from 
api_call_count.");

Review Comment:
   I've the feeling that the last sentence is S3 native specific, right?



##########
flink-filesystems/flink-s3-fs-native/src/main/java/org/apache/flink/fs/s3native/S3ClientProvider.java:
##########
@@ -682,6 +692,13 @@ S3ClientProvider build() {
                                 : "(CRT runtime default)");
             }
 
+            if (metricPublisher != null) {
+                // Re-wrap the immutable override config with the publisher 
attached. The same
+                // publisher feeds both the sync and async clients below.
+                overrideConfig =
+                        
overrideConfig.toBuilder().addMetricPublisher(metricPublisher).build();
+            }

Review Comment:
   More like a nit but I think nothing blocks us to build `overrideConfig` only 
once, right?



##########
flink-filesystems/flink-s3-fs-native/src/main/java/org/apache/flink/fs/s3native/NativeS3FileSystemFactory.java:
##########
@@ -321,9 +325,53 @@ public class NativeS3FileSystemFactory implements 
FileSystemFactory {
                                     + "When not set, the default chain is 
used: delegation tokens -> "
                                     + "static credentials (if configured) -> 
DefaultCredentialsProvider.");
 
+    public static final ConfigOption<Boolean> METRICS_ENABLED =
+            ConfigOptions.key("s3.metrics.enabled")
+                    .booleanType()
+                    .defaultValue(true)
+                    .withDescription(
+                            "Master switch for publishing S3 operation metrics 
to Flink's metric "
+                                    + "system. When false, no metric publisher 
is attached to the SDK "
+                                    + "and no metric is registered. Metrics 
are only emitted under the "
+                                    + "TaskManager and JobManager entrypoints, 
which provide a "
+                                    + "process-level metric group; other 
contexts (CLI, etc.) emit "
+                                    + "none regardless of this setting.");
+
+    public static final ConfigOption<List<String>> METRICS_ALLOWLIST =
+            ConfigOptions.key("s3.metrics.allowlist")
+                    .stringType()
+                    .asList()
+                    .defaultValues(
+                            "api_call_count",
+                            "api_call_duration_ms",
+                            "throttle_count",
+                            "retry_count",
+                            "iops")

Review Comment:
   Having a `*` is fine, the main idea is not to type all when everything is 
needed.



##########
flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/TaskManagerRunner.java:
##########
@@ -640,6 +640,11 @@ public static TaskExecutor startTaskManager(
                         resourceID,
                         
taskManagerServicesConfiguration.getSystemResourceMetricsProbingInterval());
 
+        // Second-phase init for file system plugins that opt into metrics 
(e.g.
+        // flink-s3-fs-native): hand them the process-level metric group now 
that the
+        // MetricRegistry exists. See FileSystem#attachMetrics and 
MetricsAware.
+        FileSystem.attachMetrics(taskManagerMetricGroup.f0);

Review Comment:
   Makes sense, thanks for clarifying. Confirming what we landed on: 
`MetricsAware` is a reusable contract, but the setter/two-phase pattern is 
specifically needed for filesystems, not a general requirement. Two reasons: 
`FileSystemFactory.create(URI)` is `@PublicEvolving` with many external 
implementors, so adding a `MetricGroup` parameter would break the public API; 
and `FileSystem.CACHE` can already hold instances created before any 
`MetricGroup` exists, so parameter injection could not retrofit them anyway. 
Other plugin families without that constraint (e.g. 
`StateChangelogStorageFactory`) should keep using plain parameter passing. Good 
with this approach for filesystems.



##########
flink-core/src/main/java/org/apache/flink/core/fs/metrics/FileSystemMetricRecorder.java:
##########
@@ -0,0 +1,203 @@
+/*
+ * 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.flink.core.fs.metrics;
+
+import org.apache.flink.annotation.Internal;
+import org.apache.flink.metrics.Counter;
+import org.apache.flink.metrics.Histogram;
+import org.apache.flink.metrics.MetricGroup;
+import org.apache.flink.metrics.SlidingWindowHistogram;
+import org.apache.flink.metrics.ThreadSafeSimpleCounter;
+import org.apache.flink.util.Preconditions;
+
+import javax.annotation.Nullable;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/** Registers normalized filesystem operation metrics supplied by 
cloud-specific adapters. */
+@Internal
+public final class FileSystemMetricRecorder {

Review Comment:
   I think there is a global design issue here. This code part is in core and 
assumes that all FS plugins are having the exact same metrics set. This will 
never be true. Just to give an example this maps HTTP status codes which 
assumes all filesystems are HTTP based. Instead a more dynamic approach need to 
be chosen which is not doing any prediction how a filesystem works.



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