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

pvillard pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new 6adbc1aeb0 NIFI-11036: Add Cluster Summary Metrics to Prometheus 
endpoint
6adbc1aeb0 is described below

commit 6adbc1aeb06c78b32f56af37029e08a4a239ed8f
Author: Matthew Burgess <[email protected]>
AuthorDate: Tue Jan 10 18:33:22 2023 -0500

    NIFI-11036: Add Cluster Summary Metrics to Prometheus endpoint
    
    Signed-off-by: Pierre Villard <[email protected]>
    
    This closes #6834.
---
 .../prometheus/util/ClusterMetricsRegistry.java    | 52 ++++++++++++++++++++++
 .../prometheus/util/PrometheusMetricsUtil.java     | 11 +++++
 .../apache/nifi/web/StandardNiFiServiceFacade.java | 27 ++++++++++-
 .../nifi/web/api/request/FlowMetricsRegistry.java  |  5 ++-
 .../org/apache/nifi/web/api/TestFlowResource.java  | 27 ++++++++++-
 5 files changed, 117 insertions(+), 5 deletions(-)

diff --git 
a/nifi-nar-bundles/nifi-extension-utils/nifi-prometheus-utils/src/main/java/org/apache/nifi/prometheus/util/ClusterMetricsRegistry.java
 
b/nifi-nar-bundles/nifi-extension-utils/nifi-prometheus-utils/src/main/java/org/apache/nifi/prometheus/util/ClusterMetricsRegistry.java
new file mode 100644
index 0000000000..6ca836253f
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-extension-utils/nifi-prometheus-utils/src/main/java/org/apache/nifi/prometheus/util/ClusterMetricsRegistry.java
@@ -0,0 +1,52 @@
+/*
+ * 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.nifi.prometheus.util;
+
+import io.prometheus.client.Gauge;
+
+/**
+ * This registry contains metrics related to a NiFi cluster, such as connected 
node count and total node count
+ */
+public class ClusterMetricsRegistry extends AbstractMetricsRegistry {
+
+    public ClusterMetricsRegistry() {
+
+        nameToGaugeMap.put("IS_CLUSTERED",  Gauge.build()
+                .name("cluster_is_clustered")
+                .help("Whether this NiFi instance is clustered. Values are 0 
or 1")
+                .labelNames("instance")
+                .register(registry));
+
+        nameToGaugeMap.put("IS_CONNECTED_TO_CLUSTER",  Gauge.build()
+                .name("cluster_is_connected_to_cluster")
+                .help("Whether this NiFi instance is connected to a cluster. 
Values are 0 or 1")
+                .labelNames("instance")
+                .register(registry));
+
+        nameToGaugeMap.put("CONNECTED_NODE_COUNT", Gauge.build()
+                .name("cluster_connected_node_count")
+                .help("The number of connected nodes in this cluster")
+                .labelNames("instance", "connected_nodes")
+                .register(registry));
+
+        nameToGaugeMap.put("TOTAL_NODE_COUNT", Gauge.build()
+                .name("cluster_total_node_count")
+                .help("The total number of nodes in this cluster")
+                .labelNames("instance")
+                .register(registry));
+    }
+}
diff --git 
a/nifi-nar-bundles/nifi-extension-utils/nifi-prometheus-utils/src/main/java/org/apache/nifi/prometheus/util/PrometheusMetricsUtil.java
 
b/nifi-nar-bundles/nifi-extension-utils/nifi-prometheus-utils/src/main/java/org/apache/nifi/prometheus/util/PrometheusMetricsUtil.java
index 6f1118ec65..f4e87d8a11 100644
--- 
a/nifi-nar-bundles/nifi-extension-utils/nifi-prometheus-utils/src/main/java/org/apache/nifi/prometheus/util/PrometheusMetricsUtil.java
+++ 
b/nifi-nar-bundles/nifi-extension-utils/nifi-prometheus-utils/src/main/java/org/apache/nifi/prometheus/util/PrometheusMetricsUtil.java
@@ -512,4 +512,15 @@ public class PrometheusMetricsUtil {
 
         return niFiMetricsRegistry.getRegistry();
     }
+
+    public static CollectorRegistry createClusterMetrics(final 
ClusterMetricsRegistry clusterMetricsRegistry, final String instId, final 
boolean isClustered, final boolean isConnectedToCluster,
+                                                         final String 
connectedNodes, final int connectedNodeCount, final int totalNodeCount) {
+        final String instanceId = StringUtils.isEmpty(instId) ? 
DEFAULT_LABEL_STRING : instId;
+        clusterMetricsRegistry.setDataPoint(isClustered ? 1 : 0, 
"IS_CLUSTERED", instanceId);
+        clusterMetricsRegistry.setDataPoint(isConnectedToCluster ? 1 : 0, 
"IS_CONNECTED_TO_CLUSTER", instanceId);
+        clusterMetricsRegistry.setDataPoint(connectedNodeCount, 
"CONNECTED_NODE_COUNT", instanceId, connectedNodes);
+        clusterMetricsRegistry.setDataPoint(totalNodeCount, 
"TOTAL_NODE_COUNT", instanceId);
+
+        return clusterMetricsRegistry.getRegistry();
+    }
 }
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
index 4fb1b2271e..9f4bd64c3b 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
@@ -132,6 +132,7 @@ import org.apache.nifi.parameter.StandardParameterContext;
 import org.apache.nifi.processor.VerifiableProcessor;
 import org.apache.nifi.prometheus.util.AbstractMetricsRegistry;
 import org.apache.nifi.prometheus.util.BulletinMetricsRegistry;
+import org.apache.nifi.prometheus.util.ClusterMetricsRegistry;
 import org.apache.nifi.prometheus.util.ConnectionAnalyticsMetricsRegistry;
 import org.apache.nifi.prometheus.util.JvmMetricsRegistry;
 import org.apache.nifi.prometheus.util.NiFiMetricsRegistry;
@@ -438,19 +439,22 @@ public class StandardNiFiServiceFacade implements 
NiFiServiceFacade {
     private final JvmMetricsRegistry jvmMetricsRegistry = new 
JvmMetricsRegistry();
     private final ConnectionAnalyticsMetricsRegistry 
connectionAnalyticsMetricsRegistry = new ConnectionAnalyticsMetricsRegistry();
     private final BulletinMetricsRegistry bulletinMetricsRegistry = new 
BulletinMetricsRegistry();
+    private final ClusterMetricsRegistry clusterMetricsRegistry = new 
ClusterMetricsRegistry();
 
     private final Collection<AbstractMetricsRegistry> configuredRegistries = 
Arrays.asList(
             nifiMetricsRegistry,
             jvmMetricsRegistry,
             connectionAnalyticsMetricsRegistry,
-            bulletinMetricsRegistry
+            bulletinMetricsRegistry,
+            clusterMetricsRegistry
     );
 
     private final Collection<CollectorRegistry> metricsRegistries = 
Arrays.asList(
             nifiMetricsRegistry.getRegistry(),
             jvmMetricsRegistry.getRegistry(),
             connectionAnalyticsMetricsRegistry.getRegistry(),
-            bulletinMetricsRegistry.getRegistry()
+            bulletinMetricsRegistry.getRegistry(),
+            clusterMetricsRegistry.getRegistry()
     );
 
 
@@ -6192,6 +6196,25 @@ public class StandardNiFiServiceFacade implements 
NiFiServiceFacade {
                 );
             }
         }
+
+        // Collect cluster summary metrics
+        int connectedNodeCount = 0;
+        int totalNodeCount = 0;
+        String connectedNodesLabel = "Not clustered";
+        if (clusterCoordinator != null && clusterCoordinator.isConnected()) {
+            final Map<NodeConnectionState, List<NodeIdentifier>> stateMap = 
clusterCoordinator.getConnectionStates();
+            for (final List<NodeIdentifier> nodeList : stateMap.values()) {
+                totalNodeCount += nodeList.size();
+            }
+            final List<NodeIdentifier> connectedNodeIds = 
stateMap.get(NodeConnectionState.CONNECTED);
+            connectedNodeCount = (connectedNodeIds == null) ? 0 : 
connectedNodeIds.size();
+
+            connectedNodesLabel = connectedNodeCount + " / " + totalNodeCount;
+        }
+        final boolean isClustered = clusterCoordinator != null;
+        final boolean isConnectedToCluster = isClustered() && 
clusterCoordinator.isConnected();
+        PrometheusMetricsUtil.createClusterMetrics(clusterMetricsRegistry, 
instanceId, isClustered, isConnectedToCluster, connectedNodesLabel, 
connectedNodeCount, totalNodeCount);
+
         return metricsRegistries;
     }
 
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/request/FlowMetricsRegistry.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/request/FlowMetricsRegistry.java
index c827ae822e..46b0d8033a 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/request/FlowMetricsRegistry.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/request/FlowMetricsRegistry.java
@@ -18,6 +18,7 @@ package org.apache.nifi.web.api.request;
 
 import org.apache.nifi.prometheus.util.AbstractMetricsRegistry;
 import org.apache.nifi.prometheus.util.BulletinMetricsRegistry;
+import org.apache.nifi.prometheus.util.ClusterMetricsRegistry;
 import org.apache.nifi.prometheus.util.ConnectionAnalyticsMetricsRegistry;
 import org.apache.nifi.prometheus.util.JvmMetricsRegistry;
 import org.apache.nifi.prometheus.util.NiFiMetricsRegistry;
@@ -32,7 +33,9 @@ public enum FlowMetricsRegistry {
 
     BULLETIN("BULLETIN", BulletinMetricsRegistry.class),
 
-    CONNECTION("CONNECTION", ConnectionAnalyticsMetricsRegistry.class);
+    CONNECTION("CONNECTION", ConnectionAnalyticsMetricsRegistry.class),
+
+    CLUSTER("CLUSTER", ClusterMetricsRegistry.class);
 
     private final String registry;
 
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestFlowResource.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestFlowResource.java
index 6689a99317..9446df5369 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestFlowResource.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestFlowResource.java
@@ -28,6 +28,7 @@ import io.prometheus.client.CollectorRegistry;
 import io.prometheus.client.exporter.common.TextFormat;
 import org.apache.nifi.metrics.jvm.JmxJvmMetrics;
 import org.apache.nifi.prometheus.util.BulletinMetricsRegistry;
+import org.apache.nifi.prometheus.util.ClusterMetricsRegistry;
 import org.apache.nifi.prometheus.util.ConnectionAnalyticsMetricsRegistry;
 import org.apache.nifi.prometheus.util.JvmMetricsRegistry;
 import org.apache.nifi.prometheus.util.NiFiMetricsRegistry;
@@ -83,6 +84,8 @@ public class TestFlowResource {
     private static final String SAMPLE_LABEL_VALUES_PROCESS_GROUP = 
"ProcessGroup";
     private static final String COMPONENT_TYPE_LABEL = "component_type";
     private static final int COMPONENT_TYPE_VALUE_INDEX = 1;
+    private static final String CLUSTER_TYPE_LABEL = "cluster";
+    private static final String CLUSTER_LABEL_KEY = "instance";
 
     @InjectMocks
     private FlowResource resource = new FlowResource();
@@ -193,12 +196,13 @@ public class TestFlowResource {
         assertThat(metrics, hasKey(ROOT_FIELD_NAME));
 
         final List<Sample> registryList = metrics.get(ROOT_FIELD_NAME);
-        assertThat(registryList, hasSize(9));
+        assertThat(registryList, hasSize(13));
 
         final Map<String, Long> result = getResult(registryList);
         assertThat(3L, equalTo(result.get(SAMPLE_NAME_JVM)));
         assertThat(4L, equalTo(result.get(SAMPLE_LABEL_VALUES_PROCESS_GROUP)));
         assertThat(2L, 
equalTo(result.get(SAMPLE_LABEL_VALUES_ROOT_PROCESS_GROUP)));
+        assertThat(4L, equalTo(result.get(CLUSTER_LABEL_KEY)));
     }
 
     @Test
@@ -317,7 +321,13 @@ public class TestFlowResource {
     }
 
     private String getResultKey(final Sample sample) {
-        return sample.labelNames.contains(COMPONENT_TYPE_LABEL) ? 
sample.labelValues.get(COMPONENT_TYPE_VALUE_INDEX) : SAMPLE_NAME_JVM;
+        if (sample.labelNames.contains(COMPONENT_TYPE_LABEL)) {
+            return sample.labelValues.get(COMPONENT_TYPE_VALUE_INDEX);
+        }
+        if (sample.name.startsWith(CLUSTER_TYPE_LABEL)) {
+            return CLUSTER_LABEL_KEY;
+        }
+        return SAMPLE_NAME_JVM;
     }
 
     private static List<CollectorRegistry> getCollectorRegistriesForJson() {
@@ -327,6 +337,7 @@ public class TestFlowResource {
         registryList.add(getConnectionMetricsRegistry());
         registryList.add(getJvmMetricsRegistry());
         registryList.add(getBulletinMetricsRegistry());
+        registryList.add(getClusterMetricsRegistry());
 
         return registryList;
 
@@ -378,6 +389,18 @@ public class TestFlowResource {
         return bulletinMetricsRegistry.getRegistry();
     }
 
+    private static CollectorRegistry getClusterMetricsRegistry() {
+        final ClusterMetricsRegistry clusterMetricsRegistry = new 
ClusterMetricsRegistry();
+
+        clusterMetricsRegistry.setDataPoint(1, "IS_CLUSTERED", "B1Id");
+        clusterMetricsRegistry.setDataPoint(1, "IS_CONNECTED_TO_CLUSTER", 
"B1Id");
+        clusterMetricsRegistry.setDataPoint(2, "CONNECTED_NODE_COUNT", "B1Id", 
"2 / 3");
+        clusterMetricsRegistry.setDataPoint(3, "TOTAL_NODE_COUNT", "B1Id");
+
+        return clusterMetricsRegistry.getRegistry();
+    }
+
+
     private static class SampleDeserializer extends StdDeserializer<Sample> {
         protected SampleDeserializer() {
             super(Sample.class);

Reply via email to