Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add -p for thread/dashboard to filter thread #2713

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Pattern;

import com.alibaba.arthas.deps.org.slf4j.Logger;
import com.alibaba.arthas.deps.org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -59,6 +60,8 @@ public class DashboardCommand extends AnnotatedCommand {
private final AtomicLong count = new AtomicLong(0);
private volatile Timer timer;

private Pattern threadNamePattern;

@Option(shortName = "n", longName = "number-of-execution")
@Description("The number of times this command will be executed.")
public void setNumOfExecutions(int numOfExecutions) {
Expand All @@ -71,6 +74,23 @@ public void setInterval(long interval) {
this.interval = interval;
}

@Option(shortName = "p",longName = "threadNamePattern")
@Description("Include thread name by regex pattern.")
public void setThreadNamePattern(final String pattern) {
if (pattern != null && !pattern.isEmpty()) {
this.threadNamePattern = Pattern.compile(pattern);
} else {
this.threadNamePattern = null;
}
}

private boolean runtimeInfoOff;

@Option(longName = "runtimeInfoOff", flag = true, required = false)
@Description("Hiden runtimeInfo area.")
public void setRuntimeInfoOff(boolean off) {
this.runtimeInfoOff = off;
}

@Override
public void process(final CommandProcess process) {
Expand Down Expand Up @@ -239,6 +259,7 @@ public void run() {

//thread sample
List<ThreadVO> threads = ThreadUtil.getThreads();
ThreadCommand.filterThreadByPattern(threads, threadNamePattern);
dashboardModel.setThreads(threadSampler.sample(threads));

//memory
Expand All @@ -247,9 +268,10 @@ public void run() {
//gc
addGcInfo(dashboardModel);

//runtime
addRuntimeInfo(dashboardModel);

if (!runtimeInfoOff) {
//runtime
addRuntimeInfo(dashboardModel);
}
//tomcat
try {
addTomcatInfo(dashboardModel);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

/**
* @author hengyunabc 2015年12月7日 下午2:06:21
Expand Down Expand Up @@ -58,6 +60,8 @@ public class ThreadCommand extends AnnotatedCommand {
private boolean lockedSynchronizers = false;
private boolean all = false;

private Pattern namePattern;

static {
states = new HashSet<String>(State.values().length);
for (State state : State.values()) {
Expand Down Expand Up @@ -113,6 +117,16 @@ public void setLockedSynchronizers(boolean lockedSynchronizers) {
this.lockedSynchronizers = lockedSynchronizers;
}

@Option(shortName = "p",longName = "namePattern")
@Description("Include thread name by regex pattern.")
public void setNamePattern(final String pattern) {
if (pattern != null && !pattern.isEmpty()) {
this.namePattern = Pattern.compile(pattern);
} else {
this.namePattern = null;
}
}

@Override
public void process(CommandProcess process) {
ExitStatus exitStatus;
Expand Down Expand Up @@ -160,7 +174,7 @@ private ExitStatus processAllThreads(CommandProcess process) {
} else {
resultThreads = threads;
}

filterThreadByPattern(resultThreads, namePattern);
//thread stats
ThreadSampler threadSampler = new ThreadSampler();
threadSampler.setIncludeInternalThreads(includeInternalThreads);
Expand All @@ -172,8 +186,19 @@ private ExitStatus processAllThreads(CommandProcess process) {
return ExitStatus.success();
}

static void filterThreadByPattern(Collection<ThreadVO> threads, Pattern pattern) {
if (!threads.isEmpty() && pattern != null) {
for (Iterator<ThreadVO> iter = threads.iterator(); iter.hasNext();) {
ThreadVO thread = iter.next();
if (!pattern.matcher(thread.getName()).find()) {
iter.remove();
}
}
}
}

private ExitStatus processBlockingThread(CommandProcess process) {
BlockingLockInfo blockingLockInfo = ThreadUtil.findMostBlockingLock();
final BlockingLockInfo blockingLockInfo = ThreadUtil.findMostBlockingLock(this.namePattern);
if (blockingLockInfo.getThreadInfo() == null) {
return ExitStatus.failure(1, "No most blocking thread found!");
}
Expand All @@ -186,6 +211,7 @@ private ExitStatus processTopBusyThreads(CommandProcess process) {
threadSampler.sample(ThreadUtil.getThreads());
threadSampler.pause(sampleInterval);
List<ThreadVO> threadStats = threadSampler.sample(ThreadUtil.getThreads());
filterThreadByPattern(threadStats, namePattern);

int limit = Math.min(threadStats.size(), topNBusy);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ public void draw(CommandProcess process, DashboardModel result) {
}

//runtime
TableElement runtimeInfoTable = drawRuntimeInfo(result.getRuntimeInfo());
RuntimeInfoVO runtimeInfo = result.getRuntimeInfo();
TableElement runtimeInfoTable = runtimeInfo == null ? null : drawRuntimeInfo(runtimeInfo);
//tomcat
TableElement tomcatInfoTable = drawTomcatInfo(result.getTomcatInfo());
int runtimeInfoHeight = Math.max(runtimeInfoTable.getRows().size(), tomcatInfoTable == null ? 0 : tomcatInfoTable.getRows().size());
int runtimeInfoHeight = Math.max(runtimeInfoTable == null ? 0 : runtimeInfoTable.getRows().size(),
tomcatInfoTable == null ? 0 : tomcatInfoTable.getRows().size());
if (runtimeInfoHeight < lowerHalf - memoryInfoHeight) {
//如果runtimeInfo高度有剩余,则增大MemoryInfo的高度
memoryInfoHeight = lowerHalf - runtimeInfoHeight;
Expand Down Expand Up @@ -107,6 +109,9 @@ String drawRuntimeInfoAndTomcatInfo(TableElement runtimeInfoTable, TableElement
} else {
resultTable = runtimeInfoTable;
}
if (runtimeInfoTable == null) {
return "";
}
return RenderUtil.render(resultTable, width, height);
}

Expand Down
28 changes: 21 additions & 7 deletions core/src/main/java/com/taobao/arthas/core/util/ThreadUtil.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
package com.taobao.arthas.core.util;

import java.arthas.SpyAPI;
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.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import com.taobao.arthas.core.command.model.BlockingLockInfo;
import com.taobao.arthas.core.command.model.BusyThreadInfo;
import com.taobao.arthas.core.command.model.StackModel;
import com.taobao.arthas.core.command.model.ThreadNode;
import com.taobao.arthas.core.command.model.ThreadVO;
import com.taobao.arthas.core.view.Ansi;

import java.arthas.SpyAPI;
import java.lang.management.*;
import java.lang.reflect.Method;
import java.util.*;

/**
*
* @author hengyunabc 2015年12月7日 下午2:29:28
Expand Down Expand Up @@ -96,7 +104,11 @@ public static List<Thread> getThreadList() {
*
* @return the BlockingLockInfo object, or an empty object if not found.
*/
public static BlockingLockInfo findMostBlockingLock() {
public static BlockingLockInfo findMostBlockingLock() {
return findMostBlockingLock(null);
}

public static BlockingLockInfo findMostBlockingLock(final Pattern threadNamePattern) {
ThreadInfo[] infos = threadMXBean.dumpAllThreads(threadMXBean.isObjectMonitorUsageSupported(),
threadMXBean.isSynchronizerUsageSupported());

Expand All @@ -109,7 +121,9 @@ public static BlockingLockInfo findMostBlockingLock() {
if (info == null) {
continue;
}

if (threadNamePattern != null && ! threadNamePattern.matcher(info.getThreadName()).find()) {
continue;
}
LockInfo lockInfo = info.getLockInfo();
if (lockInfo != null) {
// the current thread is blocked waiting on some condition
Expand Down