From 6ed36c4fa1738c18eca3ecf12533a4acc0210dd1 Mon Sep 17 00:00:00 2001 From: Sylvain Juge <763082+SylvainJuge@users.noreply.github.com> Date: Mon, 27 May 2024 13:44:45 +0200 Subject: [PATCH 1/3] more stack frames for thread dump --- .../co/elastic/apm/agent/util/ThreadDump.java | 86 ++++++++++++++++++- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/util/ThreadDump.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/util/ThreadDump.java index 3bd7d11784..be95555c3e 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/util/ThreadDump.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/util/ThreadDump.java @@ -33,7 +33,9 @@ public class ThreadDump extends AbstractLifecycleListener { - private Logger log = LoggerFactory.getLogger(ThreadDump.class); + private static final Logger log = LoggerFactory.getLogger(ThreadDump.class); + + private static final int MAX_FRAMES = 40; @Nullable private ScheduledThreadPoolExecutor executor; @@ -66,7 +68,7 @@ public void run() { ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); StringBuilder sb = new StringBuilder(); for (ThreadInfo threadInfo : threadMXBean.dumpAllThreads(true, true)) { - sb.append(threadInfo.toString()); + sb.append(ThreadDump.toString(threadInfo)); } log.debug("thread dump: \n\n {}", sb); @@ -82,4 +84,84 @@ public void stop() throws Exception { } ExecutorUtils.shutdownAndWaitTermination(executor); } + + /** + * Copy of {@link ThreadInfo#toString()} with a higher frame size as default implementation. + * + * @param threadInfo thread info + * @return thread info as string + */ + private static String toString(ThreadInfo threadInfo) { + StringBuilder sb = new StringBuilder("\"" + threadInfo.getThreadName() + "\"" + + (threadInfo.isDaemon() ? " daemon" : "") + + " prio=" + threadInfo.getPriority() + + " Id=" + threadInfo.getThreadId() + " " + + threadInfo.getThreadState()); + if (threadInfo.getLockName() != null) { + sb.append(" on " + threadInfo.getLockName()); + } + if (threadInfo.getLockOwnerName() != null) { + sb.append(" owned by \"" + threadInfo.getLockOwnerName() + + "\" Id=" + threadInfo.getLockOwnerId()); + } + if (threadInfo.isSuspended()) { + sb.append(" (suspended)"); + } + if (threadInfo.isInNative()) { + sb.append(" (in native)"); + } + sb.append('\n'); + + StackTraceElement[] stackTrace = threadInfo.getStackTrace(); + int i = 0; + for (; i < stackTrace.length && i < MAX_FRAMES; i++) { + StackTraceElement ste = stackTrace[i]; + sb.append("\tat " + ste.toString()); + sb.append('\n'); + if (i == 0 && threadInfo.getLockInfo() != null) { + Thread.State ts = threadInfo.getThreadState(); + switch (ts) { + case BLOCKED: + sb.append("\t- blocked on " + threadInfo.getLockInfo()); + sb.append('\n'); + break; + case WAITING: + sb.append("\t- waiting on " + threadInfo.getLockInfo()); + sb.append('\n'); + break; + case TIMED_WAITING: + sb.append("\t- waiting on " + threadInfo.getLockInfo()); + sb.append('\n'); + break; + default: + } + } + + for (MonitorInfo mi : threadInfo.getLockedMonitors()) { + if (mi.getLockedStackDepth() == i) { + sb.append("\t- locked " + mi); + sb.append('\n'); + } + } + } + if (i < stackTrace.length) { + sb.append("\t..."); + sb.append('\n'); + } + + LockInfo[] locks = threadInfo.getLockedSynchronizers(); + if (locks.length > 0) { + sb.append("\n\tNumber of locked synchronizers = " + locks.length); + sb.append('\n'); + for (LockInfo li : locks) { + sb.append("\t- " + li); + sb.append('\n'); + } + } + sb.append('\n'); + return sb.toString(); + + } + + } From 500b3bbba481d873cfce77aeb129cfcacb0bdb63 Mon Sep 17 00:00:00 2001 From: Sylvain Juge <763082+SylvainJuge@users.noreply.github.com> Date: Mon, 27 May 2024 13:47:44 +0200 Subject: [PATCH 2/3] fix imports --- .../src/main/java/co/elastic/apm/agent/util/ThreadDump.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/util/ThreadDump.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/util/ThreadDump.java index be95555c3e..86dc3a04ed 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/util/ThreadDump.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/util/ThreadDump.java @@ -28,6 +28,8 @@ import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; +import java.lang.management.MonitorInfo; +import java.lang.management.LockInfo; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; From 99b9076f160824e4224e14267b2e27d70da11c77 Mon Sep 17 00:00:00 2001 From: Sylvain Juge <763082+SylvainJuge@users.noreply.github.com> Date: Mon, 27 May 2024 14:17:32 +0200 Subject: [PATCH 3/3] fix api limitations