[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/console/plugin/xhprof/ -> DarkConsoleXHProfPluginAPI.php (source)

   1  <?php
   2  
   3  /**
   4   * @phutil-external-symbol function xhprof_enable
   5   * @phutil-external-symbol function xhprof_disable
   6   */
   7  final class DarkConsoleXHProfPluginAPI {
   8  
   9    private static $profilerStarted;
  10    private static $profilerRunning;
  11    private static $profileFilePHID;
  12  
  13    public static function isProfilerAvailable() {
  14      return extension_loaded('xhprof');
  15    }
  16  
  17    public static function getProfilerHeader() {
  18      return 'X-Phabricator-Profiler';
  19    }
  20  
  21    public static function isProfilerRequested() {
  22      if (!empty($_REQUEST['__profile__'])) {
  23        return $_REQUEST['__profile__'];
  24      }
  25  
  26      $header = AphrontRequest::getHTTPHeader(self::getProfilerHeader());
  27      if ($header) {
  28        return $header;
  29      }
  30  
  31      return false;
  32    }
  33  
  34    private static function shouldStartProfiler() {
  35      if (self::isProfilerRequested()) {
  36        return true;
  37      }
  38  
  39      static $sample_request = null;
  40  
  41      if ($sample_request === null) {
  42        if (PhabricatorEnv::getEnvConfig('debug.profile-rate')) {
  43          $rate = PhabricatorEnv::getEnvConfig('debug.profile-rate');
  44          if (mt_rand(1, $rate) == 1) {
  45            $sample_request = true;
  46          } else {
  47            $sample_request = false;
  48          }
  49        }
  50      }
  51  
  52      return $sample_request;
  53    }
  54  
  55    public static function isProfilerStarted() {
  56      return self::$profilerStarted;
  57    }
  58  
  59    private static function isProfilerRunning() {
  60      return self::$profilerRunning;
  61    }
  62  
  63    public static function includeXHProfLib() {
  64      // TODO: this is incredibly stupid, but we may not have Phutil metamodule
  65      // stuff loaded yet so we can't just phutil_get_library_root() our way
  66      // to victory.
  67      $root = __FILE__;
  68      for ($ii = 0; $ii < 6; $ii++) {
  69        $root = dirname($root);
  70      }
  71  
  72      require_once $root.'/externals/xhprof/xhprof_lib.php';
  73    }
  74  
  75  
  76    public static function saveProfilerSample(PhutilDeferredLog $access_log) {
  77      $file_phid = self::getProfileFilePHID();
  78      if (!$file_phid) {
  79        return;
  80      }
  81  
  82      if (self::isProfilerRequested()) {
  83        $sample_rate = 0;
  84      } else {
  85        $sample_rate = PhabricatorEnv::getEnvConfig('debug.profile-rate');
  86      }
  87  
  88      $profile_sample = id(new PhabricatorXHProfSample())
  89        ->setFilePHID($file_phid)
  90        ->setSampleRate($sample_rate)
  91        ->setUsTotal($access_log->getData('T'))
  92        ->setHostname($access_log->getData('h'))
  93        ->setRequestPath($access_log->getData('U'))
  94        ->setController($access_log->getData('C'))
  95        ->setUserPHID($access_log->getData('P'));
  96  
  97      AphrontWriteGuard::allowDangerousUnguardedWrites(true);
  98        $caught = null;
  99        try {
 100          $profile_sample->save();
 101        } catch (Exception $ex) {
 102          $caught = $ex;
 103        }
 104      AphrontWriteGuard::allowDangerousUnguardedWrites(false);
 105  
 106      if ($caught) {
 107        throw $caught;
 108      }
 109    }
 110  
 111    public static function hookProfiler() {
 112      if (!self::shouldStartProfiler()) {
 113        return;
 114      }
 115  
 116      if (!self::isProfilerAvailable()) {
 117        return;
 118      }
 119  
 120      if (self::$profilerStarted) {
 121        return;
 122      }
 123  
 124      self::startProfiler();
 125    }
 126  
 127    private static function startProfiler() {
 128      self::includeXHProfLib();
 129      xhprof_enable();
 130  
 131      self::$profilerStarted = true;
 132      self::$profilerRunning = true;
 133    }
 134  
 135    public static function getProfileFilePHID() {
 136      self::stopProfiler();
 137      return self::$profileFilePHID;
 138    }
 139  
 140    private static function stopProfiler() {
 141      if (!self::isProfilerRunning()) {
 142        return;
 143      }
 144  
 145      $data = xhprof_disable();
 146      $data = @json_encode($data);
 147      self::$profilerRunning = false;
 148  
 149      // Since these happen on GET we can't do guarded writes. These also
 150      // sometimes happen after we've disposed of the write guard; in this
 151      // case we need to disable the whole mechanism.
 152  
 153      $use_scope = AphrontWriteGuard::isGuardActive();
 154      if ($use_scope) {
 155        $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
 156      } else {
 157        AphrontWriteGuard::allowDangerousUnguardedWrites(true);
 158      }
 159  
 160      $caught = null;
 161      try {
 162        $file = call_user_func(
 163          array('PhabricatorFile', 'newFromFileData'),
 164          $data,
 165          array(
 166            'mime-type' => 'application/xhprof',
 167            'name'      => 'profile.xhprof',
 168          ));
 169      } catch (Exception $ex) {
 170        $caught = $ex;
 171      }
 172  
 173      if ($use_scope) {
 174        unset($unguarded);
 175      } else {
 176        AphrontWriteGuard::allowDangerousUnguardedWrites(false);
 177      }
 178  
 179      if ($caught) {
 180        throw $caught;
 181      }
 182  
 183      self::$profileFilePHID = $file->getPHID();
 184    }
 185  
 186  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1