package jetbrains.buildServer.profile; import com.yourkit.api.Controller; import jetbrains.buildServer.log.Loggers; /** * Allows to profile TeamCity server. */ @SuppressWarnings("WeakerAccess") public class Profiler { private Controller myController; private final Object myProfLock = new Object(); private Mode myMode = Mode.ENABLED; public enum Mode { ENABLED, CPU_PROF_STARTED, CAPTURING, MEMORY_CAPTURE_IN_PROGRESS } public Profiler() { } public void startProfiler() throws Exception { synchronized (myProfLock) { if (myMode != Mode.ENABLED) throw new Exception("Profiling is running (" + 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"); try { Loggers.SERVER.info("profiler starting: starting current profiling session..."); myController.startCPUSampling(null);; Loggers.SERVER.info("profiler starting: started"); } catch (Exception e) { resetState(); throw e; } 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; synchronized (myProfLock) { if (myMode != Mode.CPU_PROF_STARTED) throw new Exception("CPU profiling is not running (" + myMode.name() + ")."); if (myController == null) throw new Exception("No profiling session is running."); myMode = Mode.CAPTURING; try { Loggers.SERVER.info("profiler capturing: capturing..."); result = myController.captureSnapshot(Controller.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 { synchronized (myProfLock) { 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; } }