diff --git a/src/main/java/com/uber/profiling/AgentImpl.java b/src/main/java/com/uber/profiling/AgentImpl.java index cb15fb6..0f26936 100644 --- a/src/main/java/com/uber/profiling/AgentImpl.java +++ b/src/main/java/com/uber/profiling/AgentImpl.java @@ -30,19 +30,16 @@ import com.uber.profiling.util.AgentLogger; import com.uber.profiling.util.ClassAndMethodLongMetricBuffer; import com.uber.profiling.util.ClassMethodArgumentMetricBuffer; -import com.uber.profiling.util.JsonUtils; import com.uber.profiling.util.SparkUtils; import com.uber.profiling.util.StacktraceMetricBuffer; - import java.lang.instrument.Instrumentation; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.List; import java.util.Map; import java.util.UUID; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class AgentImpl { @@ -52,7 +49,14 @@ public class AgentImpl { private static final int MAX_THREAD_POOL_SIZE = 2; - private boolean started = false; + private Map profilers = new ConcurrentHashMap<>(); + private String processUuid; + private String appId; + private JavaAgentFileTransformer transformer; + private Thread shutdownHook; + // use ScheduledThreadPoolExecutor instead of executor service + // so we can set setRemoveOnCancelPolicy + private ScheduledThreadPoolExecutor scheduledExecutorService; public void run(Arguments arguments, Instrumentation instrumentation, Collection objectsToCloseOnShutdown) { if (arguments.isNoop()) { @@ -62,173 +66,166 @@ public void run(Arguments arguments, Instrumentation instrumentation, Collection Reporter reporter = arguments.getReporter(); - String processUuid = UUID.randomUUID().toString(); - - String appId = null; - - String appIdVariable = arguments.getAppIdVariable(); - if (appIdVariable != null && !appIdVariable.isEmpty()) { - appId = System.getenv(appIdVariable); - } - - if (appId == null || appId.isEmpty()) { - appId = SparkUtils.probeAppId(arguments.getAppIdRegex()); - } - - if (!arguments.getDurationProfiling().isEmpty() - || !arguments.getArgumentProfiling().isEmpty()) { - instrumentation.addTransformer(new JavaAgentFileTransformer(arguments.getDurationProfiling(), arguments.getArgumentProfiling())); + if (processUuid == null) { + processUuid = UUID.randomUUID().toString(); } - List profilers = createProfilers(reporter, arguments, processUuid, appId); - - ProfilerGroup profilerGroup = startProfilers(profilers); - - Thread shutdownHook = new Thread(new ShutdownHookRunner(profilerGroup.getPeriodicProfilers(), Arrays.asList(reporter), objectsToCloseOnShutdown)); - Runtime.getRuntime().addShutdownHook(shutdownHook); - } - - public ProfilerGroup startProfilers(Collection profilers) { - if (started) { - logger.warn("Profilers already started, do not start it again"); - return new ProfilerGroup(new ArrayList<>(), new ArrayList<>()); - } - - List oneTimeProfilers = new ArrayList<>(); - List periodicProfilers = new ArrayList<>(); - - for (Profiler profiler : profilers) { - if (profiler.getIntervalMillis() == 0) { - oneTimeProfilers.add(profiler); - } else if (profiler.getIntervalMillis() > 0) { - periodicProfilers.add(profiler); - } else { - logger.log(String.format("Ignored profiler %s due to its invalid interval %s", profiler, profiler.getIntervalMillis())); + if (appId == null){ + String appIdVariable = arguments.getAppIdVariable(); + if (appIdVariable != null && !appIdVariable.isEmpty()) { + appId = System.getenv(appIdVariable); } - } - for (Profiler profiler : oneTimeProfilers) { - try { - profiler.profile(); - logger.info("Finished one time profiler: " + profiler); - } catch (Throwable ex) { - logger.warn("Failed to run one time profiler: " + profiler, ex); + if (appId == null || appId.isEmpty()) { + appId = SparkUtils.probeAppId(arguments.getAppIdRegex()); } } - for (Profiler profiler : periodicProfilers) { - try { - profiler.profile(); - logger.info("Ran periodic profiler (first run): " + profiler); - } catch (Throwable ex) { - logger.warn("Failed to run periodic profiler (first run): " + profiler, ex); + if (transformer == null) { + if (!arguments.getDurationProfiling().isEmpty() + || !arguments.getArgumentProfiling().isEmpty()) { + transformer = new JavaAgentFileTransformer( + arguments.getDurationProfiling(), + arguments.getArgumentProfiling()); + instrumentation.addTransformer(transformer); } } - - scheduleProfilers(periodicProfilers); - started = true; - return new ProfilerGroup(oneTimeProfilers, periodicProfilers); + createProfilers(reporter, arguments, processUuid, appId); + scheduleProfilers(); + + // set set/update shutdown hook + if (shutdownHook != null) { + // cancel previous, in case new profilers are added at runtime + Runtime.getRuntime().removeShutdownHook(shutdownHook); + } + shutdownHook = new Thread(new ShutdownHookRunner(profilers.values(), + Arrays.asList(reporter), objectsToCloseOnShutdown)); + Runtime.getRuntime().addShutdownHook(shutdownHook); } - private List createProfilers(Reporter reporter, Arguments arguments, String processUuid, String appId) { + private void createProfilers(Reporter reporter, Arguments arguments, String processUuid, String appId) { String tag = arguments.getTag(); String cluster = arguments.getCluster(); long metricInterval = arguments.getMetricInterval(); - List profilers = new ArrayList<>(); - - CpuAndMemoryProfiler cpuAndMemoryProfiler = new CpuAndMemoryProfiler(reporter); - cpuAndMemoryProfiler.setTag(tag); - cpuAndMemoryProfiler.setCluster(cluster); - cpuAndMemoryProfiler.setIntervalMillis(metricInterval); - cpuAndMemoryProfiler.setProcessUuid(processUuid); - cpuAndMemoryProfiler.setAppId(appId); - - profilers.add(cpuAndMemoryProfiler); - - ProcessInfoProfiler processInfoProfiler = new ProcessInfoProfiler(reporter); - processInfoProfiler.setTag(tag); - processInfoProfiler.setCluster(cluster); - processInfoProfiler.setProcessUuid(processUuid); - processInfoProfiler.setAppId(appId); - - profilers.add(processInfoProfiler); + // create once the profiler, + // but update interval period in case this is changed at runtime + profilers.computeIfAbsent(CpuAndMemoryProfiler.PROFILER_NAME, k -> { + CpuAndMemoryProfiler cpuAndMemoryProfiler = new CpuAndMemoryProfiler(reporter); + cpuAndMemoryProfiler.setTag(tag); + cpuAndMemoryProfiler.setCluster(cluster); + cpuAndMemoryProfiler.setProcessUuid(processUuid); + cpuAndMemoryProfiler.setAppId(appId); + return cpuAndMemoryProfiler; + } ).setIntervalMillis(metricInterval); + + profilers.computeIfAbsent(ProcessInfoProfiler.PROFILER_NAME, k -> { + ProcessInfoProfiler processInfoProfiler = new ProcessInfoProfiler(reporter); + processInfoProfiler.setTag(tag); + processInfoProfiler.setCluster(cluster); + processInfoProfiler.setProcessUuid(processUuid); + processInfoProfiler.setAppId(appId); + processInfoProfiler.setIntervalMillis(-1); + return processInfoProfiler; + }); if (!arguments.getDurationProfiling().isEmpty()) { - ClassAndMethodLongMetricBuffer classAndMethodMetricBuffer = new ClassAndMethodLongMetricBuffer(); - - MethodDurationProfiler methodDurationProfiler = new MethodDurationProfiler(classAndMethodMetricBuffer, reporter); - methodDurationProfiler.setTag(tag); - methodDurationProfiler.setCluster(cluster); - methodDurationProfiler.setIntervalMillis(metricInterval); - methodDurationProfiler.setProcessUuid(processUuid); - methodDurationProfiler.setAppId(appId); - - MethodDurationCollector methodDurationCollector = new MethodDurationCollector(classAndMethodMetricBuffer); - MethodProfilerStaticProxy.setCollector(methodDurationCollector); - - profilers.add(methodDurationProfiler); + profilers.computeIfAbsent(MethodDurationProfiler.PROFILER_NAME, k -> { + ClassAndMethodLongMetricBuffer classAndMethodMetricBuffer = new ClassAndMethodLongMetricBuffer(); + + MethodDurationProfiler methodDurationProfiler = new MethodDurationProfiler( + classAndMethodMetricBuffer, reporter); + methodDurationProfiler.setTag(tag); + methodDurationProfiler.setCluster(cluster); + methodDurationProfiler.setProcessUuid(processUuid); + methodDurationProfiler.setAppId(appId); + + MethodDurationCollector methodDurationCollector = new MethodDurationCollector( + classAndMethodMetricBuffer); + MethodProfilerStaticProxy.setCollector(methodDurationCollector); + return methodDurationProfiler; + }).setIntervalMillis(metricInterval); } if (!arguments.getArgumentProfiling().isEmpty()) { - ClassMethodArgumentMetricBuffer classAndMethodArgumentBuffer = new ClassMethodArgumentMetricBuffer(); + profilers.computeIfAbsent(MethodArgumentCollector.PROFILER_NAME, k -> { + ClassMethodArgumentMetricBuffer classAndMethodArgumentBuffer = new ClassMethodArgumentMetricBuffer(); + + MethodArgumentProfiler methodArgumentProfiler = new MethodArgumentProfiler( + classAndMethodArgumentBuffer, reporter); + methodArgumentProfiler.setTag(tag); + methodArgumentProfiler.setCluster(cluster); + methodArgumentProfiler.setProcessUuid(processUuid); + methodArgumentProfiler.setAppId(appId); + + MethodArgumentCollector methodArgumentCollector = new MethodArgumentCollector( + classAndMethodArgumentBuffer); + MethodProfilerStaticProxy.setArgumentCollector(methodArgumentCollector); + return methodArgumentProfiler; + }).setIntervalMillis(metricInterval); - MethodArgumentProfiler methodArgumentProfiler = new MethodArgumentProfiler(classAndMethodArgumentBuffer, reporter); - methodArgumentProfiler.setTag(tag); - methodArgumentProfiler.setCluster(cluster); - methodArgumentProfiler.setIntervalMillis(metricInterval); - methodArgumentProfiler.setProcessUuid(processUuid); - methodArgumentProfiler.setAppId(appId); - - MethodArgumentCollector methodArgumentCollector = new MethodArgumentCollector(classAndMethodArgumentBuffer); - MethodProfilerStaticProxy.setArgumentCollector(methodArgumentCollector); - - profilers.add(methodArgumentProfiler); } - - if (arguments.getSampleInterval() > 0) { - StacktraceMetricBuffer stacktraceMetricBuffer = new StacktraceMetricBuffer(); - - StacktraceCollectorProfiler stacktraceCollectorProfiler = new StacktraceCollectorProfiler(stacktraceMetricBuffer, AgentThreadFactory.NAME_PREFIX); - stacktraceCollectorProfiler.setIntervalMillis(arguments.getSampleInterval()); - - StacktraceReporterProfiler stacktraceReporterProfiler = new StacktraceReporterProfiler(stacktraceMetricBuffer, reporter); - stacktraceReporterProfiler.setTag(tag); - stacktraceReporterProfiler.setCluster(cluster); - stacktraceReporterProfiler.setIntervalMillis(metricInterval); - stacktraceReporterProfiler.setProcessUuid(processUuid); - stacktraceReporterProfiler.setAppId(appId); - - profilers.add(stacktraceCollectorProfiler); - profilers.add(stacktraceReporterProfiler); + + profilers + .computeIfAbsent(StacktraceReporterProfiler.PROFILER_NAME, k -> { + StacktraceMetricBuffer stacktraceMetricBuffer = new StacktraceMetricBuffer(); + StacktraceReporterProfiler stacktraceReporterProfiler = new StacktraceReporterProfiler( + stacktraceMetricBuffer, reporter); + stacktraceReporterProfiler.setTag(tag); + stacktraceReporterProfiler.setCluster(cluster); + stacktraceReporterProfiler.setProcessUuid(processUuid); + stacktraceReporterProfiler.setAppId(appId); + return stacktraceReporterProfiler; + }).setIntervalMillis(metricInterval); + + Profiler reporterProfiler = profilers.get(StacktraceReporterProfiler.PROFILER_NAME); + if (reporterProfiler != null) { + profilers.computeIfAbsent(StacktraceCollectorProfiler.PROFILER_NAME, k -> { + StacktraceCollectorProfiler stacktraceCollectorProfiler = new StacktraceCollectorProfiler( + ((StacktraceReporterProfiler) reporterProfiler).getBuffer(), + AgentThreadFactory.NAME_PREFIX); + return stacktraceCollectorProfiler; + }).setIntervalMillis(arguments.getSampleInterval()); } if (arguments.isIoProfiling()) { - IOProfiler ioProfiler = new IOProfiler(reporter); - ioProfiler.setTag(tag); - ioProfiler.setCluster(cluster); - ioProfiler.setIntervalMillis(metricInterval); - ioProfiler.setProcessUuid(processUuid); - ioProfiler.setAppId(appId); - - profilers.add(ioProfiler); + profilers.computeIfAbsent(IOProfiler.PROFILER_NAME, k -> { + IOProfiler ioProfiler = new IOProfiler(reporter); + ioProfiler.setTag(tag); + ioProfiler.setCluster(cluster); + ioProfiler.setProcessUuid(processUuid); + ioProfiler.setAppId(appId); + + return ioProfiler; + }).setIntervalMillis(metricInterval); } - - return profilers; } - private void scheduleProfilers(Collection profilers) { - int threadPoolSize = Math.min(profilers.size(), MAX_THREAD_POOL_SIZE); - ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(threadPoolSize, new AgentThreadFactory()); - for (Profiler profiler : profilers) { + private void scheduleProfilers() { + if (scheduledExecutorService == null) { + int threadPoolSize = Math.min(profilers.size(), MAX_THREAD_POOL_SIZE); + scheduledExecutorService = new ScheduledThreadPoolExecutor(threadPoolSize, new AgentThreadFactory()); + scheduledExecutorService.setRemoveOnCancelPolicy(true); + } + + for (Profiler profiler : profilers.values()) { + if (profiler.getRunner() != null && profiler.getRunner().getHandler() != null) { + //cancel previous task if already scheduled + profiler.getRunner().getHandler().cancel(false); + } + if (profiler.getIntervalMillis() <= 0){ + //one time profiler, don't schedule + continue; + } if (profiler.getIntervalMillis() < Arguments.MIN_INTERVAL_MILLIS) { throw new RuntimeException("Interval too short for profiler: " + profiler + ", must be at least " + Arguments.MIN_INTERVAL_MILLIS); } - ProfilerRunner worker = new ProfilerRunner(profiler); - scheduledExecutorService.scheduleAtFixedRate(worker, 0, profiler.getIntervalMillis(), TimeUnit.MILLISECONDS); + ScheduledFuture handler = scheduledExecutorService.scheduleAtFixedRate(worker, 0, profiler.getIntervalMillis(), TimeUnit.MILLISECONDS); + worker.setHandler(handler); + profiler.setRunner(worker); logger.info(String.format("Scheduled profiler %s with interval %s millis", profiler, profiler.getIntervalMillis())); } } diff --git a/src/main/java/com/uber/profiling/Arguments.java b/src/main/java/com/uber/profiling/Arguments.java index 8052355..2eda09f 100644 --- a/src/main/java/com/uber/profiling/Arguments.java +++ b/src/main/java/com/uber/profiling/Arguments.java @@ -23,7 +23,6 @@ import com.uber.profiling.util.DummyConfigProvider; import com.uber.profiling.util.JsonUtils; import com.uber.profiling.util.ReflectionUtils; - import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.HashMap; @@ -59,6 +58,7 @@ public class Arguments { private boolean noop = false; private Constructor reporterConstructor; + private Reporter reporter; private Constructor configProviderConstructor; private String configFile; @@ -260,11 +260,14 @@ public Map> getRawArgValues() { } public Reporter getReporter() { + if (reporter != null) { + return reporter; + } if (reporterConstructor == null) { return new ConsoleOutputReporter(); } else { try { - Reporter reporter = reporterConstructor.newInstance(); + reporter = reporterConstructor.newInstance(); reporter.updateArguments(getRawArgValues()); return reporter; } catch (Throwable e) { diff --git a/src/main/java/com/uber/profiling/Profiler.java b/src/main/java/com/uber/profiling/Profiler.java index 464b8a0..7832f46 100644 --- a/src/main/java/com/uber/profiling/Profiler.java +++ b/src/main/java/com/uber/profiling/Profiler.java @@ -16,10 +16,20 @@ package com.uber.profiling; -public interface Profiler { - long getIntervalMillis(); +public abstract class Profiler { + private ProfilerRunner runner; - void setReporter(Reporter reporter); + public abstract long getIntervalMillis(); + public abstract void setIntervalMillis(long millis); - void profile(); + public abstract void setReporter(Reporter reporter); + + public abstract void profile(); + + void setRunner(ProfilerRunner runner){ + this.runner = runner; + } + ProfilerRunner getRunner(){ + return this.runner; + } } diff --git a/src/main/java/com/uber/profiling/ProfilerGroup.java b/src/main/java/com/uber/profiling/ProfilerGroup.java deleted file mode 100644 index 5e4b36d..0000000 --- a/src/main/java/com/uber/profiling/ProfilerGroup.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2018 Uber Technologies, Inc. - * - * 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.uber.profiling; - -import java.util.ArrayList; -import java.util.List; - -public class ProfilerGroup { - private List oneTimeProfilers; - private List periodicProfilers; - - public ProfilerGroup(List oneTimeProfilers, List periodicProfilers) { - this.oneTimeProfilers = new ArrayList<>(oneTimeProfilers); - this.periodicProfilers = new ArrayList<>(periodicProfilers); - } - - public List getOneTimeProfilers() { - return oneTimeProfilers; - } - - public List getPeriodicProfilers() { - return periodicProfilers; - } -} diff --git a/src/main/java/com/uber/profiling/ProfilerRunner.java b/src/main/java/com/uber/profiling/ProfilerRunner.java index bcd6db3..b7c5cfa 100644 --- a/src/main/java/com/uber/profiling/ProfilerRunner.java +++ b/src/main/java/com/uber/profiling/ProfilerRunner.java @@ -18,6 +18,7 @@ import com.uber.profiling.util.AgentLogger; +import java.util.concurrent.ScheduledFuture; import java.util.concurrent.atomic.AtomicLong; public class ProfilerRunner implements Runnable { @@ -27,6 +28,7 @@ public class ProfilerRunner implements Runnable { private final Profiler profiler; private final AtomicLong errorCounter = new AtomicLong(0); + private ScheduledFuture handler; public ProfilerRunner(Profiler profiler) { this.profiler = profiler; @@ -45,4 +47,12 @@ public void run() { } } } + + public void setHandler(ScheduledFuture handler) { + this.handler = handler; + } + + public ScheduledFuture getHandler() { + return handler; + } } diff --git a/src/main/java/com/uber/profiling/ShutdownHookRunner.java b/src/main/java/com/uber/profiling/ShutdownHookRunner.java index 26eaca6..0201872 100644 --- a/src/main/java/com/uber/profiling/ShutdownHookRunner.java +++ b/src/main/java/com/uber/profiling/ShutdownHookRunner.java @@ -42,6 +42,10 @@ public void run() { for (Profiler profiler : profilers) { try { + if (profiler.getIntervalMillis() <=0 ){ + //one time profiler, skip + continue; + } logShutdownMessage("Running periodic profiler (last run): " + profiler); profiler.profile(); logShutdownMessage("Ran periodic profiler (last run): " + profiler); diff --git a/src/main/java/com/uber/profiling/profilers/CpuAndMemoryProfiler.java b/src/main/java/com/uber/profiling/profilers/CpuAndMemoryProfiler.java index df7db8d..6abed1d 100644 --- a/src/main/java/com/uber/profiling/profilers/CpuAndMemoryProfiler.java +++ b/src/main/java/com/uber/profiling/profilers/CpuAndMemoryProfiler.java @@ -16,7 +16,6 @@ package com.uber.profiling.profilers; -import com.uber.profiling.Profiler; import com.uber.profiling.Reporter; import com.uber.profiling.util.AgentLogger; import com.uber.profiling.util.ProcFileUtils; @@ -36,7 +35,7 @@ import java.util.List; import java.util.Map; -public class CpuAndMemoryProfiler extends ProcessInfoBase implements Profiler { +public class CpuAndMemoryProfiler extends ProcessInfoBase { public final static String PROFILER_NAME = "CpuAndMemory"; private static final AgentLogger logger = AgentLogger.getLogger(CpuAndMemoryProfiler.class.getName()); @@ -70,6 +69,7 @@ public long getIntervalMillis() { return intervalMillis; } + @Override public void setIntervalMillis(long intervalMillis) { this.intervalMillis = intervalMillis; } diff --git a/src/main/java/com/uber/profiling/profilers/IOProfiler.java b/src/main/java/com/uber/profiling/profilers/IOProfiler.java index 8f3bc1b..7392c3c 100644 --- a/src/main/java/com/uber/profiling/profilers/IOProfiler.java +++ b/src/main/java/com/uber/profiling/profilers/IOProfiler.java @@ -16,7 +16,6 @@ package com.uber.profiling.profilers; -import com.uber.profiling.Profiler; import com.uber.profiling.Reporter; import com.uber.profiling.util.ProcFileUtils; @@ -24,7 +23,7 @@ import java.util.List; import java.util.Map; -public class IOProfiler extends ProcessInfoBase implements Profiler { +public class IOProfiler extends ProcessInfoBase { public final static String PROFILER_NAME = "IO"; private long intervalMillis = Constants.DEFAULT_METRIC_INTERVAL; diff --git a/src/main/java/com/uber/profiling/profilers/MethodArgumentCollector.java b/src/main/java/com/uber/profiling/profilers/MethodArgumentCollector.java index c7d3688..7011670 100644 --- a/src/main/java/com/uber/profiling/profilers/MethodArgumentCollector.java +++ b/src/main/java/com/uber/profiling/profilers/MethodArgumentCollector.java @@ -19,6 +19,7 @@ import com.uber.profiling.util.ClassMethodArgumentMetricBuffer; public class MethodArgumentCollector { + public static final String PROFILER_NAME = "MethodArgumentCollector"; private ClassMethodArgumentMetricBuffer buffer; public MethodArgumentCollector(ClassMethodArgumentMetricBuffer buffer) { diff --git a/src/main/java/com/uber/profiling/profilers/MethodArgumentProfiler.java b/src/main/java/com/uber/profiling/profilers/MethodArgumentProfiler.java index 990157d..cd31497 100644 --- a/src/main/java/com/uber/profiling/profilers/MethodArgumentProfiler.java +++ b/src/main/java/com/uber/profiling/profilers/MethodArgumentProfiler.java @@ -16,7 +16,6 @@ package com.uber.profiling.profilers; -import com.uber.profiling.Profiler; import com.uber.profiling.Reporter; import com.uber.profiling.reporters.ConsoleOutputReporter; import com.uber.profiling.util.ClassAndMethodMetricKey; @@ -26,7 +25,7 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicLong; -public class MethodArgumentProfiler extends ProcessInfoBase implements Profiler { +public class MethodArgumentProfiler extends ProcessInfoBase { public static final String PROFILER_NAME = "MethodArgument"; private ClassMethodArgumentMetricBuffer buffer; diff --git a/src/main/java/com/uber/profiling/profilers/MethodDurationProfiler.java b/src/main/java/com/uber/profiling/profilers/MethodDurationProfiler.java index ea21484..ca1215b 100644 --- a/src/main/java/com/uber/profiling/profilers/MethodDurationProfiler.java +++ b/src/main/java/com/uber/profiling/profilers/MethodDurationProfiler.java @@ -16,7 +16,6 @@ package com.uber.profiling.profilers; -import com.uber.profiling.Profiler; import com.uber.profiling.Reporter; import com.uber.profiling.reporters.ConsoleOutputReporter; import com.uber.profiling.util.ClassAndMethodLongMetricBuffer; @@ -26,7 +25,7 @@ import java.util.HashMap; import java.util.Map; -public class MethodDurationProfiler extends ProcessInfoBase implements Profiler { +public class MethodDurationProfiler extends ProcessInfoBase { public static final String PROFILER_NAME = "MethodDuration"; private ClassAndMethodLongMetricBuffer buffer; diff --git a/src/main/java/com/uber/profiling/profilers/ProcessInfoBase.java b/src/main/java/com/uber/profiling/profilers/ProcessInfoBase.java index 07d5b5f..0c04a4a 100644 --- a/src/main/java/com/uber/profiling/profilers/ProcessInfoBase.java +++ b/src/main/java/com/uber/profiling/profilers/ProcessInfoBase.java @@ -16,6 +16,7 @@ package com.uber.profiling.profilers; +import com.uber.profiling.Profiler; import com.uber.profiling.util.NetworkUtils; import com.uber.profiling.util.ProcFileUtils; import com.uber.profiling.util.ProcessUtils; @@ -23,7 +24,7 @@ import java.util.UUID; -public class ProcessInfoBase { +public abstract class ProcessInfoBase extends Profiler { private String tag = null; private String cluster = null; private String hostName = null; diff --git a/src/main/java/com/uber/profiling/profilers/ProcessInfoProfiler.java b/src/main/java/com/uber/profiling/profilers/ProcessInfoProfiler.java index 12d4a16..ac81ddf 100644 --- a/src/main/java/com/uber/profiling/profilers/ProcessInfoProfiler.java +++ b/src/main/java/com/uber/profiling/profilers/ProcessInfoProfiler.java @@ -17,7 +17,6 @@ package com.uber.profiling.profilers; import com.uber.profiling.AgentImpl; -import com.uber.profiling.Profiler; import com.uber.profiling.Reporter; import com.uber.profiling.util.AgentLogger; import com.uber.profiling.util.ProcFileUtils; @@ -30,7 +29,7 @@ import java.util.List; import java.util.Map; -public class ProcessInfoProfiler extends ProcessInfoBase implements Profiler { +public class ProcessInfoProfiler extends ProcessInfoBase { public final static String PROFILER_NAME = "ProcessInfo"; private static final AgentLogger logger = AgentLogger.getLogger(ProcessInfoProfiler.class.getName()); @@ -50,7 +49,11 @@ public ProcessInfoProfiler(Reporter reporter) { @Override public long getIntervalMillis() { - return 0; + return -1; + } + + @Override + public void setIntervalMillis(long millis) { } @Override diff --git a/src/main/java/com/uber/profiling/profilers/StacktraceCollectorProfiler.java b/src/main/java/com/uber/profiling/profilers/StacktraceCollectorProfiler.java index 09ede1d..547b433 100644 --- a/src/main/java/com/uber/profiling/profilers/StacktraceCollectorProfiler.java +++ b/src/main/java/com/uber/profiling/profilers/StacktraceCollectorProfiler.java @@ -31,7 +31,8 @@ /** * This class collects stacktraces by getting thread dump via JMX, and stores the stacktraces into the given buffer. */ -public class StacktraceCollectorProfiler implements Profiler { +public class StacktraceCollectorProfiler extends Profiler { + public static final String PROFILER_NAME = "StacktraceCollector"; private long intervalMillis; private StacktraceMetricBuffer buffer; private String ignoreThreadNamePrefix = ""; @@ -63,6 +64,9 @@ public void setReporter(Reporter reporter) { @Override public void profile() { + if (getIntervalMillis() <=0){ + return; + } ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false); if (threadInfos == null) { return; diff --git a/src/main/java/com/uber/profiling/profilers/StacktraceReporterProfiler.java b/src/main/java/com/uber/profiling/profilers/StacktraceReporterProfiler.java index 744e8b0..31ccd70 100644 --- a/src/main/java/com/uber/profiling/profilers/StacktraceReporterProfiler.java +++ b/src/main/java/com/uber/profiling/profilers/StacktraceReporterProfiler.java @@ -16,7 +16,6 @@ package com.uber.profiling.profilers; -import com.uber.profiling.Profiler; import com.uber.profiling.Reporter; import com.uber.profiling.reporters.ConsoleOutputReporter; import com.uber.profiling.util.ClassAndMethod; @@ -32,7 +31,7 @@ /** * This class reads the stacktraces from the given buffer and send out via given reporter. */ -public class StacktraceReporterProfiler extends ProcessInfoBase implements Profiler { +public class StacktraceReporterProfiler extends ProcessInfoBase { public static final String PROFILER_NAME = "Stacktrace"; private StacktraceMetricBuffer buffer; @@ -41,6 +40,10 @@ public class StacktraceReporterProfiler extends ProcessInfoBase implements Profi private long intervalMillis = Constants.DEFAULT_METRIC_INTERVAL; + public StacktraceMetricBuffer getBuffer() { + return buffer; + } + public StacktraceReporterProfiler(StacktraceMetricBuffer buffer, Reporter reporter) { this.buffer = buffer; this.reporter = reporter; diff --git a/src/main/java/com/uber/profiling/reporters/ConsoleOutputReporter.java b/src/main/java/com/uber/profiling/reporters/ConsoleOutputReporter.java index 37b7c11..306ad56 100644 --- a/src/main/java/com/uber/profiling/reporters/ConsoleOutputReporter.java +++ b/src/main/java/com/uber/profiling/reporters/ConsoleOutputReporter.java @@ -18,8 +18,6 @@ import com.uber.profiling.Reporter; import com.uber.profiling.util.JsonUtils; - -import java.util.List; import java.util.Map; public class ConsoleOutputReporter implements Reporter { diff --git a/src/main/java/com/uber/profiling/util/StringUtils.java b/src/main/java/com/uber/profiling/util/StringUtils.java index 1d96a4c..defda12 100644 --- a/src/main/java/com/uber/profiling/util/StringUtils.java +++ b/src/main/java/com/uber/profiling/util/StringUtils.java @@ -17,11 +17,8 @@ package com.uber.profiling.util; import org.apache.commons.lang3.math.NumberUtils; - import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/src/test/java/com/uber/profiling/ProfilerRunnableTest.java b/src/test/java/com/uber/profiling/ProfilerRunnableTest.java index 8f81dd9..d4a6e1e 100644 --- a/src/test/java/com/uber/profiling/ProfilerRunnableTest.java +++ b/src/test/java/com/uber/profiling/ProfilerRunnableTest.java @@ -32,6 +32,10 @@ public long getIntervalMillis() { return 0; } + @Override + public void setIntervalMillis(long millis) { + } + @Override public void setReporter(Reporter reporter) { } diff --git a/src/test/java/com/uber/profiling/profilers/ProcessInfoProfilerTest.java b/src/test/java/com/uber/profiling/profilers/ProcessInfoProfilerTest.java index 3494376..da08bb1 100644 --- a/src/test/java/com/uber/profiling/profilers/ProcessInfoProfilerTest.java +++ b/src/test/java/com/uber/profiling/profilers/ProcessInfoProfilerTest.java @@ -44,7 +44,7 @@ public void close() { } }); - Assert.assertEquals(0L, profiler.getIntervalMillis()); + Assert.assertEquals(-1L, profiler.getIntervalMillis()); profiler.profile(); profiler.profile();