From 7b106349310fc91eb1af6d446ea9e357b4d43d25 Mon Sep 17 00:00:00 2001 From: emeroad Date: Tue, 12 Sep 2017 17:12:29 +0900 Subject: [PATCH] [#2584] Refactor ActiveTraceDump --- .../common/util/ThreadMXBeanUtils.java | 40 +++- .../context/active/ActiveTraceRepository.java | 4 +- .../active/DefaultActiveTraceRepository.java | 28 ++- .../active/EmptyActiveTraceRepository.java | 7 +- .../profiler/monitor/DeadlockMonitorTask.java | 2 +- .../service/ActiveThreadDumpCoreService.java | 151 +++++++++++++++ .../service/ActiveThreadDumpService.java | 98 +++------- .../service/ActiveThreadLightDumpService.java | 86 +++------ .../receiver/service/ActiveThreadService.java | 6 +- .../receiver/service/LimitedList.java | 120 ++++++++++++ .../profiler/receiver/service/StackTrace.java | 24 +++ .../receiver/service/StartTimeComparator.java | 35 ++++ .../profiler/receiver/service/ThreadDump.java | 44 +++++ .../service/ThreadDumpComparator.java | 35 ++++ .../receiver/service/ThreadDumpRequest.java | 137 ++++++++++++++ .../profiler/util/ActiveThreadDumpUtils.java | 4 +- .../profiler/util/ThreadDumpUtils.java | 12 +- .../active/ActiveTraceRepositoryTest.java | 2 +- .../service/ActiveThreadDumpServiceTest.java | 174 ++++++----------- .../ActiveThreadLightDumpServiceTest.java | 177 ++++++------------ .../receiver/service/LimitedListTest.java | 116 ++++++++++++ .../profiler/receiver/service/WaitingJob.java | 45 +++++ .../service/WaitingJobListFactory.java | 54 ++++++ 23 files changed, 1020 insertions(+), 381 deletions(-) create mode 100644 profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadDumpCoreService.java create mode 100644 profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/LimitedList.java create mode 100644 profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/StackTrace.java create mode 100644 profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/StartTimeComparator.java create mode 100644 profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ThreadDump.java create mode 100644 profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ThreadDumpComparator.java create mode 100644 profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ThreadDumpRequest.java create mode 100644 profiler/src/test/java/com/navercorp/pinpoint/profiler/receiver/service/LimitedListTest.java create mode 100644 profiler/src/test/java/com/navercorp/pinpoint/profiler/receiver/service/WaitingJob.java create mode 100644 profiler/src/test/java/com/navercorp/pinpoint/profiler/receiver/service/WaitingJobListFactory.java diff --git a/commons/src/main/java/com/navercorp/pinpoint/common/util/ThreadMXBeanUtils.java b/commons/src/main/java/com/navercorp/pinpoint/common/util/ThreadMXBeanUtils.java index 62f23eb7ffad..9e6302d3739e 100644 --- a/commons/src/main/java/com/navercorp/pinpoint/common/util/ThreadMXBeanUtils.java +++ b/commons/src/main/java/com/navercorp/pinpoint/common/util/ThreadMXBeanUtils.java @@ -72,19 +72,53 @@ public static ThreadInfo[] dumpAllThread() { // } } + /** + * @deprecated Since 1.7.0. Use {@link #getThreadInfo(long)} + */ + @Deprecated public static ThreadInfo findThread(Thread thread) { - return findThread(thread.getId()); + Assert.requireNonNull(thread, "thread must not be null"); + return getThreadInfo(thread.getId()); } + /** + * @deprecated Since 1.7.0. Use {@link #getThreadInfo(long, int)} + */ + @Deprecated public static ThreadInfo findThread(Thread thread, int stackTraceMaxDepth) { - return findThread(thread.getId(), stackTraceMaxDepth); + Assert.requireNonNull(thread, "thread must not be null"); + return getThreadInfo(thread.getId(), stackTraceMaxDepth); } + /** + * @deprecated Since 1.7.0. Use {@link #getThreadInfo(long)} + */ + @Deprecated public static ThreadInfo findThread(long id) { - return findThread(id, DEFAULT_STACK_TRACE_MAX_DEPTH); + return getThreadInfo(id, DEFAULT_STACK_TRACE_MAX_DEPTH); } + public static ThreadInfo getThreadInfo(long id) { + return getThreadInfo(id, DEFAULT_STACK_TRACE_MAX_DEPTH); + } + + /** + * @deprecated Since 1.7.0. Use {@link #getThreadInfo(long, int)} + */ + @Deprecated public static ThreadInfo findThread(long id, int stackTraceMaxDepth) { + return getThreadInfo(id, stackTraceMaxDepth); + } + + public static ThreadInfo getThreadInfo(long id, int stackTraceMaxDepth) { + if (stackTraceMaxDepth <= 0) { + return THREAD_MX_BEAN.getThreadInfo(id); + } else { + return THREAD_MX_BEAN.getThreadInfo(id, stackTraceMaxDepth); + } + } + + public static ThreadInfo[] findThread(long[] id, int stackTraceMaxDepth) { if (stackTraceMaxDepth <= 0) { return THREAD_MX_BEAN.getThreadInfo(id); } else { diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/active/ActiveTraceRepository.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/active/ActiveTraceRepository.java index 3b79d1bb555f..244523a3ae00 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/active/ActiveTraceRepository.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/active/ActiveTraceRepository.java @@ -27,7 +27,9 @@ public interface ActiveTraceRepository { ActiveTraceHistogram getActiveTraceHistogram(long timeStamp); - List collect(); + List snapshot(); + + List getThreadIdList(); ActiveTraceHandle register(TraceRoot traceRoot); diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/active/DefaultActiveTraceRepository.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/active/DefaultActiveTraceRepository.java index 3d4e603f34ae..23dbca9a6193 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/active/DefaultActiveTraceRepository.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/active/DefaultActiveTraceRepository.java @@ -122,12 +122,13 @@ private ActiveTraceHandle register0(ActiveTrace activeTrace) { // @ThreadSafe @Override - public List collect() { + public List snapshot() { if (this.activeTraceInfoMap.isEmpty()) { return Collections.emptyList(); } final Collection activeTraceCollection = this.activeTraceInfoMap.values(); final List collectData = new ArrayList(activeTraceCollection.size()); + for (ActiveTrace trace : activeTraceCollection) { final long startTime = trace.getStartTime(); // not started @@ -143,6 +144,31 @@ public List collect() { return collectData; } + + // @ThreadSafe + @Override + public List getThreadIdList() { + if (this.activeTraceInfoMap.isEmpty()) { + return Collections.emptyList(); + } + final Collection activeTraceCollection = this.activeTraceInfoMap.values(); + final List collectData = new ArrayList(activeTraceCollection.size()); + + for (ActiveTrace trace : activeTraceCollection) { + final long startTime = trace.getStartTime(); + // not started + if (!isStarted(startTime)) { + continue; + } + final ActiveTraceSnapshot snapshot = trace.snapshot(); + collectData.add(snapshot.getThreadId()); + } + if (isDebug) { + logger.debug("activeTraceSnapshot size:{}", collectData.size()); + } + return collectData; + } + // @ThreadSafe @Override public ActiveTraceHistogram getActiveTraceHistogram(long currentTime) { diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/active/EmptyActiveTraceRepository.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/active/EmptyActiveTraceRepository.java index fa2dafbe7a46..a88dc7748694 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/active/EmptyActiveTraceRepository.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/active/EmptyActiveTraceRepository.java @@ -43,7 +43,12 @@ public ActiveTraceHistogram getActiveTraceHistogram(long timeStamp) { } @Override - public List collect() { + public List getThreadIdList() { + return null; + } + + @Override + public List snapshot() { return Collections.emptyList(); } diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/monitor/DeadlockMonitorTask.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/monitor/DeadlockMonitorTask.java index 9d9d1d9fdf53..c91c41090487 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/monitor/DeadlockMonitorTask.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/monitor/DeadlockMonitorTask.java @@ -80,7 +80,7 @@ void doTask() { deadlockOutput.append("================================================================").append(LINE_SEPARATOR); for (long deadlockedThreadId : deadlockedThreadIds) { - ThreadInfo threadInfo = ThreadMXBeanUtils.findThread(deadlockedThreadId); + ThreadInfo threadInfo = ThreadMXBeanUtils.getThreadInfo(deadlockedThreadId); deadlockOutput.append(createThreadDump(threadInfo)); } deadlockOutput.append("================================================================").append(LINE_SEPARATOR); diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadDumpCoreService.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadDumpCoreService.java new file mode 100644 index 000000000000..e54fc7456f0a --- /dev/null +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadDumpCoreService.java @@ -0,0 +1,151 @@ +/* + * 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.profiler.receiver.service; + +import com.navercorp.pinpoint.common.util.Assert; +import com.navercorp.pinpoint.common.util.ThreadMXBeanUtils; +import com.navercorp.pinpoint.profiler.context.active.ActiveTraceRepository; +import com.navercorp.pinpoint.profiler.context.active.ActiveTraceSnapshot; + + +import java.lang.management.ThreadInfo; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * @author Woonduk Kang(emeroad) + */ +public class ActiveThreadDumpCoreService { + + private final ActiveTraceRepository activeTraceRepository; + + private final Comparator reverseOrder = Collections.reverseOrder(new ThreadDumpComparator()); + + public ActiveThreadDumpCoreService(ActiveTraceRepository activeTraceRepository) { + this.activeTraceRepository = Assert.requireNonNull(activeTraceRepository, "activeTraceRepository must not be null"); + } + + public Collection getActiveThreadDumpList(ThreadDumpRequest request) { + + final List activeTraceInfoList = activeTraceRepository.snapshot(); + + return getActiveThreadDumpList(activeTraceInfoList, request); + } + + private Collection getActiveThreadDumpList(List activeTraceInfoList, ThreadDumpRequest request) { + + if (request.isEnableFilter()) { + return filterActiveThreadDump(activeTraceInfoList, request); + } else { + + return getAllActiveThreadDump(activeTraceInfoList, request); + } + } + + private Collection filterActiveThreadDump(List activeTraceInfoList, ThreadDumpRequest request) { + + final Collection result = new LimitedList(request.getLimit(), reverseOrder); + + for (ActiveTraceSnapshot activeTraceInfo : activeTraceInfoList) { + final long threadId = activeTraceInfo.getThreadId(); + if (!isTraceThread(threadId)) { + continue; + } + + final ThreadDump threadDump = filter(activeTraceInfo, request); + if (threadDump != null) { + result.add(threadDump); + } + } + + return result; + } + + private ThreadDump filter(ActiveTraceSnapshot activeTraceInfo, ThreadDumpRequest request) { + + if (request.isEnableLocalTransactionIdFilter()) { + + final long localTransactionId = activeTraceInfo.getLocalTransactionId(); + if (request.findLocalTransactionId(localTransactionId)) { + + final long threadId = activeTraceInfo.getThreadId(); + final ThreadInfo threadInfo = getThreadInfo(threadId, request.getStackTrace()); + if (threadInfo != null) { + return newThreadDump(activeTraceInfo, threadInfo); + } + } + } + + if (request.isEnableThreadNameFilter()) { + // native call + final long threadId = activeTraceInfo.getThreadId(); + final ThreadInfo threadInfo = getThreadInfo(threadId, request.getStackTrace()); + if (threadInfo != null) { + if (request.findThreadName(threadInfo.getThreadName())) { + return newThreadDump(activeTraceInfo, threadInfo); + } + } + } + + return null; + } + + private Collection getAllActiveThreadDump(List activeTraceInfoList, ThreadDumpRequest request) { + Collection activeThreadDumpList = new LimitedList(request.getLimit(), reverseOrder); + + for (ActiveTraceSnapshot activeTraceInfo : activeTraceInfoList) { + final long threadId = activeTraceInfo.getThreadId(); + if (!isTraceThread(threadId)) { + continue; + } + final ThreadInfo threadInfo = getThreadInfo(threadId, request.getStackTrace()); + if (threadInfo != null) { + ThreadDump threadDump = newThreadDump(activeTraceInfo, threadInfo); + activeThreadDumpList.add(threadDump); + } + } + + return activeThreadDumpList; + } + + private boolean isTraceThread(long threadId) { + if (threadId == -1) { + return false; + } + return true; + } + + + + private ThreadInfo getThreadInfo(long threadId, StackTrace dumpType) { + if (threadId == -1) { + return null; + } + + if (StackTrace.DUMP == dumpType) { + return ThreadMXBeanUtils.getThreadInfo(threadId); + } else { + return ThreadMXBeanUtils.getThreadInfo(threadId, 0); + } + } + + private ThreadDump newThreadDump(ActiveTraceSnapshot activeTraceInfo, ThreadInfo threadInfo) { + return new ThreadDump(activeTraceInfo, threadInfo); + } +} diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadDumpService.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadDumpService.java index 3254f781a421..a427750cb7fa 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadDumpService.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadDumpService.java @@ -16,12 +16,9 @@ package com.navercorp.pinpoint.profiler.receiver.service; -import com.navercorp.pinpoint.common.annotations.VisibleForTesting; import com.navercorp.pinpoint.common.util.JvmUtils; import com.navercorp.pinpoint.profiler.context.active.ActiveTraceSnapshot; -import com.navercorp.pinpoint.profiler.context.active.ActiveTraceRepository; import com.navercorp.pinpoint.profiler.receiver.ProfilerRequestCommandService; -import com.navercorp.pinpoint.profiler.util.ActiveThreadDumpUtils; import com.navercorp.pinpoint.profiler.util.ThreadDumpUtils; import com.navercorp.pinpoint.thrift.dto.command.TActiveThreadDump; import com.navercorp.pinpoint.thrift.dto.command.TCmdActiveThreadDump; @@ -29,8 +26,9 @@ import com.navercorp.pinpoint.thrift.dto.command.TThreadDump; import org.apache.thrift.TBase; +import java.lang.management.ThreadInfo; import java.util.ArrayList; -import java.util.Collections; +import java.util.Collection; import java.util.List; /** @@ -38,15 +36,12 @@ */ public class ActiveThreadDumpService implements ProfilerRequestCommandService { - private static final String JAVA = "JAVA"; - // TODO extract config - // See DefaultActiveTraceRepository.DEFAULT_MAX_ACTIVE_TRACE_SIZE = 1024 * 10 - static final int MAX_THREAD_DUMP_LIMIT = 1024 * 2; + static final String JAVA = "JAVA"; - private final ActiveTraceRepository activeTraceRepository; + private final ActiveThreadDumpCoreService activeThreadDumpCoreService; - public ActiveThreadDumpService(ActiveTraceRepository activeTraceRepository) { - this.activeTraceRepository = activeTraceRepository; + public ActiveThreadDumpService(ActiveThreadDumpCoreService activeThreadDumpCoreService) { + this.activeThreadDumpCoreService = activeThreadDumpCoreService; } @Override @@ -63,85 +58,38 @@ public ActiveThreadDumpService(ActiveTraceRepository activeTraceRepository) { return response; } - private List getActiveThreadDumpList(TCmdActiveThreadDump request) { - List activeTraceInfoList = activeTraceRepository.collect(); + private List getActiveThreadDumpList(TCmdActiveThreadDump tRequest) { - final int limit = getLimit(request.getLimit()); - if (activeTraceInfoList.size() > limit) { - Collections.sort(activeTraceInfoList, ActiveThreadDumpUtils.getActiveTraceInfoComparator()); - } + final ThreadDumpRequest request = ThreadDumpRequest.create(tRequest); - return getActiveThreadDumpList(request, limit, activeTraceInfoList); - } + Collection activeThreadDumpList = activeThreadDumpCoreService.getActiveThreadDumpList(request); - @VisibleForTesting - static int getLimit(int limit) { - if (0 >= limit) { - return MAX_THREAD_DUMP_LIMIT; - } - return Math.min(limit, MAX_THREAD_DUMP_LIMIT); + return toTActiveThreadDump(activeThreadDumpList); } - private List getActiveThreadDumpList(TCmdActiveThreadDump request, int limit, List activeTraceInfoList) { - int targetThreadNameListSize = request.getThreadNameListSize(); - int localTraceIdListSize = request.getLocalTraceIdListSize(); - boolean filterEnable = (targetThreadNameListSize + localTraceIdListSize) > 0; - - final int arrayLength = Math.min(limit, activeTraceInfoList.size()); - List activeThreadDumpList = new ArrayList(arrayLength); - if (filterEnable) { - for (ActiveTraceSnapshot activeTraceInfo : activeTraceInfoList) { - if (!ActiveThreadDumpUtils.isTraceThread(activeTraceInfo, request.getThreadNameList(), request.getLocalTraceIdList())) { - continue; - } - - TActiveThreadDump activeThreadDump = createActiveThreadDump(activeTraceInfo); - if (activeThreadDump != null) { - if (limit > activeThreadDumpList.size()) { - activeThreadDumpList.add(activeThreadDump); - } - } - } - } else { - for (ActiveTraceSnapshot activeTraceInfo : activeTraceInfoList) { - TActiveThreadDump activeThreadDump = createActiveThreadDump(activeTraceInfo); - if (activeThreadDump != null) { - if (limit > activeThreadDumpList.size()) { - activeThreadDumpList.add(activeThreadDump); - } - } - } - } - return activeThreadDumpList; - } + private List toTActiveThreadDump(Collection activeTraceInfoList) { - private TActiveThreadDump createActiveThreadDump(ActiveTraceSnapshot activeTraceInfo) { - final long threadId = activeTraceInfo.getThreadId(); - TThreadDump threadDump = createThreadDump(threadId, true); - if (threadDump != null) { - return createTActiveThreadDump(activeTraceInfo, threadDump); + final List result = new ArrayList(activeTraceInfoList.size()); + for (ThreadDump threadDump : activeTraceInfoList) { + TActiveThreadDump tActiveThreadDump = createTActiveThreadDump(threadDump); + result.add(tActiveThreadDump); } - return null; + + return result; } - private TThreadDump createThreadDump(long threadId, boolean isIncludeStackTrace) { - if (threadId == -1) { - return null; - } - if (isIncludeStackTrace) { - return ThreadDumpUtils.createTThreadDump(threadId); - } else { - return ThreadDumpUtils.createTThreadDump(threadId, 0); - } - } + private TActiveThreadDump createTActiveThreadDump(ThreadDump threadDump) { + final ActiveTraceSnapshot activeTraceInfo = threadDump.getActiveTraceSnapshot(); + final ThreadInfo threadInfo = threadDump.getThreadInfo(); + + TThreadDump tThreadDump = ThreadDumpUtils.createTThreadDump(threadInfo); - private TActiveThreadDump createTActiveThreadDump(ActiveTraceSnapshot activeTraceInfo, TThreadDump threadDump) { TActiveThreadDump activeThreadDump = new TActiveThreadDump(); activeThreadDump.setStartTime(activeTraceInfo.getStartTime()); activeThreadDump.setLocalTraceId(activeTraceInfo.getLocalTransactionId()); - activeThreadDump.setThreadDump(threadDump); + activeThreadDump.setThreadDump(tThreadDump); if (activeTraceInfo.isSampled()) { activeThreadDump.setSampled(true); diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadLightDumpService.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadLightDumpService.java index 2afad4059ce5..7d42ba41d79a 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadLightDumpService.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadLightDumpService.java @@ -16,12 +16,10 @@ package com.navercorp.pinpoint.profiler.receiver.service; +import com.navercorp.pinpoint.common.util.Assert; import com.navercorp.pinpoint.common.util.JvmUtils; -import com.navercorp.pinpoint.common.util.ThreadMXBeanUtils; import com.navercorp.pinpoint.profiler.context.active.ActiveTraceSnapshot; -import com.navercorp.pinpoint.profiler.context.active.ActiveTraceRepository; import com.navercorp.pinpoint.profiler.receiver.ProfilerRequestCommandService; -import com.navercorp.pinpoint.profiler.util.ActiveThreadDumpUtils; import com.navercorp.pinpoint.profiler.util.ThreadDumpUtils; import com.navercorp.pinpoint.thrift.dto.command.TActiveThreadLightDump; import com.navercorp.pinpoint.thrift.dto.command.TCmdActiveThreadLightDump; @@ -31,7 +29,7 @@ import java.lang.management.ThreadInfo; import java.util.ArrayList; -import java.util.Collections; +import java.util.Collection; import java.util.List; /** @@ -39,10 +37,11 @@ */ public class ActiveThreadLightDumpService implements ProfilerRequestCommandService { - private final ActiveTraceRepository activeTraceRepository; - public ActiveThreadLightDumpService(ActiveTraceRepository activeTraceRepository) { - this.activeTraceRepository = activeTraceRepository; + private final ActiveThreadDumpCoreService activeThreadDump; + + public ActiveThreadLightDumpService(ActiveThreadDumpCoreService activeThreadDump) { + this.activeThreadDump = Assert.requireNonNull(activeThreadDump, "activeThreadDump must not be null"); } @Override @@ -52,68 +51,33 @@ public ActiveThreadLightDumpService(ActiveTraceRepository activeTraceRepository) List activeThreadDumpList = getActiveThreadDumpList(request); TCmdActiveThreadLightDumpRes response = new TCmdActiveThreadLightDumpRes(); - response.setType("JAVA"); + response.setType(ActiveThreadDumpService.JAVA); response.setSubType(JvmUtils.getType().name()); response.setVersion(JvmUtils.getVersion().name()); response.setThreadDumps(activeThreadDumpList); return response; } - private List getActiveThreadDumpList(TCmdActiveThreadLightDump request) { - List activeTraceInfoList = activeTraceRepository.collect(); + private List getActiveThreadDumpList(TCmdActiveThreadLightDump tRequest) { + ThreadDumpRequest request = ThreadDumpRequest.create(tRequest); - int limit = request.getLimit(); - if (limit > 0) { - Collections.sort(activeTraceInfoList, ActiveThreadDumpUtils.getActiveTraceInfoComparator()); - } else { - limit = Integer.MAX_VALUE; - } + Collection activeTraceInfoList = activeThreadDump.getActiveThreadDumpList(request); - return getTActiveThreadDumpList(request, limit, activeTraceInfoList); + return toTActiveThreadLightDump(activeTraceInfoList); } - private List getTActiveThreadDumpList(TCmdActiveThreadLightDump request, int limit, List activeTraceInfoList) { - int targetThreadNameListSize = request.getThreadNameListSize(); - int localTraceIdListSize = request.getLocalTraceIdListSize(); - boolean filterEnable = (targetThreadNameListSize + localTraceIdListSize) > 0; - - List activeThreadDumpList = new ArrayList(Math.min(limit, activeTraceInfoList.size())); - if (filterEnable) { - final List threadNameList = request.getThreadNameList(); - for (ActiveTraceSnapshot activeTraceInfo : activeTraceInfoList) { - if (!ActiveThreadDumpUtils.isTraceThread(activeTraceInfo, threadNameList, request.getLocalTraceIdList())) { - continue; - } - - TActiveThreadLightDump activeThreadDump = createActiveLightThreadDump(activeTraceInfo); - if (activeThreadDump != null) { - if (limit > activeThreadDumpList.size()) { - activeThreadDumpList.add(activeThreadDump); - } - } - } - } else { - for (ActiveTraceSnapshot activeTraceInfo : activeTraceInfoList) { - TActiveThreadLightDump activeThreadDump = createActiveLightThreadDump(activeTraceInfo); - if (activeThreadDump != null) { - if (limit > activeThreadDumpList.size()) { - activeThreadDumpList.add(activeThreadDump); - } - } - } - } - return activeThreadDumpList; - } - private TActiveThreadLightDump createActiveLightThreadDump(ActiveTraceSnapshot activeTraceInfo) { - final long threadId = activeTraceInfo.getThreadId(); - if (threadId == -1) { - return null; + private List toTActiveThreadLightDump(Collection activeTraceInfoList) { + + final List result = new ArrayList(activeTraceInfoList.size()); + + for (ThreadDump threadDump : activeTraceInfoList) { + TActiveThreadLightDump tActiveThreadDump = createActiveThreadDump(threadDump); + result.add(tActiveThreadDump); } - ThreadInfo threadInfo = ThreadMXBeanUtils.findThread(threadId, 0); - TThreadLightDump threadDump = createTThreadLightDump(threadInfo); - return createActiveThreadDump(activeTraceInfo, threadDump); + + return result; } @@ -126,11 +90,17 @@ private TThreadLightDump createTThreadLightDump(ThreadInfo threadInfo) { return threadDump; } - private TActiveThreadLightDump createActiveThreadDump(ActiveTraceSnapshot activeTraceInfo, TThreadLightDump threadDump) { + private TActiveThreadLightDump createActiveThreadDump(ThreadDump threadDump) { + + final ActiveTraceSnapshot activeTraceInfo = threadDump.getActiveTraceSnapshot(); + final ThreadInfo threadInfo = threadDump.getThreadInfo(); + + TThreadLightDump tThreadLightDump = createTThreadLightDump(threadInfo); + TActiveThreadLightDump activeThreadDump = new TActiveThreadLightDump(); activeThreadDump.setStartTime(activeTraceInfo.getStartTime()); activeThreadDump.setLocalTraceId(activeTraceInfo.getLocalTransactionId()); - activeThreadDump.setThreadDump(threadDump); + activeThreadDump.setThreadDump(tThreadLightDump); if (activeTraceInfo.isSampled()) { activeThreadDump.setSampled(true); diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadService.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadService.java index 184a6e55f0b4..ccd3ff164462 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadService.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadService.java @@ -44,11 +44,13 @@ public ActiveThreadService(ProfilerConfig profilerConfig, ActiveTraceRepository if (profilerConfig.isTcpDataSenderCommandActiveThreadCountEnable()) { serviceList.add(new ActiveThreadCountService(activeTraceRepository)); } + + ActiveThreadDumpCoreService activeThreadDump = new ActiveThreadDumpCoreService(activeTraceRepository); if (profilerConfig.isTcpDataSenderCommandActiveThreadLightDumpEnable()) { - serviceList.add(new ActiveThreadLightDumpService(activeTraceRepository)); + serviceList.add(new ActiveThreadLightDumpService(activeThreadDump)); } if (profilerConfig.isTcpDataSenderCommandActiveThreadDumpEnable()) { - serviceList.add(new ActiveThreadDumpService(activeTraceRepository)); + serviceList.add(new ActiveThreadDumpService(activeThreadDump)); } } diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/LimitedList.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/LimitedList.java new file mode 100644 index 000000000000..a29479eb40df --- /dev/null +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/LimitedList.java @@ -0,0 +1,120 @@ +/* + * 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.profiler.receiver.service; + +import com.navercorp.pinpoint.common.util.Assert; + +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.PriorityQueue; +import java.util.Queue; + +/** + * @author Woonduk Kang(emeroad) + */ +class LimitedList implements Collection { + private final int maxSize; + private Comparator comparator; + private final Queue queue; + + public LimitedList(int maxSize, Comparator comparator) { + Assert.isTrue(maxSize > 0, "maxSize must not be negative"); + this.comparator = Assert.requireNonNull(comparator, "comparator must not be null"); + + this.maxSize = maxSize; + this.queue = new PriorityQueue(maxSize, comparator); + + } + + + @Override + public int size() { + return this.queue.size(); + } + + @Override + public boolean isEmpty() { + return this.queue.isEmpty(); + } + + @Override + public boolean contains(Object o) { + return this.queue.contains(o); + } + + @Override + public Iterator iterator() { + return this.queue.iterator(); + } + + @Override + public Object[] toArray() { + return this.queue.toArray(); + } + + @Override + public T[] toArray(T[] a) { + return this.queue.toArray(a); + } + + @Override + public boolean remove(Object o) { + return this.queue.remove(o); + } + + @Override + public boolean containsAll(Collection c) { + return this.queue.containsAll(c); + } + + @Override + public boolean addAll(Collection c) { + return this.queue.addAll(c); + } + + @Override + public boolean removeAll(Collection c) { + return this.queue.removeAll(c); + } + + @Override + public boolean retainAll(Collection c) { + return this.queue.retainAll(c); + } + + @Override + public void clear() { + this.queue.clear(); + } + + @Override + public boolean add(E e) { + if (queue.size() >= maxSize) { + final E minSnapshot = queue.peek(); + if (comparator.compare(minSnapshot, e) < 0) { + queue.poll(); + return queue.offer(e); + } + + return false; + } else { + return queue.add(e); + } + } + +} diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/StackTrace.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/StackTrace.java new file mode 100644 index 000000000000..cd71b1220608 --- /dev/null +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/StackTrace.java @@ -0,0 +1,24 @@ +/* + * 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.profiler.receiver.service; + +/** + * @author Woonduk Kang(emeroad) + */ +public enum StackTrace { + DUMP, SKIP +} diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/StartTimeComparator.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/StartTimeComparator.java new file mode 100644 index 000000000000..02a6d83cddf0 --- /dev/null +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/StartTimeComparator.java @@ -0,0 +1,35 @@ +/* + * 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.profiler.receiver.service; + +/** + * @author Woonduk Kang(emeroad) + */ +public class StartTimeComparator { + + static final int CHANGE_TO_NEW_ELEMENT = 1; + static final int KEEP_OLD_ELEMENT = -1; + + public static int compare(long before, long after) { + final long diff = before - after; + if (diff <= 0) { + // Do not change it for the same value for performance. + return KEEP_OLD_ELEMENT; + } + return CHANGE_TO_NEW_ELEMENT; + } +} diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ThreadDump.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ThreadDump.java new file mode 100644 index 000000000000..7d30b35873c6 --- /dev/null +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ThreadDump.java @@ -0,0 +1,44 @@ +/* + * 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.profiler.receiver.service; + +import com.navercorp.pinpoint.common.util.Assert; +import com.navercorp.pinpoint.profiler.context.active.ActiveTraceSnapshot; + +import java.lang.management.ThreadInfo; + +/** + * @author Woonduk Kang(emeroad) + */ +public class ThreadDump { + + private final ActiveTraceSnapshot activeTraceSnapshot; + private final ThreadInfo threadInfo; + + public ThreadDump(ActiveTraceSnapshot activeTraceSnapshot, ThreadInfo threadInfo) { + this.activeTraceSnapshot = Assert.requireNonNull(activeTraceSnapshot, "activeTraceSnapshot must not be null"); + this.threadInfo = Assert.requireNonNull(threadInfo, "threadInfo must not be null"); + } + + public ActiveTraceSnapshot getActiveTraceSnapshot() { + return activeTraceSnapshot; + } + + public ThreadInfo getThreadInfo() { + return threadInfo; + } +} diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ThreadDumpComparator.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ThreadDumpComparator.java new file mode 100644 index 000000000000..9203c3bb50e4 --- /dev/null +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ThreadDumpComparator.java @@ -0,0 +1,35 @@ +/* + * 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.profiler.receiver.service; + +import java.util.Comparator; + +/** + * @author Woonduk Kang(emeroad) + */ +public class ThreadDumpComparator implements Comparator { + private static final int CHANGE_TO_NEW_ELEMENT = 1; + private static final int KEEP_OLD_ELEMENT = -1; + + @Override + public int compare(ThreadDump oldElement, ThreadDump newElement) { + long oldStartTime = oldElement.getActiveTraceSnapshot().getStartTime(); + long newStartTime = newElement.getActiveTraceSnapshot().getStartTime(); + return StartTimeComparator.compare(oldStartTime, newStartTime); + } + +} diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ThreadDumpRequest.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ThreadDumpRequest.java new file mode 100644 index 000000000000..3a92830e9c65 --- /dev/null +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/receiver/service/ThreadDumpRequest.java @@ -0,0 +1,137 @@ +/* + * 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.profiler.receiver.service; + +import com.navercorp.pinpoint.common.annotations.VisibleForTesting; +import com.navercorp.pinpoint.common.util.Assert; +import com.navercorp.pinpoint.common.util.CollectionUtils; +import com.navercorp.pinpoint.thrift.dto.command.TCmdActiveThreadDump; +import com.navercorp.pinpoint.thrift.dto.command.TCmdActiveThreadLightDump; + +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @author Woonduk Kang(emeroad) + */ +public class ThreadDumpRequest { + + // TODO extract config + // See DefaultActiveTraceRepository.DEFAULT_MAX_ACTIVE_TRACE_SIZE = 1024 * 10 + static final int MAX_THREAD_DUMP_LIMIT = 1024 * 2; + + private final Set localTransactionIdSet; + private final Set threadNameSet; + private final int limit; + private final boolean enableFilter; + private final boolean localTransactionIdFilter; + private final boolean threadNameFilter; + private final StackTrace stackTrace; + + + public static ThreadDumpRequest create(TCmdActiveThreadDump request) { + Assert.requireNonNull(request, "request must not be null"); + + final int limit = getLimit(request.getLimit()); + + final List localTraceIdList = request.getLocalTraceIdList(); + final List threadNameList = request.getThreadNameList(); + + return new ThreadDumpRequest(StackTrace.DUMP, limit, localTraceIdList, threadNameList); + } + + public static ThreadDumpRequest create(TCmdActiveThreadLightDump request) { + Assert.requireNonNull(request, "request must not be null"); + + int limit = getLimit(request.getLimit()); + + final List localTraceIdList = request.getLocalTraceIdList(); + final List threadNameList = request.getThreadNameList(); + + return new ThreadDumpRequest(StackTrace.SKIP, limit, localTraceIdList, threadNameList); + } + + ThreadDumpRequest(StackTrace stackTrace, int limit, List localTraceIdList, List threadNameList) { + this.stackTrace = Assert.requireNonNull(stackTrace, "stackTrace must not be null"); + this.limit = limit; + + this.localTransactionIdSet = newHashSet(localTraceIdList); + this.localTransactionIdFilter = CollectionUtils.hasLength(localTransactionIdSet); + + this.threadNameSet = newHashSet(threadNameList); + this.threadNameFilter = CollectionUtils.hasLength(threadNameSet); + + this.enableFilter = isEnableFilter(localTransactionIdFilter, threadNameFilter); + } + + + private boolean isEnableFilter(boolean localTransactionIdFilter, boolean threadNameFilter) { + if (localTransactionIdFilter) { + return true; + } + if (threadNameFilter) { + return true; + } + + return false; + } + + @VisibleForTesting + static int getLimit(int limit) { + if (0 >= limit) { + return MAX_THREAD_DUMP_LIMIT; + } + return Math.min(limit, MAX_THREAD_DUMP_LIMIT); + } + + private Set newHashSet(List list) { + if (CollectionUtils.isEmpty(list)) { + return Collections.emptySet(); + } + return new HashSet(list); + } + + public int getLimit() { + return limit; + } + + public boolean isEnableFilter() { + return enableFilter; + } + + public boolean isEnableLocalTransactionIdFilter() { + return localTransactionIdFilter; + } + + public boolean findLocalTransactionId(long localTransactionId) { + return this.localTransactionIdSet.contains(localTransactionId); + } + + public boolean isEnableThreadNameFilter() { + return threadNameFilter; + } + + public boolean findThreadName(String threadName) { + return this.threadNameSet.contains(threadName); + } + + public StackTrace getStackTrace() { + return this.stackTrace; + } +} diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/ActiveThreadDumpUtils.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/ActiveThreadDumpUtils.java index 5de1d90a0684..4f1a8a236042 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/ActiveThreadDumpUtils.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/ActiveThreadDumpUtils.java @@ -58,7 +58,7 @@ private static boolean findThreadName(List threadNameList, long threadId return false; } - final ThreadInfo thread = ThreadMXBeanUtils.findThread(threadId); + final ThreadInfo thread = ThreadMXBeanUtils.getThreadInfo(threadId); if (filterThreadName(threadNameList, thread.getThreadName())) { return true; } @@ -84,7 +84,7 @@ public static ActiveTraceInfoComparator getActiveTraceInfoComparator() { return ACTIVE_TRACE_INFO_COMPARATOR; } - private static class ActiveTraceInfoComparator implements Comparator { + private static class ActiveTraceInfoComparator implements Comparator { private static final int CHANGE_TO_NEW_ELEMENT = 1; private static final int KEEP_OLD_ELEMENT = -1; diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/ThreadDumpUtils.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/ThreadDumpUtils.java index 1ab3ac4cc66d..d56c691ef30c 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/ThreadDumpUtils.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/ThreadDumpUtils.java @@ -36,7 +36,9 @@ public class ThreadDumpUtils { public static TThreadDump createTThreadDump(Thread thread) { - ThreadInfo threadInfo = ThreadMXBeanUtils.findThread(thread); + Assert.requireNonNull(thread, "thread must not be null"); + + ThreadInfo threadInfo = ThreadMXBeanUtils.getThreadInfo(thread.getId()); if (threadInfo == null) { return null; } @@ -45,7 +47,9 @@ public static TThreadDump createTThreadDump(Thread thread) { } public static TThreadDump createTThreadDump(Thread thread, int stackTraceMaxDepth) { - ThreadInfo threadInfo = ThreadMXBeanUtils.findThread(thread, stackTraceMaxDepth); + Assert.requireNonNull(thread, "thread must not be null"); + + ThreadInfo threadInfo = ThreadMXBeanUtils.getThreadInfo(thread.getId(), stackTraceMaxDepth); if (threadInfo == null) { return null; } @@ -65,7 +69,7 @@ public static TThreadDump createTThreadDump(ThreadInfo threadInfo) { } public static TThreadDump createTThreadDump(long threadId) { - ThreadInfo threadInfo = ThreadMXBeanUtils.findThread(threadId); + ThreadInfo threadInfo = ThreadMXBeanUtils.getThreadInfo(threadId); if (threadInfo == null) { return null; } @@ -74,7 +78,7 @@ public static TThreadDump createTThreadDump(long threadId) { } public static TThreadDump createTThreadDump(long threadId, int stackTraceMaxDepth) { - ThreadInfo threadInfo = ThreadMXBeanUtils.findThread(threadId, stackTraceMaxDepth); + ThreadInfo threadInfo = ThreadMXBeanUtils.getThreadInfo(threadId, stackTraceMaxDepth); if (threadInfo == null) { return null; } diff --git a/profiler/src/test/java/com/navercorp/pinpoint/profiler/context/active/ActiveTraceRepositoryTest.java b/profiler/src/test/java/com/navercorp/pinpoint/profiler/context/active/ActiveTraceRepositoryTest.java index 0d19a0312ef2..6bd7a02cdceb 100644 --- a/profiler/src/test/java/com/navercorp/pinpoint/profiler/context/active/ActiveTraceRepositoryTest.java +++ b/profiler/src/test/java/com/navercorp/pinpoint/profiler/context/active/ActiveTraceRepositoryTest.java @@ -88,7 +88,7 @@ public void verifyActiveTraceCollectionAndTransactionCount() throws Exception { // When ListenableFuture> futures = executeTransactions(awaitLatch, executeLatch, newTransactionCount, expectedSampledContinuationCount, expectedUnsampledContinuationCount); executeLatch.await(); - List activeTraceInfos = this.activeTraceRepository.collect(); + List activeTraceInfos = this.activeTraceRepository.snapshot(); awaitLatch.countDown(); List executedTraces = futures.get(); Map executedTraceMap = new HashMap(executedTraces.size()); diff --git a/profiler/src/test/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadDumpServiceTest.java b/profiler/src/test/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadDumpServiceTest.java index 1b3772b47384..9194238ebf3a 100644 --- a/profiler/src/test/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadDumpServiceTest.java +++ b/profiler/src/test/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadDumpServiceTest.java @@ -26,7 +26,6 @@ import com.navercorp.pinpoint.thrift.dto.command.TCmdActiveThreadDump; import com.navercorp.pinpoint.thrift.dto.command.TCmdActiveThreadDumpRes; import org.junit.Assert; -import org.junit.Before; import org.junit.Test; import java.lang.management.ThreadInfo; @@ -48,128 +47,108 @@ public class ActiveThreadDumpServiceTest { private static final long DEFAULT_TIME_MILLIS = System.currentTimeMillis() - 1000000; private static final long TIME_DIFF_INTERVAL = 100; + private static final long JOB_TIMEOUT = 1000 * 10; private final AtomicInteger idGenerator = new AtomicInteger(); private final PinpointThreadFactory pinpointThreadFactory = new PinpointThreadFactory(this.getClass().getSimpleName()); - @Before - public void setup() { - idGenerator.set(0); - } + private final WaitingJobListFactory waitingJobListFactory = new WaitingJobListFactory(); + @Test public void basicFunctionTest1() throws Exception { - List waitingJobList = createWaitingJobList(CREATE_SIZE); - try { - List activeTraceInfoList = createMockActiveTraceInfoList(CREATE_SIZE, DEFAULT_TIME_MILLIS, TIME_DIFF_INTERVAL, waitingJobList); + List waitingJobList = this.waitingJobListFactory.createList(CREATE_SIZE, JOB_TIMEOUT); - ActiveThreadDumpService service = createService(activeTraceInfoList); - TCmdActiveThreadDumpRes response = (TCmdActiveThreadDumpRes) service.requestCommandService(createRequest(0, null, null)); + List activeTraceInfoList = createMockActiveTraceInfoList(CREATE_SIZE, DEFAULT_TIME_MILLIS, TIME_DIFF_INTERVAL, waitingJobList); + + ActiveThreadDumpService service = createService(activeTraceInfoList); + TCmdActiveThreadDumpRes response = (TCmdActiveThreadDumpRes) service.requestCommandService(createRequest(0, null, null)); + + Assert.assertEquals(CREATE_SIZE, response.getThreadDumpsSize()); - Assert.assertEquals(CREATE_SIZE, response.getThreadDumpsSize()); - } finally { - clearResource(waitingJobList); - } } @Test public void basicFunctionTest2() throws Exception { - List waitingJobList = createWaitingJobList(CREATE_SIZE); + List waitingJobList = this.waitingJobListFactory.createList(CREATE_SIZE, 1000 * 3); - try { - List activeTraceInfoList = createMockActiveTraceInfoList(CREATE_SIZE, DEFAULT_TIME_MILLIS, TIME_DIFF_INTERVAL, waitingJobList); + List activeTraceInfoList = createMockActiveTraceInfoList(CREATE_SIZE, DEFAULT_TIME_MILLIS, TIME_DIFF_INTERVAL, waitingJobList); - TCmdActiveThreadDump tCmdActiveThreadDump = createRequest(0, null, Arrays.asList(1L)); + TCmdActiveThreadDump tCmdActiveThreadDump = createRequest(0, null, Arrays.asList(1L)); - ActiveThreadDumpService service = createService(activeTraceInfoList); - TCmdActiveThreadDumpRes response = (TCmdActiveThreadDumpRes) service.requestCommandService(tCmdActiveThreadDump); + ActiveThreadDumpService service = createService(activeTraceInfoList); + TCmdActiveThreadDumpRes response = (TCmdActiveThreadDumpRes) service.requestCommandService(tCmdActiveThreadDump); + + Assert.assertEquals(1, response.getThreadDumpsSize()); - Assert.assertEquals(1, response.getThreadDumpsSize()); - } finally { - clearResource(waitingJobList); - } } @Test public void basicFunctionTest3() throws Exception { - List waitingJobList = createWaitingJobList(CREATE_SIZE); + List waitingJobList = this.waitingJobListFactory.createList(CREATE_SIZE, 1000 * 3); - try { - int targetThreadNameSize = 3; + int targetThreadNameSize = 3; - List activeTraceInfoList = createMockActiveTraceInfoList(CREATE_SIZE, DEFAULT_TIME_MILLIS, TIME_DIFF_INTERVAL, waitingJobList); + List activeTraceInfoList = createMockActiveTraceInfoList(CREATE_SIZE, DEFAULT_TIME_MILLIS, TIME_DIFF_INTERVAL, waitingJobList); - List threadNameList = extractThreadNameList(activeTraceInfoList, targetThreadNameSize); - TCmdActiveThreadDump tCmdActiveThreadDump = createRequest(0, threadNameList, null); + List threadNameList = extractThreadNameList(activeTraceInfoList, targetThreadNameSize); + TCmdActiveThreadDump tCmdActiveThreadDump = createRequest(0, threadNameList, null); - ActiveThreadDumpService service = createService(activeTraceInfoList); - TCmdActiveThreadDumpRes response = (TCmdActiveThreadDumpRes) service.requestCommandService(tCmdActiveThreadDump); + ActiveThreadDumpService service = createService(activeTraceInfoList); + TCmdActiveThreadDumpRes response = (TCmdActiveThreadDumpRes) service.requestCommandService(tCmdActiveThreadDump); + + Assert.assertEquals(3, response.getThreadDumpsSize()); - Assert.assertEquals(3, response.getThreadDumpsSize()); - } finally { - clearResource(waitingJobList); - } } @Test public void basicFunctionTest4() throws Exception { - List waitingJobList = createWaitingJobList(CREATE_SIZE); + List waitingJobList = this.waitingJobListFactory.createList(CREATE_SIZE, 1000 * 3); + - try { - List activeTraceInfoList = createMockActiveTraceInfoList(CREATE_SIZE, DEFAULT_TIME_MILLIS, TIME_DIFF_INTERVAL, waitingJobList); - List copied = shuffle(activeTraceInfoList); + List activeTraceInfoList = createMockActiveTraceInfoList(CREATE_SIZE, DEFAULT_TIME_MILLIS, TIME_DIFF_INTERVAL, waitingJobList); + List copied = shuffle(activeTraceInfoList); - int targetThreadNameSize = 3; - List threadNameList = extractThreadNameList(copied.subList(0, targetThreadNameSize), targetThreadNameSize); + int targetThreadNameSize = 3; + List threadNameList = extractThreadNameList(copied.subList(0, targetThreadNameSize), targetThreadNameSize); - int targetTraceIdSize = 3; - List localTraceIdList = extractLocalTraceIdList(copied.subList(targetThreadNameSize, CREATE_SIZE), targetTraceIdSize); - TCmdActiveThreadDump tCmdActiveThreadDump = createRequest(0, threadNameList, localTraceIdList); + int targetTraceIdSize = 3; + List localTraceIdList = extractLocalTraceIdList(copied.subList(targetThreadNameSize, CREATE_SIZE), targetTraceIdSize); + TCmdActiveThreadDump tCmdActiveThreadDump = createRequest(0, threadNameList, localTraceIdList); - ActiveThreadDumpService service = createService(activeTraceInfoList); - TCmdActiveThreadDumpRes response = (TCmdActiveThreadDumpRes) service.requestCommandService(tCmdActiveThreadDump); + ActiveThreadDumpService service = createService(activeTraceInfoList); + TCmdActiveThreadDumpRes response = (TCmdActiveThreadDumpRes) service.requestCommandService(tCmdActiveThreadDump); + + Assert.assertEquals(targetThreadNameSize + targetTraceIdSize, response.getThreadDumpsSize()); - Assert.assertEquals(targetThreadNameSize + targetTraceIdSize, response.getThreadDumpsSize()); - } finally { - clearResource(waitingJobList); - } } @Test public void basicFunctionTest5() throws Exception { - List waitingJobList = createWaitingJobList(CREATE_SIZE); + List waitingJobList = this.waitingJobListFactory.createList(CREATE_SIZE, 1000 * 3); - try { - List activeTraceInfoList = createMockActiveTraceInfoList(CREATE_SIZE, DEFAULT_TIME_MILLIS, TIME_DIFF_INTERVAL, waitingJobList); - int limit = 3; - List oldTimeList = getOldTimeList(limit); + List activeTraceInfoList = createMockActiveTraceInfoList(CREATE_SIZE, DEFAULT_TIME_MILLIS, TIME_DIFF_INTERVAL, waitingJobList); - TCmdActiveThreadDump tCmdActiveThreadDump = createRequest(limit, null, null); + int limit = 3; + List oldTimeList = getOldTimeList(limit); - ActiveThreadDumpService service = createService(activeTraceInfoList); - TCmdActiveThreadDumpRes response = (TCmdActiveThreadDumpRes) service.requestCommandService(tCmdActiveThreadDump); + TCmdActiveThreadDump tCmdActiveThreadDump = createRequest(limit, null, null); - Assert.assertEquals(limit, response.getThreadDumpsSize()); + ActiveThreadDumpService service = createService(activeTraceInfoList); + TCmdActiveThreadDumpRes response = (TCmdActiveThreadDumpRes) service.requestCommandService(tCmdActiveThreadDump); - for (TActiveThreadDump dump : response.getThreadDumps()) { - Assert.assertTrue(oldTimeList.contains(dump.getStartTime())); - } - } finally { - clearResource(waitingJobList); - } - } + Assert.assertEquals(limit, response.getThreadDumpsSize()); - private List createWaitingJobList(int createActiveTraceRespositorySize) { - List waitingJobList = new ArrayList(); - for (int i = 0; i < createActiveTraceRespositorySize; i++) { - waitingJobList.add(new WaitingJob(100)); + for (TActiveThreadDump dump : response.getThreadDumps()) { + Assert.assertTrue(oldTimeList.contains(dump.getStartTime())); } - return waitingJobList; + } + private List createMockActiveTraceInfoList(int createActiveTraceRepositorySize, long currentTimeMillis, long diff, List waitingJobList) { List activeTraceInfoList = new ArrayList(createActiveTraceRepositorySize); for (int i = 0; i < createActiveTraceRepositorySize; i++) { @@ -201,7 +180,7 @@ private List extractThreadNameList(List activeTrace for (int i = 0; i < size; i++) { final ActiveTraceSnapshot activeTraceSnapshot = copied.get(i); - ThreadInfo thread = ThreadMXBeanUtils.findThread(activeTraceSnapshot.getThreadId()); + ThreadInfo thread = ThreadMXBeanUtils.getThreadInfo(activeTraceSnapshot.getThreadId()); threadNameList.add(thread.getThreadName()); } @@ -228,18 +207,19 @@ private List shuffle(List list) { private ActiveThreadDumpService createService(List activeTraceInfoList) { ActiveTraceRepository activeTraceRepository = mock(ActiveTraceRepository.class); - when(activeTraceRepository.collect()).thenReturn(activeTraceInfoList); + when(activeTraceRepository.snapshot()).thenReturn(activeTraceInfoList); - return new ActiveThreadDumpService(activeTraceRepository); + ActiveThreadDumpCoreService activeThreadDump = new ActiveThreadDumpCoreService(activeTraceRepository); + return new ActiveThreadDumpService(activeThreadDump); } @Test public void testGetLimit() { - final int maxThreadDumpLimit = ActiveThreadDumpService.MAX_THREAD_DUMP_LIMIT; - Assert.assertEquals(ActiveThreadDumpService.getLimit(-1), maxThreadDumpLimit); - Assert.assertEquals(ActiveThreadDumpService.getLimit(0), maxThreadDumpLimit); - Assert.assertEquals(ActiveThreadDumpService.getLimit(1000), 1000); - Assert.assertEquals(ActiveThreadDumpService.getLimit(maxThreadDumpLimit + 100), maxThreadDumpLimit); + final int maxThreadDumpLimit = ThreadDumpRequest.MAX_THREAD_DUMP_LIMIT; + Assert.assertEquals(ThreadDumpRequest.getLimit(-1), maxThreadDumpLimit); + Assert.assertEquals(ThreadDumpRequest.getLimit(0), maxThreadDumpLimit); + Assert.assertEquals(ThreadDumpRequest.getLimit(1000), 1000); + Assert.assertEquals(ThreadDumpRequest.getLimit(maxThreadDumpLimit + 100), maxThreadDumpLimit); } private TCmdActiveThreadDump createRequest(int limit, List threadNameList, List localTraceIdList) { @@ -256,40 +236,6 @@ private TCmdActiveThreadDump createRequest(int limit, List threadNameLis return request; } - private void clearResource(List waitingJobList) { - if (waitingJobList == null) { - return; - } - - for (WaitingJob waitingJob : waitingJobList) { - waitingJob.close(); - } - } - - private static class WaitingJob implements Runnable { - - private final long timeIntervalMillis; - private boolean close = false; - public WaitingJob(long timeIntervalMillis) { - this.timeIntervalMillis = timeIntervalMillis; - } - - @Override - public void run() { - while (!close) { - try { - Thread.sleep(timeIntervalMillis); - } catch (InterruptedException e) { - close = true; - } - } - } - - public void close() { - this.close = true; - } - - } } diff --git a/profiler/src/test/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadLightDumpServiceTest.java b/profiler/src/test/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadLightDumpServiceTest.java index 37ac5b5270a7..346253d06309 100644 --- a/profiler/src/test/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadLightDumpServiceTest.java +++ b/profiler/src/test/java/com/navercorp/pinpoint/profiler/receiver/service/ActiveThreadLightDumpServiceTest.java @@ -26,16 +26,15 @@ import com.navercorp.pinpoint.thrift.dto.command.TCmdActiveThreadLightDump; import com.navercorp.pinpoint.thrift.dto.command.TCmdActiveThreadLightDumpRes; import org.junit.Assert; -import org.junit.Before; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.lang.management.ThreadInfo; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import static org.mockito.Mockito.mock; @@ -46,132 +45,113 @@ */ public class ActiveThreadLightDumpServiceTest { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + private static final int CREATE_SIZE = 10; private static final long DEFAULT_TIME_MILLIS = System.currentTimeMillis() - 1000000; private static final long TIME_DIFF_INTERVAL = 100; + private static final long JOB_TIMEOUT = 1000 * 10; private final AtomicInteger idGenerator = new AtomicInteger(); private final PinpointThreadFactory pinpointThreadFactory = new PinpointThreadFactory(this.getClass().getSimpleName()); - @Before - public void setup() { - idGenerator.set(0); - } + private final WaitingJobListFactory waitingJobListFactory = new WaitingJobListFactory(); + @Test public void basicFunctionTest1() throws Exception { - List waitingJobList = createWaitingJobList(CREATE_SIZE); + List waitingJobList = this.waitingJobListFactory.createList(CREATE_SIZE, JOB_TIMEOUT); - try { - List activeTraceInfoList = createMockActiveTraceInfoList(CREATE_SIZE, DEFAULT_TIME_MILLIS, TIME_DIFF_INTERVAL, waitingJobList); + List activeTraceInfoList = createMockActiveTraceInfoList(CREATE_SIZE, DEFAULT_TIME_MILLIS, TIME_DIFF_INTERVAL, waitingJobList); - ActiveThreadLightDumpService service = createService(activeTraceInfoList); - TCmdActiveThreadLightDumpRes response = (TCmdActiveThreadLightDumpRes) service.requestCommandService(createRequest(0, null, null)); + ActiveThreadLightDumpService service = createService(activeTraceInfoList); + TCmdActiveThreadLightDumpRes response = (TCmdActiveThreadLightDumpRes) service.requestCommandService(createRequest(0, null, null)); + + Assert.assertEquals(CREATE_SIZE, response.getThreadDumpsSize()); - Assert.assertEquals(CREATE_SIZE, response.getThreadDumpsSize()); - } finally { - clearResource(waitingJobList); - } } @Test public void basicFunctionTest2() throws Exception { - List waitingJobList = createWaitingJobList(CREATE_SIZE); + List waitingJobList = this.waitingJobListFactory.createList(CREATE_SIZE, JOB_TIMEOUT); - try { - List activeTraceInfoList = createMockActiveTraceInfoList(CREATE_SIZE, DEFAULT_TIME_MILLIS, TIME_DIFF_INTERVAL, waitingJobList); - TCmdActiveThreadLightDump tCmdActiveThreadDump = createRequest(0, null, Arrays.asList(1L)); + List activeTraceInfoList = createMockActiveTraceInfoList(CREATE_SIZE, DEFAULT_TIME_MILLIS, TIME_DIFF_INTERVAL, waitingJobList); - ActiveThreadLightDumpService service = createService(activeTraceInfoList); - TCmdActiveThreadLightDumpRes response = (TCmdActiveThreadLightDumpRes) service.requestCommandService(tCmdActiveThreadDump); + TCmdActiveThreadLightDump tCmdActiveThreadDump = createRequest(0, null, Arrays.asList(1L)); + + ActiveThreadLightDumpService service = createService(activeTraceInfoList); + TCmdActiveThreadLightDumpRes response = (TCmdActiveThreadLightDumpRes) service.requestCommandService(tCmdActiveThreadDump); + + Assert.assertEquals(1, response.getThreadDumpsSize()); - Assert.assertEquals(1, response.getThreadDumpsSize()); - } finally { - clearResource(waitingJobList); - } } @Test public void basicFunctionTest3() throws Exception { - List waitingJobList = createWaitingJobList(CREATE_SIZE); + List waitingJobList = this.waitingJobListFactory.createList(CREATE_SIZE, JOB_TIMEOUT); - try { - int targetThreadNameSize = 3; + int targetThreadNameSize = 3; - List activeTraceInfoList = createMockActiveTraceInfoList(CREATE_SIZE, DEFAULT_TIME_MILLIS, TIME_DIFF_INTERVAL, waitingJobList); + List activeTraceInfoList = createMockActiveTraceInfoList(CREATE_SIZE, DEFAULT_TIME_MILLIS, TIME_DIFF_INTERVAL, waitingJobList); - List threadNameList = extractThreadNameList(activeTraceInfoList, targetThreadNameSize); - TCmdActiveThreadLightDump tCmdActiveThreadDump = createRequest(0, threadNameList, null); + List threadNameList = extractThreadNameList(activeTraceInfoList, targetThreadNameSize); + TCmdActiveThreadLightDump tCmdActiveThreadDump = createRequest(0, threadNameList, null); - ActiveThreadLightDumpService service = createService(activeTraceInfoList); - TCmdActiveThreadLightDumpRes response = (TCmdActiveThreadLightDumpRes) service.requestCommandService(tCmdActiveThreadDump); + ActiveThreadLightDumpService service = createService(activeTraceInfoList); + TCmdActiveThreadLightDumpRes response = (TCmdActiveThreadLightDumpRes) service.requestCommandService(tCmdActiveThreadDump); + + Assert.assertEquals(3, response.getThreadDumpsSize()); - Assert.assertEquals(3, response.getThreadDumpsSize()); - } finally { - clearResource(waitingJobList); - } } @Test public void basicFunctionTest4() throws Exception { - List waitingJobList = createWaitingJobList(CREATE_SIZE); + List waitingJobList = this.waitingJobListFactory.createList(CREATE_SIZE, JOB_TIMEOUT); - try { - List activeTraceInfoList = createMockActiveTraceInfoList(CREATE_SIZE, DEFAULT_TIME_MILLIS, TIME_DIFF_INTERVAL, waitingJobList); - List activeTraceSnapshotList = shuffle(activeTraceInfoList); - int targetThreadNameSize = 3; - List threadNameList = extractThreadNameList(activeTraceSnapshotList.subList(0, targetThreadNameSize), targetThreadNameSize); + List activeTraceInfoList = createMockActiveTraceInfoList(CREATE_SIZE, DEFAULT_TIME_MILLIS, TIME_DIFF_INTERVAL, waitingJobList); + List activeTraceSnapshotList = shuffle(activeTraceInfoList); - int targetTraceIdSize = 3; - List localTraceIdList = extractLocalTraceIdList(activeTraceSnapshotList.subList(targetThreadNameSize, CREATE_SIZE), targetTraceIdSize); - TCmdActiveThreadLightDump tCmdActiveThreadDump = createRequest(0, threadNameList, localTraceIdList); + int targetThreadNameSize = 3; + List threadNameList = extractThreadNameList(activeTraceSnapshotList.subList(0, targetThreadNameSize), targetThreadNameSize); - ActiveThreadLightDumpService service = createService(activeTraceInfoList); - TCmdActiveThreadLightDumpRes response = (TCmdActiveThreadLightDumpRes) service.requestCommandService(tCmdActiveThreadDump); + int targetTraceIdSize = 3; + List localTraceIdList = extractLocalTraceIdList(activeTraceSnapshotList.subList(targetThreadNameSize, CREATE_SIZE), targetTraceIdSize); + TCmdActiveThreadLightDump tCmdActiveThreadDump = createRequest(0, threadNameList, localTraceIdList); + + ActiveThreadLightDumpService service = createService(activeTraceInfoList); + TCmdActiveThreadLightDumpRes response = (TCmdActiveThreadLightDumpRes) service.requestCommandService(tCmdActiveThreadDump); + + Assert.assertEquals(targetThreadNameSize + targetTraceIdSize, response.getThreadDumpsSize()); - Assert.assertEquals(targetThreadNameSize + targetTraceIdSize, response.getThreadDumpsSize()); - } finally { - clearResource(waitingJobList); - } } @Test public void basicFunctionTest5() throws Exception { - List waitingJobList = createWaitingJobList(CREATE_SIZE); + List waitingJobList = this.waitingJobListFactory.createList(CREATE_SIZE, JOB_TIMEOUT); - try { - List activeTraceInfoList = createMockActiveTraceInfoList(CREATE_SIZE, DEFAULT_TIME_MILLIS, TIME_DIFF_INTERVAL, waitingJobList); - int limit = 3; - List oldTimeList = getOldTimeList(limit); + List activeTraceInfoList = createMockActiveTraceInfoList(CREATE_SIZE, DEFAULT_TIME_MILLIS, TIME_DIFF_INTERVAL, waitingJobList); - TCmdActiveThreadLightDump tCmdActiveThreadDump = createRequest(limit, null, null); + int limit = 3; + List oldTimeList = getOldTimeList(limit); - ActiveThreadLightDumpService service = createService(activeTraceInfoList); - TCmdActiveThreadLightDumpRes response = (TCmdActiveThreadLightDumpRes) service.requestCommandService(tCmdActiveThreadDump); + TCmdActiveThreadLightDump tCmdActiveThreadDump = createRequest(limit, null, null); - Assert.assertEquals(limit, response.getThreadDumpsSize()); + ActiveThreadLightDumpService service = createService(activeTraceInfoList); + TCmdActiveThreadLightDumpRes response = (TCmdActiveThreadLightDumpRes) service.requestCommandService(tCmdActiveThreadDump); - for (TActiveThreadLightDump dump : response.getThreadDumps()) { - Assert.assertTrue(oldTimeList.contains(dump.getStartTime())); - } - } finally { - clearResource(waitingJobList); - } - } + Assert.assertEquals(limit, response.getThreadDumpsSize()); - private List createWaitingJobList(int createActiveTraceRepositorySize) { - List waitingJobList = new ArrayList(); - for (int i = 0; i < createActiveTraceRepositorySize; i++) { - WaitingJob latchJob = new WaitingJob(1000 * 10); - waitingJobList.add(latchJob); + for (TActiveThreadLightDump dump : response.getThreadDumps()) { + Assert.assertTrue(oldTimeList.contains(dump.getStartTime())); } - return waitingJobList; + } + private List createMockActiveTraceInfoList(int createActiveTraceRepositorySize, long currentTimeMillis, long diff, List waitingJobList) { List activeTraceInfoList = new ArrayList(createActiveTraceRepositorySize); for (int i = 0; i < createActiveTraceRepositorySize; i++) { @@ -202,7 +182,7 @@ private List extractThreadNameList(List activeTrace for (int i = 0; i < size; i++) { final ActiveTraceSnapshot activeTraceSnapshot = activeTraceSnapshotList.get(i); final long threadId = activeTraceSnapshot.getThreadId(); - ThreadInfo thread = ThreadMXBeanUtils.findThread(threadId); + ThreadInfo thread = ThreadMXBeanUtils.getThreadInfo(threadId); threadNameList.add(thread.getThreadName()); } @@ -228,9 +208,10 @@ private List shuffle(List list) { private ActiveThreadLightDumpService createService(List activeTraceInfoList) { ActiveTraceRepository activeTraceRepository = mock(ActiveTraceRepository.class); - when(activeTraceRepository.collect()).thenReturn(activeTraceInfoList); + when(activeTraceRepository.snapshot()).thenReturn(activeTraceInfoList); - return new ActiveThreadLightDumpService(activeTraceRepository); + ActiveThreadDumpCoreService activeThreadDump = new ActiveThreadDumpCoreService(activeTraceRepository); + return new ActiveThreadLightDumpService(activeThreadDump); } private TCmdActiveThreadLightDump createRequest(int limit, List threadNameList, List localTraceIdList) { @@ -247,44 +228,4 @@ private TCmdActiveThreadLightDump createRequest(int limit, List threadNa return request; } - private void clearResource(List waitingJobList) { - if (waitingJobList == null) { - return; - } - - for (WaitingJob waitingJob : waitingJobList) { - waitingJob.close(); - } - } - - private static class WaitingJob implements Runnable { - - private final CountDownLatch latch = new CountDownLatch(1); - private final long timeIntervalMillis; - - public WaitingJob(long timeIntervalMillis) { - this.timeIntervalMillis = timeIntervalMillis; - } - - @Override - public void run() { - try { - latch.await(timeIntervalMillis, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - - public void close() { - latch.countDown(); - } - - } - - @Test - public void tet() { -// 382899065050 - System.out.println("" + TimeUnit.NANOSECONDS.toMinutes(382899065050L)); - } - } diff --git a/profiler/src/test/java/com/navercorp/pinpoint/profiler/receiver/service/LimitedListTest.java b/profiler/src/test/java/com/navercorp/pinpoint/profiler/receiver/service/LimitedListTest.java new file mode 100644 index 000000000000..625ba43428f0 --- /dev/null +++ b/profiler/src/test/java/com/navercorp/pinpoint/profiler/receiver/service/LimitedListTest.java @@ -0,0 +1,116 @@ +/* + * 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.profiler.receiver.service; + +import com.google.common.collect.Lists; +import com.navercorp.pinpoint.profiler.context.active.ActiveTraceSnapshot; +import com.navercorp.pinpoint.profiler.context.active.UnsampledActiveTraceSnapshot; +import com.navercorp.pinpoint.profiler.util.ActiveThreadDumpUtils; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.management.ThreadInfo; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import static org.mockito.Mockito.mock; + +/** + * @author Woonduk Kang(emeroad) + */ +public class LimitedListTest { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + + @Test + public void testMaxSize() { + Comparator threadDump = Collections.reverseOrder(new ThreadDumpComparator()); + + final int maxSize = 10; + Collection limitedList = new LimitedList(maxSize, threadDump); + + final int id = 100; + final long startTime = System.currentTimeMillis(); + final long threadId = 1000; + + logger.debug("startTime:{}", startTime); + final List testData = newTestData(id, startTime, threadId, maxSize * 2); + final long lastTime = getListObject(testData).getActiveTraceSnapshot().getStartTime(); + + logger.debug("addAll "); + limitedList.addAll(testData); + + logger.debug("size:{}", limitedList.size()); + for (ThreadDump activeTraceSnapshot : limitedList) { + logger.debug("priorityQueue:{}", activeTraceSnapshot); + } + + List sortedList = Lists.newArrayList(limitedList); + Collections.sort(sortedList, threadDump); + for (ThreadDump activeTraceSnapshot : sortedList) { + logger.debug("poll:{}", activeTraceSnapshot ); + } + + ThreadDump last = getListObject(sortedList); + logger.debug("last pool:{}", last); + logger.debug("poll.startTime:{}", last.getActiveTraceSnapshot().getStartTime()); + logger.debug("startTime:{}", lastTime); + Assert.assertEquals(last.getActiveTraceSnapshot().getStartTime(), startTime); + + } + + private T getListObject(List testData) { + int lastIndex = getListIndex(testData); + return testData.get(lastIndex); + } + + private int getListIndex(List testData) { + return testData.size() -1; + } + + private List newTestData(int localTransactionId, long startTime, long threadId, int size) { + + List result = new ArrayList(); + for (int i = 0; i < size; i++) { + + ActiveTraceSnapshot activeTraceSnapshot = new UnsampledActiveTraceSnapshot(localTransactionId, startTime, threadId); + ThreadInfo threadInfo = mock(ThreadInfo.class); + ThreadDump threadDump = new ThreadDump(activeTraceSnapshot, threadInfo); + + threadId++; + localTransactionId++; + startTime++; + result.add(threadDump); + } + + for (ThreadDump threadDump : result) { + logger.debug("newTestData:{}", threadDump); + } + + Collections.shuffle(result); + + return result; + } + + +} \ No newline at end of file diff --git a/profiler/src/test/java/com/navercorp/pinpoint/profiler/receiver/service/WaitingJob.java b/profiler/src/test/java/com/navercorp/pinpoint/profiler/receiver/service/WaitingJob.java new file mode 100644 index 000000000000..668f8bf08512 --- /dev/null +++ b/profiler/src/test/java/com/navercorp/pinpoint/profiler/receiver/service/WaitingJob.java @@ -0,0 +1,45 @@ +/* + * 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.profiler.receiver.service; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * @author Woonduk Kang(emeroad) + */ +class WaitingJob implements Runnable { + private final CountDownLatch latch = new CountDownLatch(1); + private final long timeIntervalMillis; + + public WaitingJob(long timeIntervalMillis) { + this.timeIntervalMillis = timeIntervalMillis; + } + + @Override + public void run() { + try { + latch.await(timeIntervalMillis, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + public void close() { + latch.countDown(); + } +} diff --git a/profiler/src/test/java/com/navercorp/pinpoint/profiler/receiver/service/WaitingJobListFactory.java b/profiler/src/test/java/com/navercorp/pinpoint/profiler/receiver/service/WaitingJobListFactory.java new file mode 100644 index 000000000000..62f4cd419fab --- /dev/null +++ b/profiler/src/test/java/com/navercorp/pinpoint/profiler/receiver/service/WaitingJobListFactory.java @@ -0,0 +1,54 @@ +/* + * 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.profiler.receiver.service; + +import com.navercorp.pinpoint.common.util.Assert; +import com.navercorp.pinpoint.common.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Woonduk Kang(emeroad) + */ +class WaitingJobListFactory { + + private List waitingJobList = new ArrayList(); + + + public List createList(int size, long timeout) { + Assert.state(waitingJobList.isEmpty(), "WaitingJob not close"); + + for (int i = 0; i < size; i++) { + WaitingJob latchJob = new WaitingJob(timeout); + waitingJobList.add(latchJob); + } + return waitingJobList; + } + + + public void close() { + if (this.waitingJobList.isEmpty()) { + return; + } + + for (WaitingJob waitingJob : waitingJobList) { + waitingJob.close(); + } + waitingJobList.clear(); + } +}