Remove product literal strings in "pht()", part 6
[phabricator.git] / src / applications / console / plugin / xhprof / DarkConsoleXHProfPluginAPI.php
blob747ddd2267e339e020c2c773a03d5b5a6937b2c1
1 <?php
3 /**
4 * @phutil-external-symbol function xhprof_enable
5 * @phutil-external-symbol function xhprof_disable
6 */
7 final class DarkConsoleXHProfPluginAPI extends Phobject {
9 private static $profilerStarted;
10 private static $profilerRunning;
11 private static $profileFilePHID;
13 public static function isProfilerAvailable() {
14 return extension_loaded('xhprof');
17 public static function getProfilerHeader() {
18 return 'X-Phabricator-Profiler';
21 public static function isProfilerRequested() {
22 if (!empty($_REQUEST['__profile__'])) {
23 return $_REQUEST['__profile__'];
26 $header = AphrontRequest::getHTTPHeader(self::getProfilerHeader());
27 if ($header) {
28 return $header;
31 return false;
34 private static function shouldStartProfiler() {
35 if (self::isProfilerRequested()) {
36 return true;
39 static $sample_request = null;
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;
52 return $sample_request;
55 public static function isProfilerStarted() {
56 return self::$profilerStarted;
59 private static function isProfilerRunning() {
60 return self::$profilerRunning;
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);
72 require_once $root.'/externals/xhprof/xhprof_lib.php';
76 public static function saveProfilerSample(PhutilDeferredLog $access_log) {
77 $file_phid = self::getProfileFilePHID();
78 if (!$file_phid) {
79 return;
82 if (self::isProfilerRequested()) {
83 $sample_rate = 0;
84 } else {
85 $sample_rate = PhabricatorEnv::getEnvConfig('debug.profile-rate');
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'));
97 AphrontWriteGuard::allowDangerousUnguardedWrites(true);
98 $caught = null;
99 try {
100 $profile_sample->save();
101 } catch (Exception $ex) {
102 $caught = $ex;
104 AphrontWriteGuard::allowDangerousUnguardedWrites(false);
106 if ($caught) {
107 throw $caught;
111 public static function hookProfiler() {
112 if (!self::shouldStartProfiler()) {
113 return;
116 if (!self::isProfilerAvailable()) {
117 return;
120 if (self::$profilerStarted) {
121 return;
124 self::startProfiler();
129 * @phutil-external-symbol class PhabricatorStartup
131 private static function startProfiler() {
132 PhabricatorStartup::beginStartupPhase('profiler.init');
134 self::includeXHProfLib();
135 xhprof_enable();
137 self::$profilerStarted = true;
138 self::$profilerRunning = true;
143 * @phutil-external-symbol class PhabricatorStartup
145 public static function getProfileFilePHID() {
146 if (!self::isProfilerRunning()) {
147 return;
150 PhabricatorStartup::beginStartupPhase('profiler.stop');
151 self::stopProfiler();
152 PhabricatorStartup::beginStartupPhase('profiler.done');
154 return self::$profileFilePHID;
157 private static function stopProfiler() {
159 $data = xhprof_disable();
160 $data = @json_encode($data);
161 self::$profilerRunning = false;
163 // Since these happen on GET we can't do guarded writes. These also
164 // sometimes happen after we've disposed of the write guard; in this
165 // case we need to disable the whole mechanism.
167 $use_scope = AphrontWriteGuard::isGuardActive();
168 if ($use_scope) {
169 $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
170 } else {
171 AphrontWriteGuard::allowDangerousUnguardedWrites(true);
174 $caught = null;
175 try {
176 $file = call_user_func(
177 array('PhabricatorFile', 'newFromFileData'),
178 $data,
179 array(
180 'mime-type' => 'application/xhprof',
181 'name' => 'profile.xhprof',
183 } catch (Exception $ex) {
184 $caught = $ex;
187 if ($use_scope) {
188 unset($unguarded);
189 } else {
190 AphrontWriteGuard::allowDangerousUnguardedWrites(false);
193 if ($caught) {
194 throw $caught;
197 self::$profileFilePHID = $file->getPHID();