Path: blob/master/src/applications/console/plugin/xhprof/DarkConsoleXHProfPluginAPI.php
13409 views
<?php12/**3* @phutil-external-symbol function xhprof_enable4* @phutil-external-symbol function xhprof_disable5*/6final class DarkConsoleXHProfPluginAPI extends Phobject {78private static $profilerStarted;9private static $profilerRunning;10private static $profileFilePHID;1112public static function isProfilerAvailable() {13return extension_loaded('xhprof');14}1516public static function getProfilerHeader() {17return 'X-Phabricator-Profiler';18}1920public static function isProfilerRequested() {21if (!empty($_REQUEST['__profile__'])) {22return $_REQUEST['__profile__'];23}2425$header = AphrontRequest::getHTTPHeader(self::getProfilerHeader());26if ($header) {27return $header;28}2930return false;31}3233private static function shouldStartProfiler() {34if (self::isProfilerRequested()) {35return true;36}3738static $sample_request = null;3940if ($sample_request === null) {41if (PhabricatorEnv::getEnvConfig('debug.profile-rate')) {42$rate = PhabricatorEnv::getEnvConfig('debug.profile-rate');43if (mt_rand(1, $rate) == 1) {44$sample_request = true;45} else {46$sample_request = false;47}48}49}5051return $sample_request;52}5354public static function isProfilerStarted() {55return self::$profilerStarted;56}5758private static function isProfilerRunning() {59return self::$profilerRunning;60}6162public static function includeXHProfLib() {63// TODO: this is incredibly stupid, but we may not have Phutil metamodule64// stuff loaded yet so we can't just phutil_get_library_root() our way65// to victory.66$root = __FILE__;67for ($ii = 0; $ii < 6; $ii++) {68$root = dirname($root);69}7071require_once $root.'/externals/xhprof/xhprof_lib.php';72}737475public static function saveProfilerSample(PhutilDeferredLog $access_log) {76$file_phid = self::getProfileFilePHID();77if (!$file_phid) {78return;79}8081if (self::isProfilerRequested()) {82$sample_rate = 0;83} else {84$sample_rate = PhabricatorEnv::getEnvConfig('debug.profile-rate');85}8687$profile_sample = id(new PhabricatorXHProfSample())88->setFilePHID($file_phid)89->setSampleRate($sample_rate)90->setUsTotal($access_log->getData('T'))91->setHostname($access_log->getData('h'))92->setRequestPath($access_log->getData('U'))93->setController($access_log->getData('C'))94->setUserPHID($access_log->getData('P'));9596AphrontWriteGuard::allowDangerousUnguardedWrites(true);97$caught = null;98try {99$profile_sample->save();100} catch (Exception $ex) {101$caught = $ex;102}103AphrontWriteGuard::allowDangerousUnguardedWrites(false);104105if ($caught) {106throw $caught;107}108}109110public static function hookProfiler() {111if (!self::shouldStartProfiler()) {112return;113}114115if (!self::isProfilerAvailable()) {116return;117}118119if (self::$profilerStarted) {120return;121}122123self::startProfiler();124}125126127/**128* @phutil-external-symbol class PhabricatorStartup129*/130private static function startProfiler() {131PhabricatorStartup::beginStartupPhase('profiler.init');132133self::includeXHProfLib();134xhprof_enable();135136self::$profilerStarted = true;137self::$profilerRunning = true;138}139140141/**142* @phutil-external-symbol class PhabricatorStartup143*/144public static function getProfileFilePHID() {145if (!self::isProfilerRunning()) {146return;147}148149PhabricatorStartup::beginStartupPhase('profiler.stop');150self::stopProfiler();151PhabricatorStartup::beginStartupPhase('profiler.done');152153return self::$profileFilePHID;154}155156private static function stopProfiler() {157158$data = xhprof_disable();159$data = @json_encode($data);160self::$profilerRunning = false;161162// Since these happen on GET we can't do guarded writes. These also163// sometimes happen after we've disposed of the write guard; in this164// case we need to disable the whole mechanism.165166$use_scope = AphrontWriteGuard::isGuardActive();167if ($use_scope) {168$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();169} else {170AphrontWriteGuard::allowDangerousUnguardedWrites(true);171}172173$caught = null;174try {175$file = call_user_func(176array('PhabricatorFile', 'newFromFileData'),177$data,178array(179'mime-type' => 'application/xhprof',180'name' => 'profile.xhprof',181));182} catch (Exception $ex) {183$caught = $ex;184}185186if ($use_scope) {187unset($unguarded);188} else {189AphrontWriteGuard::allowDangerousUnguardedWrites(false);190}191192if ($caught) {193throw $caught;194}195196self::$profileFilePHID = $file->getPHID();197}198199}200201202