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

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


The following commit(s) were added to refs/heads/master by this push:
     new 8b1a23a  NIFI-7539: When capturing diagnostics information, capture a 
thread dump once and then provide this information to ProcessorNode when 
capturing active threads. Previously, each processor captured a thread dump 
itself. When this is done thousands of times it can result in a very long delay.
8b1a23a is described below

commit 8b1a23a99cc25c8395117b609fd8e16c88f9518d
Author: Mark Payne <[email protected]>
AuthorDate: Tue Jun 16 14:21:44 2020 -0400

    NIFI-7539: When capturing diagnostics information, capture a thread dump 
once and then provide this information to ProcessorNode when capturing active 
threads. Previously, each processor captured a thread dump itself. When this is 
done thousands of times it can result in a very long delay.
---
 .../org/apache/nifi/controller/ProcessorNode.java  |  4 +-
 .../org/apache/nifi/controller/ThreadDetails.java  | 51 ++++++++++++++++++++++
 .../nifi/controller/StandardProcessorNode.java     | 12 ++---
 .../bootstrap/tasks/LongRunningProcessorTask.java  |  4 +-
 .../org/apache/nifi/web/api/dto/DtoFactory.java    |  3 +-
 5 files changed, 61 insertions(+), 13 deletions(-)

diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ProcessorNode.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ProcessorNode.java
index 9601fe5..77308cb 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ProcessorNode.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ProcessorNode.java
@@ -73,12 +73,12 @@ public abstract class ProcessorNode extends 
AbstractComponentNode implements Con
 
     public abstract Requirement getInputRequirement();
 
-    public abstract List<ActiveThreadInfo> getActiveThreads();
+    public abstract List<ActiveThreadInfo> getActiveThreads(ThreadDetails 
threadDetails);
 
     /**
      * Returns the number of threads that are still 'active' in this Processor 
but have been terminated
      * via {@link #terminate()}. To understand more about these threads, such 
as their stack traces and
-     * how long they have been active, one can use {@link #getActiveThreads()} 
and then filter the results
+     * how long they have been active, one can use {@link 
#getActiveThreads(ThreadDetails)} and then filter the results
      * to include only those {@link ActiveThreadInfo} objects for which the 
thread is terminated. For example:
      * {@code 
getActiveThreads().stream().filter(ActiveThreadInfo::isTerminated).collect(Collectors.toList());}
      *
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ThreadDetails.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ThreadDetails.java
new file mode 100644
index 0000000..9a6348c
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ThreadDetails.java
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+
+public class ThreadDetails {
+    private final ThreadInfo[] threadInfos;
+    private final long[] deadlockedThreadIds;
+    private final long[] monitorDeadlockThreadIds;
+
+    private ThreadDetails(final ThreadMXBean mbean) {
+        threadInfos = mbean.dumpAllThreads(true, true);
+        deadlockedThreadIds = mbean.findDeadlockedThreads();
+        monitorDeadlockThreadIds = mbean.findMonitorDeadlockedThreads();
+    }
+
+    public ThreadInfo[] getThreadInfos() {
+        return threadInfos;
+    }
+
+    public long[] getDeadlockedThreadIds() {
+        return deadlockedThreadIds;
+    }
+
+    public long[] getMonitorDeadlockThreadIds() {
+        return monitorDeadlockThreadIds;
+    }
+
+    public static ThreadDetails capture() {
+        final ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
+        return new ThreadDetails(mbean);
+    }
+}
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java
index 96402a4..1cc3605 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java
@@ -76,9 +76,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.util.Assert;
 
-import java.lang.management.ManagementFactory;
 import java.lang.management.ThreadInfo;
-import java.lang.management.ThreadMXBean;
 import java.lang.reflect.InvocationTargetException;
 import java.net.URL;
 import java.util.ArrayList;
@@ -1401,14 +1399,10 @@ public class StandardProcessorNode extends 
ProcessorNode implements Connectable
     }
 
     @Override
-    public synchronized List<ActiveThreadInfo> getActiveThreads() {
+    public synchronized List<ActiveThreadInfo> getActiveThreads(final 
ThreadDetails threadDetails) {
         final long now = System.currentTimeMillis();
-        final ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
-        final ThreadInfo[] infos = mbean.dumpAllThreads(true, true);
-        final long[] deadlockedThreadIds = mbean.findDeadlockedThreads();
-        final long[] monitorDeadlockThreadIds = 
mbean.findMonitorDeadlockedThreads();
 
-        final Map<Long, ThreadInfo> threadInfoMap = Stream.of(infos)
+        final Map<Long, ThreadInfo> threadInfoMap = 
Stream.of(threadDetails.getThreadInfos())
             .collect(Collectors.toMap(ThreadInfo::getThreadId, 
Function.identity(), (a, b) -> a));
 
         final List<ActiveThreadInfo> threadList = new 
ArrayList<>(activeThreads.size());
@@ -1419,7 +1413,7 @@ public class StandardProcessorNode extends ProcessorNode 
implements Connectable
             final long activeMillis = now - timestamp;
             final ThreadInfo threadInfo = threadInfoMap.get(thread.getId());
 
-            final String stackTrace = ThreadUtils.createStackTrace(thread, 
threadInfo, deadlockedThreadIds, monitorDeadlockThreadIds, activeMillis);
+            final String stackTrace = ThreadUtils.createStackTrace(thread, 
threadInfo, threadDetails.getDeadlockedThreadIds(), 
threadDetails.getMonitorDeadlockThreadIds(), activeMillis);
 
             final ActiveThreadInfo activeThreadInfo = new 
ActiveThreadInfo(thread.getName(), stackTrace, activeMillis, 
activeTask.isTerminated());
             threadList.add(activeThreadInfo);
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/diagnostics/bootstrap/tasks/LongRunningProcessorTask.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/diagnostics/bootstrap/tasks/LongRunningProcessorTask.java
index 73b7990..d90ef45 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/diagnostics/bootstrap/tasks/LongRunningProcessorTask.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/diagnostics/bootstrap/tasks/LongRunningProcessorTask.java
@@ -19,6 +19,7 @@ package org.apache.nifi.diagnostics.bootstrap.tasks;
 import org.apache.nifi.controller.ActiveThreadInfo;
 import org.apache.nifi.controller.FlowController;
 import org.apache.nifi.controller.ProcessorNode;
+import org.apache.nifi.controller.ThreadDetails;
 import org.apache.nifi.diagnostics.DiagnosticTask;
 import org.apache.nifi.diagnostics.DiagnosticsDumpElement;
 import org.apache.nifi.diagnostics.StandardDiagnosticsDumpElement;
@@ -40,9 +41,10 @@ public class LongRunningProcessorTask implements 
DiagnosticTask {
     @Override
     public DiagnosticsDumpElement captureDump(final boolean verbose) {
         final List<String> details = new ArrayList<>();
+        final ThreadDetails threadDetails = ThreadDetails.capture();
 
         for (final ProcessorNode processorNode : 
flowController.getFlowManager().getRootGroup().findAllProcessors()) {
-            final List<ActiveThreadInfo> activeThreads = 
processorNode.getActiveThreads();
+            final List<ActiveThreadInfo> activeThreads = 
processorNode.getActiveThreads(threadDetails);
 
             for (final ActiveThreadInfo activeThread : activeThreads) {
                 if (activeThread.getActiveMillis() > MIN_ACTIVE_MILLIS) {
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
index 9d70f9e..2fcca8b 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
@@ -82,6 +82,7 @@ import org.apache.nifi.controller.ProcessorNode;
 import org.apache.nifi.controller.ReportingTaskNode;
 import org.apache.nifi.controller.Snippet;
 import org.apache.nifi.controller.Template;
+import org.apache.nifi.controller.ThreadDetails;
 import org.apache.nifi.controller.flow.FlowManager;
 import org.apache.nifi.controller.label.Label;
 import org.apache.nifi.controller.queue.DropFlowFileState;
@@ -3873,7 +3874,7 @@ public final class DtoFactory {
     private List<ThreadDumpDTO> createThreadDumpDtos(final ProcessorNode 
procNode) {
         final List<ThreadDumpDTO> threadDumps = new ArrayList<>();
 
-        final List<ActiveThreadInfo> activeThreads = 
procNode.getActiveThreads();
+        final List<ActiveThreadInfo> activeThreads = 
procNode.getActiveThreads(ThreadDetails.capture());
         for (final ActiveThreadInfo threadInfo : activeThreads) {
             final ThreadDumpDTO dto = new ThreadDumpDTO();
             dto.setStackTrace(threadInfo.getStackTrace());

Reply via email to