package org.radargun.stages.monitor; import java.lang.management.ManagementFactory; import java.util.Collection; import javax.management.MBeanServer; import javax.management.ObjectName; import org.radargun.DistStageAck; import org.radargun.config.Property; import org.radargun.config.Stage; import org.radargun.stages.AbstractDistStage; /** * Stage for invoking operations on JProfiler. Remember to set up JVM args: "-agentpath:/path/to/libjprofilerti.so=offline,id=100,config=/path/to/configuration.xml" * * @author Radim Vansa <rvansa@redhat.com> */ @Stage(doc = "Stage for invoking operations on JProfiler.\nRemember to set up JVM args: " + "\"-agentpath:/path/to/libjprofilerti.so=offline,id=100,config=/path/to/configuration.xml\"") public class JProfilerStage extends AbstractDistStage { public static final String JPROFILER6_CONTROLLER_OBJECT_NAME = "com.jprofiler.api.agent.mbean:type=Controller"; public static final String JPROFILER7_CONTROLLER_OBJECT_NAME = "com.jprofiler.api.agent.mbean:type=RemoteController"; private ObjectName objectName; public enum Operation { NO_OPERATION(null, null), START_METHOD_STATS_RECORDING("startMethodStatsRecording", new String[] {}), STOP_METHOD_STATS_RECORDING("stopMethodStatsRecording", new String[] {}), START_CPU_RECORDING("startCPURecording", new String[] {boolean.class.getName()}), STOP_CPU_RECORDING("stopCPURecording", new String[] {}), SAVE_SNAPSHOT("saveSnapshot", new String[] {String.class.getName()}), START_MEMORY_RECORDING("startAllocRecording", new String[] {boolean.class.getName()}), STOP_MEMORY_RECORDING("stopAllocRecording", new String[] {}), START_MONITOR_RECORDING("startMonitorRecording", new String[] {}), STOP_MONITOR_RECORDING("stopMonitorRecording", new String[] {}), START_THREAD_RECORDING("startThreadProfiling", new String[] {}), STOP_THREAD_RECORDING("stopThreadProfiling", new String[] {}), START_VM_TELEMETRY_RECORDING("startVMTelemetryRecording", new String[] {}), STOP_VM_TELEMETRY_RECORDING("stopVMTelemetryRecording", new String[] {}); private String name; private String[] signature; private Operation(String name, String[] signature) { this.name = name; this.signature = signature; } public String getName() { return name; } public String[] getSignature() { return signature; } } @Property(optional = false, doc = "Operations that should be invoked on the Controller") protected Collection<Operation> operations; @Property(doc = "Directory where the snapshot should be written (for SAVE_SNAPSHOT).") protected String snapshotDirectory; @Property(doc = "If true, any previously accumulated CPU profiling data will be discarded. If false, CPU data will" + "be accumulated across pairs of invocations of START_CPU_RECORDING and STOP_CPU_RECORDING. Default is false.") protected boolean resetCPUStats; @Property(doc = "If true, any previously accumulated Memory profiling data will be discarded. If false, CPU data will" + "be accumulated across pairs of invocations of START_MEMORY_RECORDING and STOP_MEMORY_RECORDING. Default is false.") protected boolean resetMemoryStats; @Override public DistStageAck executeOnSlave() { if (operations == null || operations.isEmpty()) { log.warn("No operation specified"); return successfulResponse(); } for (Operation operation : operations) { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); try { objectName = new ObjectName(JPROFILER7_CONTROLLER_OBJECT_NAME); if (!mbs.isRegistered(objectName)) { objectName = new ObjectName(JPROFILER6_CONTROLLER_OBJECT_NAME); if (!mbs.isRegistered(objectName)) { log.info("JProfiler not enabled on this node."); return successfulResponse(); } } mbs.invoke(objectName, operation.getName(), getParams(operation), operation.getSignature()); } catch (Exception e) { return errorResponse("Failed to execute JMX operations", e); } } return successfulResponse(); } private Object[] getParams(Operation operation) { switch (operation) { case NO_OPERATION: return null; case STOP_METHOD_STATS_RECORDING: case START_METHOD_STATS_RECORDING: case STOP_CPU_RECORDING: case STOP_MEMORY_RECORDING: return new Object[0]; case SAVE_SNAPSHOT: if (snapshotDirectory == null) throw new NullPointerException("snapshotOutput not set"); return new Object[] {String.format("%s%s-node%d-profiler.jps", snapshotDirectory, slaveState.getConfigName(), slaveState.getSlaveIndex())}; case START_CPU_RECORDING: return new Object[] {resetCPUStats}; case START_MEMORY_RECORDING: return new Object[] {resetMemoryStats}; default: throw new UnsupportedOperationException(); } } }