mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-22 14:52:41 +01:00
Move XHProf sampling code out of index.php
Summary: - Separate the ideas of "requested" (explicit user request) vs "started" (user request or sampling). - Move this code out of index.php into the XHProf stuff (general effort to make index.php smaller). Test Plan: Verified that profiling still works, and profiling extends to ajax requests. Set sampling rate to 2, saw 50% samples. Looked at database, saw sampling data populating properly. Reviewers: vrana, nh Reviewed By: vrana CC: aran Differential Revision: https://secure.phabricator.com/D4891
This commit is contained in:
parent
b72e7969a1
commit
0f8984f5a7
4 changed files with 94 additions and 69 deletions
|
@ -97,8 +97,7 @@ final class DarkConsoleXHProfPlugin extends DarkConsolePlugin {
|
||||||
|
|
||||||
|
|
||||||
public function willShutdown() {
|
public function willShutdown() {
|
||||||
if (DarkConsoleXHProfPluginAPI::isProfilerRequested() &&
|
if (DarkConsoleXHProfPluginAPI::isProfilerStarted()) {
|
||||||
(DarkConsoleXHProfPluginAPI::isProfilerRequested() !== 'all')) {
|
|
||||||
$this->xhprofID = DarkConsoleXHProfPluginAPI::stopProfiler();
|
$this->xhprofID = DarkConsoleXHProfPluginAPI::stopProfiler();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,20 +27,32 @@ final class DarkConsoleXHProfPluginAPI {
|
||||||
return $header;
|
return $header;
|
||||||
}
|
}
|
||||||
|
|
||||||
static $profilerRequested = null;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!isset($profilerRequested)) {
|
public static function shouldStartProfiler() {
|
||||||
|
if (self::isProfilerRequested()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static $sample_request = null;
|
||||||
|
|
||||||
|
if ($sample_request === null) {
|
||||||
if (PhabricatorEnv::getEnvConfig('debug.profile-rate')) {
|
if (PhabricatorEnv::getEnvConfig('debug.profile-rate')) {
|
||||||
$rate = PhabricatorEnv::getEnvConfig('debug.profile-rate');
|
$rate = PhabricatorEnv::getEnvConfig('debug.profile-rate');
|
||||||
if (mt_rand(1, $rate) == 1) {
|
if (mt_rand(1, $rate) == 1) {
|
||||||
$profilerRequested = true;
|
$sample_request = true;
|
||||||
} else {
|
} else {
|
||||||
$profilerRequested = false;
|
$sample_request = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $profilerRequested;
|
return $sample_request;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function isProfilerStarted() {
|
||||||
|
return self::$profilerStarted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function includeXHProfLib() {
|
public static function includeXHProfLib() {
|
||||||
|
@ -56,8 +68,40 @@ final class DarkConsoleXHProfPluginAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static function saveProfilerSample(
|
||||||
|
AphrontRequest $request,
|
||||||
|
$access_log) {
|
||||||
|
|
||||||
|
if (!self::isProfilerStarted()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$profile = DarkConsoleXHProfPluginAPI::stopProfiler();
|
||||||
|
$profile_sample = id(new PhabricatorXHProfSample())
|
||||||
|
->setFilePHID($profile);
|
||||||
|
|
||||||
|
if (self::isProfilerRequested()) {
|
||||||
|
$sample_rate = 0;
|
||||||
|
} else {
|
||||||
|
$sample_rate = PhabricatorEnv::getEnvConfig('debug.profile-rate');
|
||||||
|
}
|
||||||
|
|
||||||
|
$profile_sample->setSampleRate($sample_rate);
|
||||||
|
|
||||||
|
if ($access_log) {
|
||||||
|
$profile_sample
|
||||||
|
->setUsTotal($access_log->getData('T'))
|
||||||
|
->setHostname($access_log->getData('h'))
|
||||||
|
->setRequestPath($access_log->getData('U'))
|
||||||
|
->setController($access_log->getData('C'))
|
||||||
|
->setUserPHID($request->getUser()->getPHID());
|
||||||
|
}
|
||||||
|
|
||||||
|
$profile_sample->save();
|
||||||
|
}
|
||||||
|
|
||||||
public static function hookProfiler() {
|
public static function hookProfiler() {
|
||||||
if (!self::isProfilerRequested()) {
|
if (!self::shouldStartProfiler()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,49 +123,49 @@ final class DarkConsoleXHProfPluginAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function stopProfiler() {
|
public static function stopProfiler() {
|
||||||
if (self::$profilerStarted) {
|
if (!self::isProfilerStarted()) {
|
||||||
$data = xhprof_disable();
|
|
||||||
$data = serialize($data);
|
|
||||||
$file_class = 'PhabricatorFile';
|
|
||||||
|
|
||||||
// Since these happen on GET we can't do guarded writes. These also
|
|
||||||
// sometimes happen after we've disposed of the write guard; in this
|
|
||||||
// case we need to disable the whole mechanism.
|
|
||||||
|
|
||||||
$use_scope = AphrontWriteGuard::isGuardActive();
|
|
||||||
if ($use_scope) {
|
|
||||||
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
|
||||||
} else {
|
|
||||||
AphrontWriteGuard::allowDangerousUnguardedWrites(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
$caught = null;
|
|
||||||
try {
|
|
||||||
$file = call_user_func(
|
|
||||||
array($file_class, 'newFromFileData'),
|
|
||||||
$data,
|
|
||||||
array(
|
|
||||||
'mime-type' => 'application/xhprof',
|
|
||||||
'name' => 'profile.xhprof',
|
|
||||||
));
|
|
||||||
} catch (Exception $ex) {
|
|
||||||
$caught = $ex;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($use_scope) {
|
|
||||||
unset($unguarded);
|
|
||||||
} else {
|
|
||||||
AphrontWriteGuard::allowDangerousUnguardedWrites(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($caught) {
|
|
||||||
throw $caught;
|
|
||||||
} else {
|
|
||||||
return $file->getPHID();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$data = xhprof_disable();
|
||||||
|
$data = serialize($data);
|
||||||
|
$file_class = 'PhabricatorFile';
|
||||||
|
|
||||||
|
// Since these happen on GET we can't do guarded writes. These also
|
||||||
|
// sometimes happen after we've disposed of the write guard; in this
|
||||||
|
// case we need to disable the whole mechanism.
|
||||||
|
|
||||||
|
$use_scope = AphrontWriteGuard::isGuardActive();
|
||||||
|
if ($use_scope) {
|
||||||
|
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
||||||
|
} else {
|
||||||
|
AphrontWriteGuard::allowDangerousUnguardedWrites(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$caught = null;
|
||||||
|
try {
|
||||||
|
$file = call_user_func(
|
||||||
|
array($file_class, 'newFromFileData'),
|
||||||
|
$data,
|
||||||
|
array(
|
||||||
|
'mime-type' => 'application/xhprof',
|
||||||
|
'name' => 'profile.xhprof',
|
||||||
|
));
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
$caught = $ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($use_scope) {
|
||||||
|
unset($unguarded);
|
||||||
|
} else {
|
||||||
|
AphrontWriteGuard::allowDangerousUnguardedWrites(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($caught) {
|
||||||
|
throw $caught;
|
||||||
|
} else {
|
||||||
|
return $file->getPHID();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,7 +163,7 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView {
|
||||||
require_celerity_resource('aphront-dark-console-css');
|
require_celerity_resource('aphront-dark-console-css');
|
||||||
|
|
||||||
$headers = array();
|
$headers = array();
|
||||||
if (DarkConsoleXHProfPluginAPI::isProfilerRequested()) {
|
if (DarkConsoleXHProfPluginAPI::isProfilerStarted()) {
|
||||||
$headers[DarkConsoleXHProfPluginAPI::getProfilerHeader()] = 'page';
|
$headers[DarkConsoleXHProfPluginAPI::getProfilerHeader()] = 'page';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,25 +132,7 @@ try {
|
||||||
$access_log->write();
|
$access_log->write();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DarkConsoleXHProfPluginAPI::isProfilerRequested()) {
|
DarkConsoleXHProfPluginAPI::saveProfilerSample($request, $access_log);
|
||||||
$profile = DarkConsoleXHProfPluginAPI::stopProfiler();
|
|
||||||
$profile_sample = id(new PhabricatorXHProfSample())
|
|
||||||
->setFilePHID($profile);
|
|
||||||
if (empty($_REQUEST['__profile__'])) {
|
|
||||||
$sample_rate = PhabricatorEnv::getEnvConfig('debug.profile-rate');
|
|
||||||
} else {
|
|
||||||
$sample_rate = 0;
|
|
||||||
}
|
|
||||||
$profile_sample->setSampleRate($sample_rate);
|
|
||||||
if ($access_log) {
|
|
||||||
$profile_sample->setUsTotal($access_log->getData('T'))
|
|
||||||
->setHostname($access_log->getData('h'))
|
|
||||||
->setRequestPath($access_log->getData('U'))
|
|
||||||
->setController($access_log->getData('C'))
|
|
||||||
->setUserPHID($request->getUser()->getPHID());
|
|
||||||
}
|
|
||||||
$profile_sample->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception $ex) {
|
} catch (Exception $ex) {
|
||||||
PhabricatorStartup::didFatal("[Exception] ".$ex->getMessage());
|
PhabricatorStartup::didFatal("[Exception] ".$ex->getMessage());
|
||||||
|
|
Loading…
Reference in a new issue