/* * Copyright 2014 NAVER Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.navercorp.pinpoint.profiler.receiver.service; import com.navercorp.pinpoint.common.util.ThreadMXBeanUtils; import com.navercorp.pinpoint.profiler.receiver.ProfilerRequestCommandService; import com.navercorp.pinpoint.thrift.dto.command.*; import org.apache.thrift.TBase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.management.LockInfo; import java.lang.management.MonitorInfo; import java.lang.management.ThreadInfo; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * @author koo.taejin */ public class ThreadDumpService implements ProfilerRequestCommandService { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Override public TBase<?, ?> requestCommandService(TBase tbase) { logger.info("{} execute {}.", this, tbase); TCommandThreadDump param = (TCommandThreadDump) tbase; TThreadDumpType type = param.getType(); List<ThreadInfo> threadInfoList = null; if (TThreadDumpType.TARGET == type) { threadInfoList = getThreadInfo(param.getName()); } else if (TThreadDumpType.PENDING == type) { threadInfoList = getThreadInfo(param.getPendingTimeMillis()); } else { threadInfoList = Arrays.asList(getAllThreadInfo()); } TCommandThreadDumpResponse response = new TCommandThreadDumpResponse(); for (ThreadInfo info : threadInfoList) { TThreadDump dump = new TThreadDump(); dump.setThreadName(info.getThreadName()); dump.setThreadId(info.getThreadId()); dump.setBlockedTime(info.getBlockedTime()); dump.setBlockedCount(info.getBlockedCount()); dump.setWaitedTime(info.getWaitedTime()); dump.setWaitedCount(info.getWaitedCount()); dump.setLockName(info.getLockName()); dump.setLockOwnerId(info.getLockOwnerId()); dump.setLockOwnerName(info.getLockOwnerName()); dump.setInNative(info.isInNative()); dump.setSuspended(info.isSuspended()); dump.setThreadState(getThreadState(info)); StackTraceElement[] stackTraceElements = info.getStackTrace(); for (StackTraceElement each : stackTraceElements) { dump.addToStackTrace(each.toString()); } MonitorInfo[] monitorInfos = info.getLockedMonitors(); for (MonitorInfo each : monitorInfos) { TMonitorInfo tMonitorInfo = new TMonitorInfo(); tMonitorInfo.setStackDepth(each.getLockedStackDepth()); tMonitorInfo.setStackFrame(each.getLockedStackFrame().toString()); dump.addToLockedMonitors(tMonitorInfo); } LockInfo[] lockInfos = info.getLockedSynchronizers(); for (LockInfo lockInfo : lockInfos) { dump.addToLockedSynchronizers(lockInfo.toString()); } response.addToThreadDumps(dump); } return response; } private TThreadState getThreadState(ThreadInfo info) { String stateName = info.getThreadState().name(); for (TThreadState state : TThreadState.values()) { if (state.name().equalsIgnoreCase(stateName)) { return state; } } return null; } private List<ThreadInfo> getThreadInfo(String threadName) { List<ThreadInfo> result = new ArrayList<ThreadInfo>(); if (threadName == null || threadName.trim().equals("")) { return Arrays.asList(getAllThreadInfo()); } for (ThreadInfo threadIno : getAllThreadInfo()) { if (threadName.equals(threadIno.getThreadName())) { result.add(threadIno); } } return result; } // TODO : need to modify later private List<ThreadInfo> getThreadInfo(long pendingTimeMillis) { List<ThreadInfo> result = new ArrayList<ThreadInfo>(); if (pendingTimeMillis <= 0) { return Arrays.asList(getAllThreadInfo()); } for (ThreadInfo threadInfo : getAllThreadInfo()) { if (threadInfo.getBlockedTime() >= pendingTimeMillis) { result.add(threadInfo); continue; } if (threadInfo.getWaitedTime() >= pendingTimeMillis) { result.add(threadInfo); } } return result; } private ThreadInfo[] getAllThreadInfo() { ThreadInfo[] threadInfos = ThreadMXBeanUtils.dumpAllThread(); return threadInfos; } @Override public Class<? extends TBase> getCommandClazz() { return TCommandThreadDump.class; } }