All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sirius.kernel.health.console.ThreadsCommand Maven / Gradle / Ivy

Go to download

Provides common core classes and the microkernel powering all Sirius applications

There is a newer version: 12.9.1
Show newest version
/*
 * Made with all the love in the world
 * by scireum in Remshalden, Germany
 *
 * Copyright by scireum GmbH
 * http://www.scireum.de - [email protected]
 */

package sirius.kernel.health.console;

import sirius.kernel.async.CallContext;
import sirius.kernel.commons.Tuple;
import sirius.kernel.commons.Value;
import sirius.kernel.di.std.Register;

import javax.annotation.Nonnull;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.Map;
import java.util.Optional;

/**
 * Console command which reports all running threads.
 */
@Register
public class ThreadsCommand implements Command {

    private ThreadMXBean t = ManagementFactory.getThreadMXBean();

    @Override
    public void execute(Output output, String... params) throws Exception {
        boolean withTraces = Value.indexOf(0, params).isFilled();
        boolean includeWaiting = "Y".equals(Value.indexOf(1, params).asString());
        if (withTraces) {
            outputThreadInfos(output, includeWaiting, params[0]);
        } else {
            output.line("Usage: threads [ (or 'all')] [Y=include WAITING/NATIVE]");
            output.separator();
            output.apply("%-15s %10s %53s", "STATE", "ID", "NAME");
            output.separator();
            for (ThreadInfo info : t.dumpAllThreads(false, false)) {
                output.apply("%-15s %10s %53s",
                             info.isInNative() ? "NATIVE" : info.getThreadState().name(),
                             info.getThreadId(),
                             info.getThreadName());
            }
            output.separator();
        }
    }

    private void outputThreadInfos(Output output, boolean includeWaiting, String threadName) {
        for (Map.Entry thread : Thread.getAllStackTraces().entrySet()) {
            outputThreadInfo(output, includeWaiting, threadName, thread);
        }
    }

    private void outputThreadInfo(Output output,
                                  boolean includeWaiting,
                                  String threadName,
                                  Map.Entry thread) {
        ThreadInfo info = t.getThreadInfo(thread.getKey().getId());
        if (!"all".equalsIgnoreCase(threadName) && !thread.getKey()
                                                          .getName()
                                                          .toLowerCase()
                                                          .contains(threadName.toLowerCase())) {
            return;
        }
        if (!includeWaiting && isWaitingOrNative(thread.getKey(), info)) {
            return;
        }

        output.blankLine();
        output.line(thread.getKey().getName() + " (" + thread.getKey().getState() + ")");
        output.separator();
        for (StackTraceElement e : thread.getValue()) {
            output.apply("%-60s %19s",
                         e.getClassName() + "." + e.getMethodName(),
                         e.getFileName() + ":" + e.getLineNumber());
        }
        output.separator();

        Optional cc = CallContext.getContext(thread.getKey().getId());
        if (cc.isPresent()) {
            output.line("Mapped Diagnostic Context");
            output.separator();
            for (Tuple e : cc.get().getMDC()) {
                output.apply("%-20s %59s", e.getFirst(), e.getSecond());
            }
            output.apply("Flow duration: %s", cc.get().getWatch().duration());
        }
        output.blankLine();
    }

    private boolean isWaitingOrNative(Thread thread, ThreadInfo info) {
        return (info != null && info.isInNative())
               || thread.getState() == Thread.State.WAITING
               || thread.getState() == Thread.State.TIMED_WAITING;
    }

    @Override
    @Nonnull
    public String getName() {
        return "threads";
    }

    @Override
    public String getDescription() {
        return "Reports a list of all threads.";
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy