nifi-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From GitBox <...@apache.org>
Subject [GitHub] [nifi] tpalfy commented on a change in pull request #4420: NIFI-7429 Adding status history for system level metrics
Date Thu, 03 Sep 2020 18:08:57 GMT

tpalfy commented on a change in pull request #4420:
URL: https://github.com/apache/nifi/pull/4420#discussion_r482254565



##########
File path: nifi-api/src/main/java/org/apache/nifi/controller/status/StorageStatus.java
##########
@@ -0,0 +1,69 @@
+/*
+ * 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.controller.status;
+
+/**
+ * The status of a storage repository.
+ */
+public class StorageStatus {

Review comment:
       Shouldn't this be `Cloneable`?

##########
File path: nifi-docs/src/main/asciidoc/user-guide.adoc
##########
@@ -3089,6 +3089,10 @@ recent change to the dataflow has caused a problem and needs to be fixed. The DF
 adjust the flow as needed to fix the problem. While NiFi does not have an "undo" feature, the DFM can make new changes to the
 dataflow that will fix the problem.
 
+Select Node Status History to view instance specific metrics from the last 24 hours or if the instance runs for less time, then
+since it has been started. The status history can help the DFM in troubleshooting performance barriers and provides a general

Review comment:
       I would use `performance issues` instead of `performance barriers` (which is not used too often in this context).

##########
File path: nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/status/history/NodeStatusDescriptor.java
##########
@@ -0,0 +1,192 @@
+/*
+ * 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.controller.status.history;
+
+import org.apache.nifi.controller.status.NodeStatus;
+
+import java.util.List;
+
+public enum NodeStatusDescriptor {
+    FREE_HEAP(
+            "freeHeap",
+            "Free Heap",
+            "The amount of free memory in the heap that can be used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFreeHeap()),
+    USED_HEAP(
+            "usedHeap",
+            "Used Heap",
+            "The amount of used memory in the heap that is used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getUsedHeap()),
+    HEAP_UTILIZATION(
+            "heapUtilization",
+            "Heap Utilization",
+            "The percentage of available heap currently used by the Java virtual machine.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getHeapUtilization(),
+            new ValueReducer<StatusSnapshot, Long>() {
+                @Override
+                public Long reduce(final List<StatusSnapshot> values) {
+                    long sumUtilization = 0L;
+                    int invocations = 0;
+
+                    for (final StatusSnapshot snapshot : values) {
+                        final Long utilization = snapshot.getStatusMetric(HEAP_UTILIZATION.getDescriptor());
+                        if (utilization != null) {
+                            sumUtilization += utilization.longValue();
+                            invocations++;
+                        }
+                    }
+
+                    if (invocations == 0) {
+                        return 0L;
+                    }
+
+                    return sumUtilization / invocations;
+                }
+            }),

Review comment:
       ```suggestion
               new ValueReducer<StatusSnapshot, Long>() {
                   @Override
                   public Long reduce(final List<StatusSnapshot> values) {
                       return (long) values.stream()
                           .map(snapshot -> snapshot.getStatusMetric(HEAP_UTILIZATION.getDescriptor()))
                           .filter(Objects::nonNull)
                           .mapToLong(value -> value)
                           .average()
                           .orElse(0L);
                   }
               }),
   ```

##########
File path: nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/status/history/NodeStatusDescriptor.java
##########
@@ -0,0 +1,192 @@
+/*
+ * 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.controller.status.history;
+
+import org.apache.nifi.controller.status.NodeStatus;
+
+import java.util.List;
+
+public enum NodeStatusDescriptor {
+    FREE_HEAP(
+            "freeHeap",
+            "Free Heap",
+            "The amount of free memory in the heap that can be used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFreeHeap()),
+    USED_HEAP(
+            "usedHeap",
+            "Used Heap",
+            "The amount of used memory in the heap that is used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getUsedHeap()),
+    HEAP_UTILIZATION(
+            "heapUtilization",
+            "Heap Utilization",
+            "The percentage of available heap currently used by the Java virtual machine.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getHeapUtilization(),
+            new ValueReducer<StatusSnapshot, Long>() {
+                @Override
+                public Long reduce(final List<StatusSnapshot> values) {
+                    long sumUtilization = 0L;
+                    int invocations = 0;
+
+                    for (final StatusSnapshot snapshot : values) {
+                        final Long utilization = snapshot.getStatusMetric(HEAP_UTILIZATION.getDescriptor());
+                        if (utilization != null) {
+                            sumUtilization += utilization.longValue();
+                            invocations++;
+                        }
+                    }
+
+                    if (invocations == 0) {
+                        return 0L;
+                    }
+
+                    return sumUtilization / invocations;
+                }
+            }),
+    FREE_NON_HEAP(
+            "freeNonHeap",
+            "Free Non Heap",
+            "The currently available non-heap memory that can be used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFreeNonHeap()),
+    USED_NON_HEAP(
+            "usedNonHeap",
+            "Used Non Heap",
+            "The current memory usage of non-heap memory that is used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getUsedNonHeap()),
+    OPEN_FILE_HANDLERS(
+            "openFileHandlers",
+            "Open File Handlers",
+            "The current number of open file descriptors used by the Java virtual machine.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getOpenFileHandlers()),
+    PROCESSOR_LOAD_AVERAGE(
+            "processorLoadAverage",
+            "Processor Load Average",
+            "The processor load. Every measurement point represents the system load average for the last minute.",
+            MetricDescriptor.Formatter.FRACTION,
+            s -> Double.valueOf(s.getProcessorLoadAverage() * MetricDescriptor.FRACTION_MULTIPLIER).longValue(),
+            new ValueReducer<StatusSnapshot, Long>() {
+                @Override
+                public Long reduce(final List<StatusSnapshot> values) {
+                    long sumLoad = 0L;
+                    int invocations = 0;
+
+                    for (final StatusSnapshot snapshot : values) {
+                        final Long load = snapshot.getStatusMetric(PROCESSOR_LOAD_AVERAGE.getDescriptor());
+                        if (load != null) {
+                            sumLoad += load.longValue();
+                            invocations++;
+                        }
+                    }
+
+                    if (invocations == 0) {
+                        return 0L;
+                    }
+
+                    return sumLoad / invocations;
+                }
+            }),
+    TOTAL_THREADS(
+            "totalThreads",
+            "Number of total threads",
+            "The current number of live threads in the Java virtual machine (both daemon and non-daemon threads).",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getTotalThreads()),
+    EVENT_DRIVEN_THREADS(
+            "eventDrivenThreads",
+            "Number of event driven threads",
+            "The current number of active threads in the event driven thread pool.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getEventDrivenThreads()),
+    TIME_DRIVEN_THREADS(
+            "timeDrivenThreads",
+            "Number of time driven threads",
+            "The current number of active threads in the time driven thread pool.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getTimeDrivenThreads()),
+    FLOW_FILE_REPOSITORY_FREE_SPACE(
+            "flowFileRepositoryFreeSpace",
+            "Flow File Repository Free Space",
+            "The usable space available for use by the underlying storage mechanism.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFlowFileRepositoryFreeSpace()),
+    FLOW_FILE_REPOSITORY_USED_SPACE(
+            "flowFileRepositoryUsedSpace",
+            "Flow File Repository Used Space",
+            "The space in use on the underlying storage mechanism.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFlowFileRepositoryUsedSpace()),
+    CONTENT_REPOSITORY_FREE_SPACE(
+            "contentRepositoryFreeSpace",
+            "Sum content Repository Free Space",
+            "The usable space available for use by the underlying storage mechanisms.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getContentRepositories().stream().map(r -> r.getFreeSpace()).reduce(0L, (a, b) -> a + b)),

Review comment:
       ```suggestion
               s -> s.getContentRepositories().stream().mapToLong(StorageStatus::getFreeSpace).sum()),
   ```

##########
File path: nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
##########
@@ -1057,6 +1058,39 @@ public Response deleteNode(
     // history
     // -------
 
+    @GET
+    @Consumes(MediaType.WILDCARD)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("status/history")
+    @ApiOperation(
+            value = "Gets configuration history for the node",
+            notes = NON_GUARANTEED_ENDPOINT,
+            response = ComponentHistoryEntity.class,
+            authorizations = {
+                    @Authorization(value = "Read - /controller")
+            }
+    )
+    @ApiResponses(
+            value = {
+                    @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
+                    @ApiResponse(code = 401, message = "Client could not be authenticated."),
+                    @ApiResponse(code = 403, message = "Client is not authorized to make this request."),
+                    @ApiResponse(code = 404, message = "The specified resource could not be found."),
+                    @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
+            }
+    )
+    public Response getNodeHistory() {

Review comment:
       ```suggestion
       public Response getNodeStatusHistory() {
   ```

##########
File path: nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/status/history/NodeStatusDescriptor.java
##########
@@ -0,0 +1,192 @@
+/*
+ * 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.controller.status.history;
+
+import org.apache.nifi.controller.status.NodeStatus;
+
+import java.util.List;
+
+public enum NodeStatusDescriptor {
+    FREE_HEAP(
+            "freeHeap",
+            "Free Heap",
+            "The amount of free memory in the heap that can be used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFreeHeap()),
+    USED_HEAP(
+            "usedHeap",
+            "Used Heap",
+            "The amount of used memory in the heap that is used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getUsedHeap()),
+    HEAP_UTILIZATION(
+            "heapUtilization",
+            "Heap Utilization",
+            "The percentage of available heap currently used by the Java virtual machine.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getHeapUtilization(),
+            new ValueReducer<StatusSnapshot, Long>() {
+                @Override
+                public Long reduce(final List<StatusSnapshot> values) {
+                    long sumUtilization = 0L;
+                    int invocations = 0;
+
+                    for (final StatusSnapshot snapshot : values) {
+                        final Long utilization = snapshot.getStatusMetric(HEAP_UTILIZATION.getDescriptor());
+                        if (utilization != null) {
+                            sumUtilization += utilization.longValue();
+                            invocations++;
+                        }
+                    }
+
+                    if (invocations == 0) {
+                        return 0L;
+                    }
+
+                    return sumUtilization / invocations;
+                }
+            }),
+    FREE_NON_HEAP(
+            "freeNonHeap",
+            "Free Non Heap",
+            "The currently available non-heap memory that can be used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFreeNonHeap()),
+    USED_NON_HEAP(
+            "usedNonHeap",
+            "Used Non Heap",
+            "The current memory usage of non-heap memory that is used by the Java virtual machine.",

Review comment:
       ```suggestion
               "The current usage of non-heap memory that is used by the Java virtual machine.",
   ```

##########
File path: nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/status/history/NodeStatusDescriptor.java
##########
@@ -0,0 +1,192 @@
+/*
+ * 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.controller.status.history;
+
+import org.apache.nifi.controller.status.NodeStatus;
+
+import java.util.List;
+
+public enum NodeStatusDescriptor {
+    FREE_HEAP(
+            "freeHeap",
+            "Free Heap",
+            "The amount of free memory in the heap that can be used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFreeHeap()),
+    USED_HEAP(
+            "usedHeap",
+            "Used Heap",
+            "The amount of used memory in the heap that is used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getUsedHeap()),
+    HEAP_UTILIZATION(
+            "heapUtilization",
+            "Heap Utilization",
+            "The percentage of available heap currently used by the Java virtual machine.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getHeapUtilization(),
+            new ValueReducer<StatusSnapshot, Long>() {
+                @Override
+                public Long reduce(final List<StatusSnapshot> values) {
+                    long sumUtilization = 0L;
+                    int invocations = 0;
+
+                    for (final StatusSnapshot snapshot : values) {
+                        final Long utilization = snapshot.getStatusMetric(HEAP_UTILIZATION.getDescriptor());
+                        if (utilization != null) {
+                            sumUtilization += utilization.longValue();
+                            invocations++;
+                        }
+                    }
+
+                    if (invocations == 0) {
+                        return 0L;
+                    }
+
+                    return sumUtilization / invocations;
+                }
+            }),
+    FREE_NON_HEAP(
+            "freeNonHeap",
+            "Free Non Heap",
+            "The currently available non-heap memory that can be used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFreeNonHeap()),
+    USED_NON_HEAP(
+            "usedNonHeap",
+            "Used Non Heap",
+            "The current memory usage of non-heap memory that is used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getUsedNonHeap()),
+    OPEN_FILE_HANDLERS(
+            "openFileHandlers",
+            "Open File Handlers",
+            "The current number of open file descriptors used by the Java virtual machine.",

Review comment:
       `file handle` is a more accurate term than `file handler`
   ```suggestion
               "The current number of open file handles used by the Java virtual machine.",
   ```

##########
File path: nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/status/history/NodeStatusDescriptor.java
##########
@@ -0,0 +1,192 @@
+/*
+ * 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.controller.status.history;
+
+import org.apache.nifi.controller.status.NodeStatus;
+
+import java.util.List;
+
+public enum NodeStatusDescriptor {
+    FREE_HEAP(
+            "freeHeap",
+            "Free Heap",
+            "The amount of free memory in the heap that can be used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFreeHeap()),
+    USED_HEAP(
+            "usedHeap",
+            "Used Heap",
+            "The amount of used memory in the heap that is used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getUsedHeap()),
+    HEAP_UTILIZATION(
+            "heapUtilization",
+            "Heap Utilization",
+            "The percentage of available heap currently used by the Java virtual machine.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getHeapUtilization(),
+            new ValueReducer<StatusSnapshot, Long>() {
+                @Override
+                public Long reduce(final List<StatusSnapshot> values) {
+                    long sumUtilization = 0L;
+                    int invocations = 0;
+
+                    for (final StatusSnapshot snapshot : values) {
+                        final Long utilization = snapshot.getStatusMetric(HEAP_UTILIZATION.getDescriptor());
+                        if (utilization != null) {
+                            sumUtilization += utilization.longValue();
+                            invocations++;
+                        }
+                    }
+
+                    if (invocations == 0) {
+                        return 0L;
+                    }
+
+                    return sumUtilization / invocations;
+                }
+            }),
+    FREE_NON_HEAP(
+            "freeNonHeap",
+            "Free Non Heap",
+            "The currently available non-heap memory that can be used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFreeNonHeap()),
+    USED_NON_HEAP(
+            "usedNonHeap",
+            "Used Non Heap",
+            "The current memory usage of non-heap memory that is used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getUsedNonHeap()),
+    OPEN_FILE_HANDLERS(
+            "openFileHandlers",
+            "Open File Handlers",
+            "The current number of open file descriptors used by the Java virtual machine.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getOpenFileHandlers()),
+    PROCESSOR_LOAD_AVERAGE(
+            "processorLoadAverage",
+            "Processor Load Average",
+            "The processor load. Every measurement point represents the system load average for the last minute.",
+            MetricDescriptor.Formatter.FRACTION,
+            s -> Double.valueOf(s.getProcessorLoadAverage() * MetricDescriptor.FRACTION_MULTIPLIER).longValue(),
+            new ValueReducer<StatusSnapshot, Long>() {
+                @Override
+                public Long reduce(final List<StatusSnapshot> values) {
+                    long sumLoad = 0L;
+                    int invocations = 0;
+
+                    for (final StatusSnapshot snapshot : values) {
+                        final Long load = snapshot.getStatusMetric(PROCESSOR_LOAD_AVERAGE.getDescriptor());
+                        if (load != null) {
+                            sumLoad += load.longValue();
+                            invocations++;
+                        }
+                    }
+
+                    if (invocations == 0) {
+                        return 0L;
+                    }
+
+                    return sumLoad / invocations;
+                }
+            }),

Review comment:
       ```suggestion
               new ValueReducer<StatusSnapshot, Long>() {
                   @Override
                   public Long reduce(final List<StatusSnapshot> values) {
                       return (long) values.stream()
                           .map(snapshot -> snapshot.getStatusMetric(PROCESSOR_LOAD_AVERAGE.getDescriptor()))
                           .filter(Objects::nonNull)
                           .mapToLong(value -> value)
                           .average()
                           .orElse(0L);
                   }
               }),
   ```

##########
File path: nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/status/history/NodeStatusDescriptor.java
##########
@@ -0,0 +1,192 @@
+/*
+ * 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.controller.status.history;
+
+import org.apache.nifi.controller.status.NodeStatus;
+
+import java.util.List;
+
+public enum NodeStatusDescriptor {
+    FREE_HEAP(
+            "freeHeap",
+            "Free Heap",
+            "The amount of free memory in the heap that can be used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFreeHeap()),
+    USED_HEAP(
+            "usedHeap",
+            "Used Heap",
+            "The amount of used memory in the heap that is used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getUsedHeap()),
+    HEAP_UTILIZATION(
+            "heapUtilization",
+            "Heap Utilization",
+            "The percentage of available heap currently used by the Java virtual machine.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getHeapUtilization(),
+            new ValueReducer<StatusSnapshot, Long>() {
+                @Override
+                public Long reduce(final List<StatusSnapshot> values) {
+                    long sumUtilization = 0L;
+                    int invocations = 0;
+
+                    for (final StatusSnapshot snapshot : values) {
+                        final Long utilization = snapshot.getStatusMetric(HEAP_UTILIZATION.getDescriptor());
+                        if (utilization != null) {
+                            sumUtilization += utilization.longValue();
+                            invocations++;
+                        }
+                    }
+
+                    if (invocations == 0) {
+                        return 0L;
+                    }
+
+                    return sumUtilization / invocations;
+                }
+            }),
+    FREE_NON_HEAP(
+            "freeNonHeap",
+            "Free Non Heap",
+            "The currently available non-heap memory that can be used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFreeNonHeap()),
+    USED_NON_HEAP(
+            "usedNonHeap",
+            "Used Non Heap",
+            "The current memory usage of non-heap memory that is used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getUsedNonHeap()),
+    OPEN_FILE_HANDLERS(
+            "openFileHandlers",
+            "Open File Handlers",
+            "The current number of open file descriptors used by the Java virtual machine.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getOpenFileHandlers()),
+    PROCESSOR_LOAD_AVERAGE(
+            "processorLoadAverage",
+            "Processor Load Average",
+            "The processor load. Every measurement point represents the system load average for the last minute.",
+            MetricDescriptor.Formatter.FRACTION,
+            s -> Double.valueOf(s.getProcessorLoadAverage() * MetricDescriptor.FRACTION_MULTIPLIER).longValue(),
+            new ValueReducer<StatusSnapshot, Long>() {
+                @Override
+                public Long reduce(final List<StatusSnapshot> values) {
+                    long sumLoad = 0L;
+                    int invocations = 0;
+
+                    for (final StatusSnapshot snapshot : values) {
+                        final Long load = snapshot.getStatusMetric(PROCESSOR_LOAD_AVERAGE.getDescriptor());
+                        if (load != null) {
+                            sumLoad += load.longValue();
+                            invocations++;
+                        }
+                    }
+
+                    if (invocations == 0) {
+                        return 0L;
+                    }
+
+                    return sumLoad / invocations;
+                }
+            }),
+    TOTAL_THREADS(
+            "totalThreads",
+            "Number of total threads",
+            "The current number of live threads in the Java virtual machine (both daemon and non-daemon threads).",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getTotalThreads()),
+    EVENT_DRIVEN_THREADS(
+            "eventDrivenThreads",
+            "Number of event driven threads",
+            "The current number of active threads in the event driven thread pool.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getEventDrivenThreads()),
+    TIME_DRIVEN_THREADS(
+            "timeDrivenThreads",
+            "Number of time driven threads",
+            "The current number of active threads in the time driven thread pool.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getTimeDrivenThreads()),
+    FLOW_FILE_REPOSITORY_FREE_SPACE(
+            "flowFileRepositoryFreeSpace",
+            "Flow File Repository Free Space",
+            "The usable space available for use by the underlying storage mechanism.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFlowFileRepositoryFreeSpace()),
+    FLOW_FILE_REPOSITORY_USED_SPACE(
+            "flowFileRepositoryUsedSpace",
+            "Flow File Repository Used Space",
+            "The space in use on the underlying storage mechanism.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFlowFileRepositoryUsedSpace()),
+    CONTENT_REPOSITORY_FREE_SPACE(
+            "contentRepositoryFreeSpace",
+            "Sum content Repository Free Space",
+            "The usable space available for use by the underlying storage mechanisms.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getContentRepositories().stream().map(r -> r.getFreeSpace()).reduce(0L, (a, b) -> a + b)),
+    CONTENT_REPOSITORY_USED_SPACE(
+            "contentRepositoryUsedSpace",
+            "Sum content Repository Used Space",
+            "The space in use on the underlying storage mechanisms.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getContentRepositories().stream().map(r -> r.getUsedSpace()).reduce(0L, (a, b) -> a + b)),

Review comment:
       ```suggestion
               s -> s.getContentRepositories().stream().mapToLong(StorageStatus::getUsedSpace).sum()),
   ```

##########
File path: nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/status/history/VolatileComponentStatusRepository.java
##########
@@ -164,6 +183,182 @@ public StatusHistory getRemoteProcessGroupStatusHistory(final String remoteGroup
         return getStatusHistory(remoteGroupId, true, DEFAULT_RPG_METRICS, start, end, preferredDataPoints);
     }
 
+    @Override
+    public StatusHistory getNodeStatusHistory() {

Review comment:
       Could this be covered with unit tests?

##########
File path: nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/status/history/NodeStatusDescriptor.java
##########
@@ -0,0 +1,192 @@
+/*
+ * 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.controller.status.history;
+
+import org.apache.nifi.controller.status.NodeStatus;
+
+import java.util.List;
+
+public enum NodeStatusDescriptor {
+    FREE_HEAP(
+            "freeHeap",
+            "Free Heap",
+            "The amount of free memory in the heap that can be used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFreeHeap()),
+    USED_HEAP(
+            "usedHeap",
+            "Used Heap",
+            "The amount of used memory in the heap that is used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getUsedHeap()),
+    HEAP_UTILIZATION(
+            "heapUtilization",
+            "Heap Utilization",
+            "The percentage of available heap currently used by the Java virtual machine.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getHeapUtilization(),
+            new ValueReducer<StatusSnapshot, Long>() {
+                @Override
+                public Long reduce(final List<StatusSnapshot> values) {
+                    long sumUtilization = 0L;
+                    int invocations = 0;
+
+                    for (final StatusSnapshot snapshot : values) {
+                        final Long utilization = snapshot.getStatusMetric(HEAP_UTILIZATION.getDescriptor());
+                        if (utilization != null) {
+                            sumUtilization += utilization.longValue();
+                            invocations++;
+                        }
+                    }
+
+                    if (invocations == 0) {
+                        return 0L;
+                    }
+
+                    return sumUtilization / invocations;
+                }
+            }),
+    FREE_NON_HEAP(
+            "freeNonHeap",
+            "Free Non Heap",
+            "The currently available non-heap memory that can be used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFreeNonHeap()),
+    USED_NON_HEAP(
+            "usedNonHeap",
+            "Used Non Heap",
+            "The current memory usage of non-heap memory that is used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getUsedNonHeap()),
+    OPEN_FILE_HANDLERS(
+            "openFileHandlers",
+            "Open File Handlers",
+            "The current number of open file descriptors used by the Java virtual machine.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getOpenFileHandlers()),
+    PROCESSOR_LOAD_AVERAGE(
+            "processorLoadAverage",
+            "Processor Load Average",
+            "The processor load. Every measurement point represents the system load average for the last minute.",
+            MetricDescriptor.Formatter.FRACTION,
+            s -> Double.valueOf(s.getProcessorLoadAverage() * MetricDescriptor.FRACTION_MULTIPLIER).longValue(),
+            new ValueReducer<StatusSnapshot, Long>() {
+                @Override
+                public Long reduce(final List<StatusSnapshot> values) {
+                    long sumLoad = 0L;
+                    int invocations = 0;
+
+                    for (final StatusSnapshot snapshot : values) {
+                        final Long load = snapshot.getStatusMetric(PROCESSOR_LOAD_AVERAGE.getDescriptor());
+                        if (load != null) {
+                            sumLoad += load.longValue();
+                            invocations++;
+                        }
+                    }
+
+                    if (invocations == 0) {
+                        return 0L;
+                    }
+
+                    return sumLoad / invocations;
+                }
+            }),
+    TOTAL_THREADS(
+            "totalThreads",
+            "Number of total threads",
+            "The current number of live threads in the Java virtual machine (both daemon and non-daemon threads).",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getTotalThreads()),
+    EVENT_DRIVEN_THREADS(
+            "eventDrivenThreads",
+            "Number of event driven threads",
+            "The current number of active threads in the event driven thread pool.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getEventDrivenThreads()),
+    TIME_DRIVEN_THREADS(
+            "timeDrivenThreads",
+            "Number of time driven threads",
+            "The current number of active threads in the time driven thread pool.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getTimeDrivenThreads()),
+    FLOW_FILE_REPOSITORY_FREE_SPACE(
+            "flowFileRepositoryFreeSpace",
+            "Flow File Repository Free Space",
+            "The usable space available for use by the underlying storage mechanism.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFlowFileRepositoryFreeSpace()),
+    FLOW_FILE_REPOSITORY_USED_SPACE(
+            "flowFileRepositoryUsedSpace",
+            "Flow File Repository Used Space",
+            "The space in use on the underlying storage mechanism.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFlowFileRepositoryUsedSpace()),
+    CONTENT_REPOSITORY_FREE_SPACE(
+            "contentRepositoryFreeSpace",
+            "Sum content Repository Free Space",
+            "The usable space available for use by the underlying storage mechanisms.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getContentRepositories().stream().map(r -> r.getFreeSpace()).reduce(0L, (a, b) -> a + b)),
+    CONTENT_REPOSITORY_USED_SPACE(
+            "contentRepositoryUsedSpace",
+            "Sum content Repository Used Space",
+            "The space in use on the underlying storage mechanisms.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getContentRepositories().stream().map(r -> r.getUsedSpace()).reduce(0L, (a, b) -> a + b)),
+    PROVENANCE_REPOSITORY_FREE_SPACE(
+            "provenanceRepositoryFreeSpace",
+            "Sum provenance Repository Free Space",
+            "The usable space available for use by the underlying storage mechanisms.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getProvenanceRepositories().stream().map(r -> r.getFreeSpace()).reduce(0L, (a, b) -> a + b)),

Review comment:
       ```suggestion
               s -> s.getProvenanceRepositories().stream().mapToLong(StorageStatus::getFreeSpace).sum()),
   ```

##########
File path: nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/status/history/NodeStatusDescriptor.java
##########
@@ -0,0 +1,192 @@
+/*
+ * 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.controller.status.history;
+
+import org.apache.nifi.controller.status.NodeStatus;
+
+import java.util.List;
+
+public enum NodeStatusDescriptor {
+    FREE_HEAP(
+            "freeHeap",
+            "Free Heap",
+            "The amount of free memory in the heap that can be used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFreeHeap()),
+    USED_HEAP(
+            "usedHeap",
+            "Used Heap",
+            "The amount of used memory in the heap that is used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getUsedHeap()),
+    HEAP_UTILIZATION(
+            "heapUtilization",
+            "Heap Utilization",
+            "The percentage of available heap currently used by the Java virtual machine.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getHeapUtilization(),
+            new ValueReducer<StatusSnapshot, Long>() {
+                @Override
+                public Long reduce(final List<StatusSnapshot> values) {
+                    long sumUtilization = 0L;
+                    int invocations = 0;
+
+                    for (final StatusSnapshot snapshot : values) {
+                        final Long utilization = snapshot.getStatusMetric(HEAP_UTILIZATION.getDescriptor());
+                        if (utilization != null) {
+                            sumUtilization += utilization.longValue();
+                            invocations++;
+                        }
+                    }
+
+                    if (invocations == 0) {
+                        return 0L;
+                    }
+
+                    return sumUtilization / invocations;
+                }
+            }),
+    FREE_NON_HEAP(
+            "freeNonHeap",
+            "Free Non Heap",
+            "The currently available non-heap memory that can be used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFreeNonHeap()),
+    USED_NON_HEAP(
+            "usedNonHeap",
+            "Used Non Heap",
+            "The current memory usage of non-heap memory that is used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getUsedNonHeap()),
+    OPEN_FILE_HANDLERS(
+            "openFileHandlers",
+            "Open File Handlers",
+            "The current number of open file descriptors used by the Java virtual machine.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getOpenFileHandlers()),
+    PROCESSOR_LOAD_AVERAGE(
+            "processorLoadAverage",
+            "Processor Load Average",
+            "The processor load. Every measurement point represents the system load average for the last minute.",
+            MetricDescriptor.Formatter.FRACTION,
+            s -> Double.valueOf(s.getProcessorLoadAverage() * MetricDescriptor.FRACTION_MULTIPLIER).longValue(),
+            new ValueReducer<StatusSnapshot, Long>() {
+                @Override
+                public Long reduce(final List<StatusSnapshot> values) {
+                    long sumLoad = 0L;
+                    int invocations = 0;
+
+                    for (final StatusSnapshot snapshot : values) {
+                        final Long load = snapshot.getStatusMetric(PROCESSOR_LOAD_AVERAGE.getDescriptor());
+                        if (load != null) {
+                            sumLoad += load.longValue();
+                            invocations++;
+                        }
+                    }
+
+                    if (invocations == 0) {
+                        return 0L;
+                    }
+
+                    return sumLoad / invocations;
+                }
+            }),
+    TOTAL_THREADS(
+            "totalThreads",
+            "Number of total threads",
+            "The current number of live threads in the Java virtual machine (both daemon and non-daemon threads).",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getTotalThreads()),
+    EVENT_DRIVEN_THREADS(
+            "eventDrivenThreads",
+            "Number of event driven threads",
+            "The current number of active threads in the event driven thread pool.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getEventDrivenThreads()),
+    TIME_DRIVEN_THREADS(
+            "timeDrivenThreads",
+            "Number of time driven threads",
+            "The current number of active threads in the time driven thread pool.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getTimeDrivenThreads()),
+    FLOW_FILE_REPOSITORY_FREE_SPACE(
+            "flowFileRepositoryFreeSpace",
+            "Flow File Repository Free Space",
+            "The usable space available for use by the underlying storage mechanism.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFlowFileRepositoryFreeSpace()),
+    FLOW_FILE_REPOSITORY_USED_SPACE(
+            "flowFileRepositoryUsedSpace",
+            "Flow File Repository Used Space",
+            "The space in use on the underlying storage mechanism.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFlowFileRepositoryUsedSpace()),
+    CONTENT_REPOSITORY_FREE_SPACE(
+            "contentRepositoryFreeSpace",
+            "Sum content Repository Free Space",
+            "The usable space available for use by the underlying storage mechanisms.",

Review comment:
       Has the same description as `FLOW_FILE_REPOSITORY_FREE_SPACE`.

##########
File path: nifi-api/src/main/java/org/apache/nifi/controller/status/NodeStatus.java
##########
@@ -0,0 +1,229 @@
+/*
+ * 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.controller.status;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The status of a NiFi node.
+ */
+public class NodeStatus implements Cloneable {
+    private long createdAtInMs;
+
+    private long freeHeap;
+    private long usedHeap;
+    private long heapUtilization;
+    private long freeNonHeap;
+    private long usedNonHeap;
+
+    private long openFileHandlers;
+    private double processorLoadAverage;
+    private long uptime;
+
+    private long totalThreads;
+    private long eventDrivenThreads;
+    private long timeDrivenThreads;

Review comment:
       ```suggestion
       private long timerDrivenThreads;
   ```

##########
File path: nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
##########
@@ -1057,6 +1058,39 @@ public Response deleteNode(
     // history
     // -------
 
+    @GET
+    @Consumes(MediaType.WILDCARD)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("status/history")
+    @ApiOperation(
+            value = "Gets configuration history for the node",

Review comment:
       ```suggestion
               value = "Gets status history for the node",
   ```

##########
File path: nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/status/history/NodeStatusDescriptor.java
##########
@@ -0,0 +1,192 @@
+/*
+ * 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.controller.status.history;
+
+import org.apache.nifi.controller.status.NodeStatus;
+
+import java.util.List;
+
+public enum NodeStatusDescriptor {
+    FREE_HEAP(
+            "freeHeap",
+            "Free Heap",
+            "The amount of free memory in the heap that can be used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFreeHeap()),
+    USED_HEAP(
+            "usedHeap",
+            "Used Heap",
+            "The amount of used memory in the heap that is used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getUsedHeap()),
+    HEAP_UTILIZATION(
+            "heapUtilization",
+            "Heap Utilization",
+            "The percentage of available heap currently used by the Java virtual machine.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getHeapUtilization(),
+            new ValueReducer<StatusSnapshot, Long>() {
+                @Override
+                public Long reduce(final List<StatusSnapshot> values) {
+                    long sumUtilization = 0L;
+                    int invocations = 0;
+
+                    for (final StatusSnapshot snapshot : values) {
+                        final Long utilization = snapshot.getStatusMetric(HEAP_UTILIZATION.getDescriptor());
+                        if (utilization != null) {
+                            sumUtilization += utilization.longValue();
+                            invocations++;
+                        }
+                    }
+
+                    if (invocations == 0) {
+                        return 0L;
+                    }
+
+                    return sumUtilization / invocations;
+                }
+            }),
+    FREE_NON_HEAP(
+            "freeNonHeap",
+            "Free Non Heap",
+            "The currently available non-heap memory that can be used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFreeNonHeap()),
+    USED_NON_HEAP(
+            "usedNonHeap",
+            "Used Non Heap",
+            "The current memory usage of non-heap memory that is used by the Java virtual machine.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getUsedNonHeap()),
+    OPEN_FILE_HANDLERS(
+            "openFileHandlers",
+            "Open File Handlers",
+            "The current number of open file descriptors used by the Java virtual machine.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getOpenFileHandlers()),
+    PROCESSOR_LOAD_AVERAGE(
+            "processorLoadAverage",
+            "Processor Load Average",
+            "The processor load. Every measurement point represents the system load average for the last minute.",
+            MetricDescriptor.Formatter.FRACTION,
+            s -> Double.valueOf(s.getProcessorLoadAverage() * MetricDescriptor.FRACTION_MULTIPLIER).longValue(),
+            new ValueReducer<StatusSnapshot, Long>() {
+                @Override
+                public Long reduce(final List<StatusSnapshot> values) {
+                    long sumLoad = 0L;
+                    int invocations = 0;
+
+                    for (final StatusSnapshot snapshot : values) {
+                        final Long load = snapshot.getStatusMetric(PROCESSOR_LOAD_AVERAGE.getDescriptor());
+                        if (load != null) {
+                            sumLoad += load.longValue();
+                            invocations++;
+                        }
+                    }
+
+                    if (invocations == 0) {
+                        return 0L;
+                    }
+
+                    return sumLoad / invocations;
+                }
+            }),
+    TOTAL_THREADS(
+            "totalThreads",
+            "Number of total threads",
+            "The current number of live threads in the Java virtual machine (both daemon and non-daemon threads).",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getTotalThreads()),
+    EVENT_DRIVEN_THREADS(
+            "eventDrivenThreads",
+            "Number of event driven threads",
+            "The current number of active threads in the event driven thread pool.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getEventDrivenThreads()),
+    TIME_DRIVEN_THREADS(
+            "timeDrivenThreads",
+            "Number of time driven threads",
+            "The current number of active threads in the time driven thread pool.",
+            MetricDescriptor.Formatter.COUNT,
+            s -> s.getTimeDrivenThreads()),
+    FLOW_FILE_REPOSITORY_FREE_SPACE(
+            "flowFileRepositoryFreeSpace",
+            "Flow File Repository Free Space",
+            "The usable space available for use by the underlying storage mechanism.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFlowFileRepositoryFreeSpace()),
+    FLOW_FILE_REPOSITORY_USED_SPACE(
+            "flowFileRepositoryUsedSpace",
+            "Flow File Repository Used Space",
+            "The space in use on the underlying storage mechanism.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getFlowFileRepositoryUsedSpace()),
+    CONTENT_REPOSITORY_FREE_SPACE(
+            "contentRepositoryFreeSpace",
+            "Sum content Repository Free Space",
+            "The usable space available for use by the underlying storage mechanisms.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getContentRepositories().stream().map(r -> r.getFreeSpace()).reduce(0L, (a, b) -> a + b)),
+    CONTENT_REPOSITORY_USED_SPACE(
+            "contentRepositoryUsedSpace",
+            "Sum content Repository Used Space",
+            "The space in use on the underlying storage mechanisms.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getContentRepositories().stream().map(r -> r.getUsedSpace()).reduce(0L, (a, b) -> a + b)),
+    PROVENANCE_REPOSITORY_FREE_SPACE(
+            "provenanceRepositoryFreeSpace",
+            "Sum provenance Repository Free Space",
+            "The usable space available for use by the underlying storage mechanisms.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getProvenanceRepositories().stream().map(r -> r.getFreeSpace()).reduce(0L, (a, b) -> a + b)),
+    PROVENANCE_REPOSITORY_USED_SPACE(
+            "provenanceRepositoryUsedSpace",
+            "Sum provenance Repository Used Space",
+            "The space in use on the underlying storage mechanisms.",
+            MetricDescriptor.Formatter.DATA_SIZE,
+            s -> s.getProvenanceRepositories().stream().map(r -> r.getUsedSpace()).reduce(0L, (a, b) -> a + b));

Review comment:
       ```suggestion
               s -> s.getProvenanceRepositories().stream().mapToLong(StorageStatus::getUsedSpace).sum()),
   ```

##########
File path: nifi-api/src/main/java/org/apache/nifi/controller/status/NodeStatus.java
##########
@@ -0,0 +1,229 @@
+/*
+ * 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.controller.status;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The status of a NiFi node.
+ */
+public class NodeStatus implements Cloneable {

Review comment:
       Is there a reason for the new DTO classes? Couldn't we use the original `SystemDiagnostics` and `StorageStatus` instead?

##########
File path: nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/status/history/StatusHistoryUtil.java
##########
@@ -76,14 +76,14 @@ public static StatusDescriptorDTO createStatusDescriptorDto(final MetricDescript
 
     public static List<StatusDescriptorDTO> createFieldDescriptorDtos(final Collection<MetricDescriptor<?>> metricDescriptors) {
         final List<StatusDescriptorDTO> dtos = new ArrayList<>();
+        final Map<Integer, MetricDescriptor<?>> orderedDescriptors = new HashMap<>();
 
-        final Set<MetricDescriptor<?>> allDescriptors = new LinkedHashSet<>();
         for (final MetricDescriptor<?> metricDescriptor : metricDescriptors) {

Review comment:
       Is there a reason why this logic is this complex?
   `orderedDescriptors.get(i)` indicates that `metricDescriptors` cannot have a gap in their `getMetricIdentifier()` values.
   Not sure if it's a good idea to rely on that. But if absolutely can, we could simply go with:
   ```java
       public static List<StatusDescriptorDTO> createFieldDescriptorDtos(final Collection<MetricDescriptor<?>> metricDescriptors) {
           final List<StatusDescriptorDTO> dtos = new ArrayList<>();
   
           for (final MetricDescriptor<?> metricDescriptor : metricDescriptors) {
               dtos.add(metricDescriptor.getMetricIdentifier(), createStatusDescriptorDto(metricDescriptor));
           }
   
           return dtos;
       }
   ```
   Otherwise we might simply want to call a `sort` on `dtos`.




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

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



Mime
View raw message