[ASTERIXDB-2353][HYR][RT][FAIL] Provide complete thread dumps - user model changes: no - storage format changes: no - interface changes: no
Details: - Implements a thread dump mechanism that does not truncate stack frames after the top 8 Change-Id: Id778615b3ac8951113d6b9ea027ad8650b784cb2 Reviewed-on: https://asterix-gerrit.ics.uci.edu/2564 Sonar-Qube: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Reviewed-by: Murtadha Hubail <mhub...@apache.org> Tested-by: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Contrib: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Project: http://git-wip-us.apache.org/repos/asf/asterixdb/repo Commit: http://git-wip-us.apache.org/repos/asf/asterixdb/commit/aa05501d Tree: http://git-wip-us.apache.org/repos/asf/asterixdb/tree/aa05501d Diff: http://git-wip-us.apache.org/repos/asf/asterixdb/diff/aa05501d Branch: refs/heads/master Commit: aa05501d4cd23eae0210e9da7e4b22721290debc Parents: 5ff35c9 Author: Michael Blow <mb...@apache.org> Authored: Tue Apr 3 18:49:03 2018 -0400 Committer: Michael Blow <mb...@apache.org> Committed: Tue Apr 3 16:55:24 2018 -0700 ---------------------------------------------------------------------- .../org/apache/hyracks/util/ThreadDumpUtil.java | 64 +++++++++++++++++++- 1 file changed, 61 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/asterixdb/blob/aa05501d/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/ThreadDumpUtil.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/ThreadDumpUtil.java b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/ThreadDumpUtil.java index 221d4b0..2de6700 100644 --- a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/ThreadDumpUtil.java +++ b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/ThreadDumpUtil.java @@ -19,7 +19,9 @@ package org.apache.hyracks.util; import java.io.IOException; +import java.lang.management.LockInfo; import java.lang.management.ManagementFactory; +import java.lang.management.MonitorInfo; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; import java.util.ArrayList; @@ -29,6 +31,8 @@ import java.util.List; import java.util.Map; import java.util.stream.Stream; +import org.apache.commons.lang3.mutable.MutableInt; + import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -100,8 +104,62 @@ public class ThreadDumpUtil { } public static String takeDumpString() { - StringBuilder buf = new StringBuilder(2048); - Stream.of(threadMXBean.dumpAllThreads(true, true)).forEach(buf::append); - return buf.toString(); + ThreadDumpHelper helper = new ThreadDumpHelper(); + Stream.of(threadMXBean.dumpAllThreads(true, true)).forEach(helper::addThread); + return helper.dumpAsString(); + } + + static class ThreadDumpHelper { + + private final StringBuilder buf = new StringBuilder(32 * 1024); + + private ThreadDumpHelper() { + } + + private void addThread(ThreadInfo ti) { + buf.append('\n'); + quote(ti.getThreadName()).append(" [tid=").append(ti.getThreadId()).append(" state=") + .append(ti.getThreadState()); + + if (ti.getLockName() != null) { + buf.append(" lock=").append(ti.getLockName()); + if (ti.getLockOwnerName() != null) { + buf.append(" lockOwner="); + quote(ti.getLockOwnerName()).append(" (tid=").append(ti.getLockOwnerId()); + } + } + if (ti.isSuspended()) { + buf.append(" suspended=true"); + } + buf.append("]\n"); + MutableInt depth = new MutableInt(); + for (StackTraceElement frame : ti.getStackTrace()) { + int thisDepth = depth.getAndIncrement(); + buf.append("\tat ").append(frame).append('\n'); + Stream.of(ti.getLockedMonitors()).filter(m -> m.getLockedStackDepth() == thisDepth) + .forEach(this::output); + } + LockInfo[] lockedSynchronizers = ti.getLockedSynchronizers(); + if (lockedSynchronizers.length > 0) { + buf.append("\n\tLocked synchronizers:\n"); + Stream.of(lockedSynchronizers).forEachOrdered(this::output); + } + } + + private StringBuilder quote(Object quotable) { + return buf.append('"').append(quotable).append('"'); + } + + private StringBuilder output(MonitorInfo info) { + return buf.append("\t- <").append("locked ").append(info).append(">\n"); + } + + private StringBuilder output(LockInfo info) { + return buf.append("\t- ").append("").append(info).append("\n"); + } + + public String dumpAsString() { + return buf.toString(); + } } }