package jetbrains.buildServer.profile; import com.yourkit.api.Controller; import com.yourkit.api.ProfilingModes; import jetbrains.buildServer.log.Loggers; /** * Allows to profile TeamCity server. */ public class Profiler { private Controller myController; private final Object myProfLock = new Object(); private Mode myMode = Mode.DISABLED; public static enum Mode { DISABLED, ENABLED, CPU_PROF_STARTED, CAPTURING, MEMORY_CAPTURE_IN_PROGRESS } public Profiler() { } public void init() { try { /* Tries to create controller. If controller cannot be created no profiler actions will be available. */ myMode = Mode.ENABLED; } catch (Exception e) { Loggers.SERVER.warn(e); } } public boolean isAvailable() { return myMode != Mode.DISABLED; } public boolean canStartCPUProfiling() { return myMode == Mode.ENABLED; } public boolean canCaptureSnapshot() { return myMode == Mode.CPU_PROF_STARTED; } public void startProfiler() throws Exception { synchronized (myProfLock) { if (myMode == Mode.CPU_PROF_STARTED) throw new Exception("Profiler is locked (current mode is " + myMode.name() + ")."); if (myController != null) throw new Exception("Profiler is locked (another profiling session is running)."); myController = new Controller(); Loggers.SERVER.info("profiler starting: stopping current profiling session... mode = " + myMode); myController.stopCPUProfiling(); Loggers.SERVER.info("profiler starting: stopped"); Loggers.SERVER.info("profiler starting: starting current profiling session..."); myController.startCPUProfiling(ProfilingModes.CPU_SAMPLING, "Agent"); Loggers.SERVER.info("profiler starting: started"); } myMode = Mode.CPU_PROF_STARTED; } public String captureMemorySnapshot() throws Exception { synchronized (myProfLock) { if (myMode != Mode.ENABLED) throw new Exception("Profiler is locked (current mode is " + myMode.name() + ")."); if (myController != null) throw new Exception("Profiler is locked (another profiling session is running)."); String result; try { myController = new Controller(); Loggers.SERVER.info("profiler: starting memory snapshot dump..."); myMode = Mode.MEMORY_CAPTURE_IN_PROGRESS; result = myController.captureMemorySnapshot(); Loggers.SERVER.info("profiler: memory snapshot done: " + result); } finally { resetState(); } return result; } } public String captureAndStop() throws Exception { String result = null; synchronized (myProfLock) { if (myController == null) throw new Exception("Profiler is locked (another profiling session is running)."); myMode = Mode.CAPTURING; try { Loggers.SERVER.info("profiler capturing: capturing..."); result = myController.captureSnapshot(ProfilingModes.SNAPSHOT_WITHOUT_HEAP); Loggers.SERVER.info("profiler capturing: Snapshot saved to " + result); } finally { myMode = Mode.CPU_PROF_STARTED; try { Loggers.SERVER.info("profiler capturing: stopping current profiling session... mode = " + myMode); myController.stopCPUProfiling(); Loggers.SERVER.info("profiler capturing: stopped"); } finally { resetState(); } } } return result; } public void stopProfiler() throws Exception { try { Loggers.SERVER.info("profiler stopping: stopping current profiling session... mode = " + myMode); myController.stopCPUProfiling(); Loggers.SERVER.info("profiler stopping: stopped"); } finally { resetState(); } } private void resetState() { myController = null; myMode = Mode.ENABLED; } public Mode getMode() { return myMode; } }