/* * Copyright 2017 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.web.vo; import com.navercorp.pinpoint.common.util.CollectionUtils; import com.navercorp.pinpoint.thrift.dto.command.TActiveThreadDump; import com.navercorp.pinpoint.thrift.dto.command.TActiveThreadLightDump; import com.navercorp.pinpoint.thrift.dto.command.TMonitorInfo; import com.navercorp.pinpoint.thrift.dto.command.TThreadDump; import com.navercorp.pinpoint.thrift.dto.command.TThreadLightDump; import com.navercorp.pinpoint.thrift.dto.command.TThreadState; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; /** * @author Taejin Koo */ public class AgentActiveThreadDumpFactory { public static final String LINE_SEPARATOR = System.getProperty("line.separator"); public static final String TAB_SEPARATOR = " "; // tab to 4 spaces private final Logger logger = LoggerFactory.getLogger(this.getClass()); public AgentActiveThreadDumpFactory() { } public AgentActiveThreadDumpList create1(List<TActiveThreadDump> tActiveThreadDumpList) { if (CollectionUtils.isEmpty(tActiveThreadDumpList)) { return AgentActiveThreadDumpList.EMPTY_INSTANCE; } AgentActiveThreadDumpList result = new AgentActiveThreadDumpList(tActiveThreadDumpList.size()); for (TActiveThreadDump activeThreadDump : tActiveThreadDumpList) { try { AgentActiveThreadDump agentActiveThreadDump = create1(activeThreadDump); result.add(agentActiveThreadDump); } catch (Exception e) { logger.warn("create AgentActiveThreadDump fail. arguments(TActiveThreadDump:{})", activeThreadDump); } } return result; } private AgentActiveThreadDump create1(TActiveThreadDump tActiveThreadDump) { if (tActiveThreadDump == null) { throw new NullPointerException("tActiveThreadDump may not be null"); } TThreadDump activeThreadDump = tActiveThreadDump.getThreadDump(); AgentActiveThreadDump.Builder builder = new AgentActiveThreadDump.Builder(); builder.setThreadId(activeThreadDump.getThreadId()); builder.setThreadName(activeThreadDump.getThreadName()); builder.setThreadState(getThreadState(activeThreadDump.getThreadState())); builder.setStartTime(tActiveThreadDump.getStartTime()); builder.setExecTime(System.currentTimeMillis() - tActiveThreadDump.getStartTime()); builder.setLocalTraceId(tActiveThreadDump.getLocalTraceId()); builder.setSampled(tActiveThreadDump.isSampled()); builder.setTransactionId(tActiveThreadDump.getTransactionId()); builder.setEntryPoint(tActiveThreadDump.getEntryPoint()); builder.setDetailMessage(createDumpMessage(activeThreadDump)); return builder.build(); } public AgentActiveThreadDumpList create2(List<TActiveThreadLightDump> tActiveThreadLightDumpList) { if (CollectionUtils.isEmpty(tActiveThreadLightDumpList)) { return AgentActiveThreadDumpList.EMPTY_INSTANCE; } AgentActiveThreadDumpList result = new AgentActiveThreadDumpList(tActiveThreadLightDumpList.size()); for (TActiveThreadLightDump activeThreadLightDump : tActiveThreadLightDumpList) { try { AgentActiveThreadDump agentActiveThreadDump = create2(activeThreadLightDump); result.add(agentActiveThreadDump); } catch (Exception e) { logger.warn("create AgentActiveThreadDump fail. arguments(TActiveThreadDump:{})", activeThreadLightDump); } } return result; } private AgentActiveThreadDump create2(TActiveThreadLightDump tActiveThreadLightDump) { if (tActiveThreadLightDump == null) { throw new NullPointerException("tActiveThreadLightDump may not be null"); } TThreadLightDump activeThreadDump = tActiveThreadLightDump.getThreadDump(); AgentActiveThreadDump.Builder builder = new AgentActiveThreadDump.Builder(); builder.setThreadId(activeThreadDump.getThreadId()); builder.setThreadName(activeThreadDump.getThreadName()); builder.setThreadState(getThreadState(activeThreadDump.getThreadState())); builder.setStartTime(tActiveThreadLightDump.getStartTime()); builder.setExecTime(System.currentTimeMillis() - tActiveThreadLightDump.getStartTime()); builder.setLocalTraceId(tActiveThreadLightDump.getLocalTraceId()); builder.setSampled(tActiveThreadLightDump.isSampled()); builder.setTransactionId(tActiveThreadLightDump.getTransactionId()); builder.setEntryPoint(tActiveThreadLightDump.getEntryPoint()); builder.setDetailMessage(StringUtils.EMPTY); return builder.build(); } private TThreadState getThreadState(TThreadState threadState) { if (threadState == null) { return TThreadState.UNKNOWN; } else { return threadState; } } public String createDumpMessage(TThreadDump threadDump) { TThreadState threadState = getThreadState(threadDump.getThreadState()); // set threadName StringBuilder message = new StringBuilder("\"" + threadDump.getThreadName() + "\""); // set threadId String hexStringThreadId = Long.toHexString(threadDump.getThreadId()); message.append(" Id=0x" + hexStringThreadId); // set threadState message.append(" " + threadState.name()); if (!StringUtils.isBlank(threadDump.getLockName())) { message.append(" on ").append(threadDump.getLockName()); } if (!StringUtils.isBlank(threadDump.getLockOwnerName())) { message.append(" owned by \"").append(threadDump.getLockOwnerName()).append("\" Id=").append(threadDump.getLockOwnerId()); } if (threadDump.isSuspended()) { message.append(" (suspended)"); } if (threadDump.isInNative()) { message.append(" (in native)"); } message.append(LINE_SEPARATOR); // set StackTrace for (int i = 0; i < threadDump.getStackTraceSize(); i++) { String stackTrace = threadDump.getStackTrace().get(i); message.append(TAB_SEPARATOR + "at ").append(stackTrace); message.append(LINE_SEPARATOR); if (i == 0 && !StringUtils.isBlank(threadDump.getLockName())) { switch (threadState) { case BLOCKED: message.append(TAB_SEPARATOR + "- blocked on ").append(threadDump.getLockName()); message.append(LINE_SEPARATOR); break; case WAITING: message.append(TAB_SEPARATOR + "- waiting on ").append(threadDump.getLockName()); message.append(LINE_SEPARATOR); break; case TIMED_WAITING: message.append(TAB_SEPARATOR + "- waiting on ").append(threadDump.getLockName()); message.append(LINE_SEPARATOR); break; default: } } if (threadDump.getLockedMonitors() != null) { for (TMonitorInfo lockedMonitor : threadDump.getLockedMonitors()) { if (lockedMonitor.getStackDepth() == i) { message.append(TAB_SEPARATOR + "- locked ").append(lockedMonitor.getStackFrame()); message.append(LINE_SEPARATOR); } } } } // set Locks List<String> lockedSynchronizers = threadDump.getLockedSynchronizers(); if (!CollectionUtils.isEmpty(lockedSynchronizers)) { message.append(LINE_SEPARATOR + TAB_SEPARATOR + "Number of locked synchronizers = ").append(lockedSynchronizers.size()); message.append(LINE_SEPARATOR); for (String lockedSynchronizer : lockedSynchronizers) { message.append(TAB_SEPARATOR + "- ").append(lockedSynchronizer); message.append(LINE_SEPARATOR); } } message.append(LINE_SEPARATOR); return message.toString(); } }