
Analyse thread dumps sometimes can be difficult, you have to take the thread dump, save on you machine, upload it somewhere to analyse the file and then search for the docs which apply for your case.
Working with SAP Commerce, some times we have to analyse thread dumps to debug issues, find performance-related problems and so on. On Cloud you can rely on Monitoring Tools to find such information, but on local it can be tricky, you are by yourself, so, wouldn't be nice to have something to make it a little easier?
If so, you will appreciate the convenience of this Groovy script, which is engineered specifically for the Hybris Administration Console (HAC) in SAP Commerce. Instead of generating large, complicated thread dumps, this script provides an examination of active threads for quick troubleshooting and diagnostics.
Using the script is a breeze thanks to HAC's script console. Simply run the script in the console and the output can be conveniently viewed directly in the console's "Output" tab.
You can add more definitions to match the threads and add commentaries in case you are searching for something specific.
The output provided can be a key instrument for debugging and optimizing performance. The output for each thread includes the thread name, its state and the stack trace. Furthermore, you can cross-reference recognized issues with the solutions provided in the form of a link or comments. This can greatly assist in understanding and resolving the situation promptly.
Remember that the script only returns the threads for the machine it's currently running on. If you're running the script on SAP Commerce Cloud, it will return the threads from the service replica where it was initiated.
While the script is intended for convenience, it's important to employ it carefully. The process of acquiring and examining thread data can potentially impose on system performance. Always ensure your system's capacity and health before running thread analysis.
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicReference;
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
long[] threadIds = threadMXBean.getAllThreadIds();
ThreadInfo[] threadInfos = threadMXBean.getThreadInfo(threadIds, Integer.MAX_VALUE);
var threadsByState = Arrays.stream(threadInfos)
.filter(it -> it != null)
.collect(java.util.stream.Collectors.groupingBy(ThreadInfo::getThreadState));
var threadStatesOrder = Arrays.asList(
Thread.State.RUNNABLE,
Thread.State.BLOCKED,
Thread.State.WAITING,
Thread.State.TIMED_WAITING,
Thread.State.NEW,
Thread.State.TERMINATED
);
var solutions = Arrays.asList(
new Object[]{ "hybrisHTTP", Thread.State.BLOCKED, "org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal", "Try to check https://me.sap.com/notes/3153768" },
new Object[]{ "hybrisHTTP", Thread.State.WAITING, "de.hybris.platform.tx.DefaultAfterSaveListenerRegistry.enqueueChangesForAsyncNotification", "Try to check https://me.sap.com/notes/3118007 and https://me.sap.com/notes/3158467" },
new Object[]{ "hybrisHTTP", Thread.State.BLOCKED, "org.apache.commons.lang.builder.HashCodeBuilder.reflectionHashCode", "Try to check https://me.sap.com/notes/2589737" },
new Object[]{ "hybrisHTTP", Thread.State.RUNNABLE, "java.lang.Thread.run", "Just a Normal SAP Commerce thread" },
new Object[]{ "hybrisHTTP", Thread.State.RUNNABLE, "java.lang.Thread.run", "Just a Normal SAP Commerce thread" },
new Object[]{ "Thread", Thread.State.TIMED_WAITING, "de.hybris.platform.core.threadregistry.RegistrableThread.run", "Threads which contain only Thread-<number> on name and are deployed by threadregistry.RegistrableThread.run, are background threads that can include even this script" }
);
threadStatesOrder.forEach(state -> {
if (threadsByState.containsKey(state)) {
println("Threads in state: " + state);
threadsByState.get(state).stream().forEach(threadInfo -> {
println("Thread name: " + threadInfo.getThreadName());
println("Thread state: " + threadInfo.getThreadState());
println("Thread ID: " + threadInfo.getThreadId());
AtomicReference<String> solutionLink = new AtomicReference<>();
Arrays.stream(threadInfo.getStackTrace()).forEach(stackTraceElement -> {
solutions.stream().forEach(solution -> {
if (threadInfo.getThreadName().contains((String) solution[0]) &&
threadInfo.getThreadState() == solution[1] &&
(stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName()).contains((String) solution[2])) {
solutionLink.set((String) solution[3]);
}
});
});
String link = solutionLink.get();
if (link != null) {
println("Solution or comments: " + link);
}
println("Stack trace:");
Arrays.stream(threadInfo.getStackTrace()).forEach(stackTraceElement -> {
println("\t" + stackTraceElement);
});
println("-".repeat(80));
});
}
});
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
8 | |
3 | |
3 | |
2 | |
2 | |
1 | |
1 | |
1 | |
1 | |
1 |