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.ENABLED; private ProfilingSettings mySettings; public static enum Mode { DISABLED, ENABLED, CPU_PROF_STARTED, CAPTURING, MEMORY_CAPTURE_IN_PROGRESS } public Profiler() { mySettings = new ProfilingSettings(true); } 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.startCPUProfiling(getCPUProfilingMode(), "Agent"); Loggers.SERVER.info("profiler starting: started"); } catch (Exception e){ resetState(); throw e; } myMode = Mode.CPU_PROF_STARTED; } } private long getCPUProfilingMode() { long mode = ProfilingModes.CPU_SAMPLING; if (mySettings.isJ2eeCPUProfilingEnabled()){ mode = mode | ProfilingModes.CPU_J2EE; } return mode; } 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 (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(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 { 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; } public ProfilingSettings getSettings() { return mySettings; } }