1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-23 22:10:55 +01:00

Emit cache setup issues from cache specs

Summary:
Ref T5501. Currently, we emit some bad warnings about, e.g., "apc.stat" on PHP 5.5+ systems with OPcache, where the warnings are not relevant.

Generate and raise warnings out of the CacheSpec pipeline so we only run relevant code.

Test Plan: Faked various warnings and saw them render correctly.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T5501

Differential Revision: https://secure.phabricator.com/D12318
This commit is contained in:
epriestley 2015-04-08 11:31:01 -07:00
parent bc08901afa
commit ffe9c26b00
9 changed files with 237 additions and 216 deletions

View file

@ -1262,7 +1262,6 @@ phutil_register_library_map(array(
'PeopleCreateUsersCapability' => 'applications/people/capability/PeopleCreateUsersCapability.php',
'PeopleUserLogGarbageCollector' => 'applications/people/garbagecollector/PeopleUserLogGarbageCollector.php',
'Phabricator404Controller' => 'applications/base/controller/Phabricator404Controller.php',
'PhabricatorAPCSetupCheck' => 'applications/config/check/PhabricatorAPCSetupCheck.php',
'PhabricatorAWSConfigOptions' => 'applications/config/option/PhabricatorAWSConfigOptions.php',
'PhabricatorAccessControlTestCase' => 'applications/base/controller/__tests__/PhabricatorAccessControlTestCase.php',
'PhabricatorAccessLog' => 'infrastructure/log/PhabricatorAccessLog.php',
@ -1474,6 +1473,7 @@ phutil_register_library_map(array(
'PhabricatorCacheManagementWorkflow' => 'applications/cache/management/PhabricatorCacheManagementWorkflow.php',
'PhabricatorCacheMarkupGarbageCollector' => 'applications/cache/garbagecollector/PhabricatorCacheMarkupGarbageCollector.php',
'PhabricatorCacheSchemaSpec' => 'applications/cache/storage/PhabricatorCacheSchemaSpec.php',
'PhabricatorCacheSetupCheck' => 'applications/config/check/PhabricatorCacheSetupCheck.php',
'PhabricatorCacheSpec' => 'applications/cache/spec/PhabricatorCacheSpec.php',
'PhabricatorCacheTTLGarbageCollector' => 'applications/cache/garbagecollector/PhabricatorCacheTTLGarbageCollector.php',
'PhabricatorCaches' => 'applications/cache/PhabricatorCaches.php',
@ -4544,7 +4544,6 @@ phutil_register_library_map(array(
'PeopleCreateUsersCapability' => 'PhabricatorPolicyCapability',
'PeopleUserLogGarbageCollector' => 'PhabricatorGarbageCollector',
'Phabricator404Controller' => 'PhabricatorController',
'PhabricatorAPCSetupCheck' => 'PhabricatorSetupCheck',
'PhabricatorAWSConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorAccessControlTestCase' => 'PhabricatorTestCase',
'PhabricatorAccessLogConfigOptions' => 'PhabricatorApplicationConfigOptions',
@ -4768,6 +4767,7 @@ phutil_register_library_map(array(
'PhabricatorCacheManagementWorkflow' => 'PhabricatorManagementWorkflow',
'PhabricatorCacheMarkupGarbageCollector' => 'PhabricatorGarbageCollector',
'PhabricatorCacheSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'PhabricatorCacheSetupCheck' => 'PhabricatorSetupCheck',
'PhabricatorCacheSpec' => 'Phobject',
'PhabricatorCacheTTLGarbageCollector' => 'PhabricatorGarbageCollector',
'PhabricatorCalendarApplication' => 'PhabricatorApplication',

View file

@ -38,14 +38,10 @@ abstract class PhabricatorCacheSpec extends Phobject {
return $this->version;
}
protected function newIssue($title, $body, $option = null) {
$issue = array(
'title' => $title,
'body' => $body,
'option' => $option,
);
$this->issues[] = $issue;
protected function newIssue($key) {
$issue = id(new PhabricatorSetupIssue())
->setIssueKey($key);
$this->issues[$key] = $issue;
return $issue;
}
@ -81,6 +77,35 @@ abstract class PhabricatorCacheSpec extends Phobject {
return $this->entryCount;
}
protected function raiseInstallAPCIssue() {
$message = pht(
"Installing the PHP extension 'APC' (Alternative PHP Cache) will ".
"dramatically improve performance. Note that APC versions 3.1.14 and ".
"3.1.15 are broken; 3.1.13 is recommended instead.");
return $this
->newIssue('extension.apc')
->setShortName(pht('APC'))
->setName(pht("PHP Extension 'APC' Not Installed"))
->setMessage($message)
->addPHPExtension('apc');
}
protected function raiseEnableAPCIssue() {
$summary = pht('Enabling APC/APCu will improve performance.');
$message = pht(
'The APC or APCu PHP extensions are installed, but not enabled in your '.
'PHP configuration. Enabling these extensions will improve Phabricator '.
'performance. Edit the "apc.enabled" setting to enable these '.
'extensions.');
return $this
->newIssue('extension.apc.enabled')
->setShortName(pht('APC/APCu Disabled'))
->setName(pht('APC/APCu Extensions Not Enabled'))
->setSummary($summary)
->setMessage($message)
->addPHPConfig('apc.enabled');
}
}

View file

@ -15,81 +15,70 @@ final class PhabricatorDataCacheSpec extends PhabricatorCacheSpec {
public static function getActiveCacheSpec() {
$spec = new PhabricatorDataCacheSpec();
// NOTE: If APCu is installed, it reports that APC is installed.
if (extension_loaded('apc') && !extension_loaded('apcu')) {
return self::getAPCSpec($spec);
$spec->initAPCSpec();
} else if (extension_loaded('apcu')) {
return self::getAPCuSpec($spec);
$spec->initAPCuSpec();
} else {
return self::getNoneSpec($spec);
$spec->initNoneSpec();
}
return $spec;
}
private static function getAPCSpec(PhabricatorDataCacheSpec $spec) {
$spec
private function initAPCSpec() {
$this
->setName(pht('APC User Cache'))
->setVersion(phpversion('apc'));
if (ini_get('apc.enabled')) {
$spec->setIsEnabled(true);
self::getAPCCommonSpec($spec);
$this->setIsEnabled(true);
$this->initAPCCommonSpec();
} else {
$spec->setIsEnabled(false);
$spec->newIssue(
pht('Enable APC'),
pht(
'The "APC" extension is currently disabled. Set "apc.enabled" to '.
'true to provide caching.'),
'apc.enabled');
$this->setIsEnabled(false);
$this->raiseEnableAPCIssue();
}
return $spec;
}
private static function getAPCuSpec(PhabricatorDataCacheSpec $spec) {
$spec
private function initAPCuSpec() {
$this
->setName(pht('APCu'))
->setVersion(phpversion('apcu'));
if (ini_get('apc.enabled')) {
$spec->setIsEnabled(true);
self::getAPCCommonSpec($spec);
$this->setIsEnabled(true);
$this->getAPCCommonSpec();
} else {
$spec->setIsEnabled(false);
$spec->newissue(
pht('Enable APCu'),
pht(
'The "APCu" extension is currently disabled. Set '.
'"apc.enabled" to true to provide caching.'),
'apc.enabled');
$this->setIsEnabled(false);
$this->raiseEnableAPCIssue();
}
return $spec;
}
private static function getNoneSpec(PhabricatorDataCacheSpec $spec) {
private function getNoneSpec() {
if (version_compare(phpversion(), '5.5', '>=')) {
$spec->newIssue(
pht('Install APCu'),
pht(
'Install the "APCu" PHP extension to provide data caching.'));
} else {
$spec->newIssue(
pht('Install APC'),
pht(
'Install the "APC" PHP extension to provide data caching.'));
}
$message = pht(
'Installing the "APCu" PHP extension will improve performance.');
return $spec;
$this
->newIssue('extension.apcu')
->setShortName(pht('APCu'))
->setName(pht('PHP Extension "APCu" Not Installed'))
->setMessage($message)
->addPHPExtension('apcu');
} else {
$this->raiseInstallAPCIssue();
}
}
private static function getAPCCommonSpec(PhabricatorDataCacheSpec $spec) {
private function getAPCCommonSpec() {
$mem = apc_sma_info();
$spec->setTotalMemory($mem['num_seg'] * $mem['seg_size']);
$this->setTotalMemory($mem['num_seg'] * $mem['seg_size']);
$info = apc_cache_info('user');
$spec->setUsedMemory($info['mem_size']);
$spec->setEntryCount(count($info['cache_list']));
$this->setUsedMemory($info['mem_size']);
$this->setEntryCount(count($info['cache_list']));
$cache = $info['cache_list'];
$state = array();
@ -107,7 +96,7 @@ final class PhabricatorDataCacheSpec extends PhabricatorCacheSpec {
$state[$key]['count']++;
}
$spec->setCacheSummary($state);
$this->setCacheSummary($state);
}
private static function getKeyPattern($key) {

View file

@ -4,49 +4,85 @@ final class PhabricatorOpcodeCacheSpec extends PhabricatorCacheSpec {
public static function getActiveCacheSpec() {
$spec = new PhabricatorOpcodeCacheSpec();
// NOTE: If APCu is installed, it reports that APC is installed.
if (extension_loaded('apc') && !extension_loaded('apcu')) {
return self::getAPCSpec($spec);
$spec->initAPCSpec();
} else if (extension_loaded('Zend OPcache')) {
return self::getOpcacheSpec($spec);
$spec->initOpcacheSpec();
} else {
return self::getNoneSpec($spec);
}
}
private static function getAPCSpec(PhabricatorOpcodeCacheSpec $spec) {
$spec
->setName(pht('APC'))
->setVersion(phpversion('apc'));
if (ini_get('apc.enabled')) {
$spec->setIsEnabled(true);
$mem = apc_sma_info();
$spec->setTotalMemory($mem['num_seg'] * $mem['seg_size']);
$info = apc_cache_info();
$spec->setUsedMemory($info['mem_size']);
} else {
$spec->setIsEnabled(false);
$spec->newIssue(
pht('Enable APC'),
pht(
'The "APC" extension is currently disabled. Set "apc.enabled" to '.
'true to improve performance.'),
'apc.enabled');
$spec->initNoneSpec();
}
return $spec;
}
private static function getOpcacheSpec(PhabricatorOpcodeCacheSpec $spec) {
$spec
private function initAPCSpec() {
$this
->setName(pht('APC'))
->setVersion(phpversion('apc'));
if (ini_get('apc.enabled')) {
$this->setIsEnabled(true);
$mem = apc_sma_info();
$this->setTotalMemory($mem['num_seg'] * $mem['seg_size']);
$info = apc_cache_info();
$this->setUsedMemory($info['mem_size']);
$is_dev = PhabricatorEnv::getEnvConfig('phabricator.developer-mode');
$is_stat_enabled = ini_get('apc.stat');
if ($is_stat_enabled && !$is_dev) {
$summary = pht(
'"apc.stat" is currently enabled, but should probably be disabled.');
$message = pht(
'The "apc.stat" setting is currently enabled in your PHP '.
'configuration. In production mode, "apc.stat" should be '.
'disabled. This will improve performance slightly.');
$this
->newIssue('extension.apc.stat-enabled')
->setShortName(pht('"apc.stat" Enabled'))
->setName(pht('"apc.stat" Enabled in Production'))
->setSummary($summary)
->setMessage($message)
->addPHPConfig('apc.stat')
->addPhabricatorConfig('phabricator.developer-mode');
} else if (!$is_stat_enabled && $is_dev) {
$summary = pht(
'"apc.stat" is currently disabled, but should probably be enabled.');
$message = pht(
'The "apc.stat" setting is currently disabled in your PHP '.
'configuration, but Phabricator is running in development mode. '.
'This option should normally be enabled in development so you do '.
'not need to restart your webserver after making changes to the '.
'code.');
$this
->newIssue('extension.apc.stat-disabled')
->setShortName(pht('"apc.stat" Disabled'))
->setName(pht('"apc.stat" Disabled in Development'))
->setSummary($summary)
->setMessage($message)
->addPHPConfig('apc.stat')
->addPhabricatorConfig('phabricator.developer-mode');
}
} else {
$this->setIsEnabled(false);
$this->raiseEnableAPCIssue();
}
}
private function initOpcacheSpec() {
$this
->setName(pht('Zend OPcache'))
->setVersion(phpversion('Zend OPcache'));
if (ini_get('opcache.enable')) {
$spec->setIsEnabled(true);
$this->setIsEnabled(true);
$status = opcache_get_status();
$memory = $status['memory_usage'];
@ -54,36 +90,86 @@ final class PhabricatorOpcodeCacheSpec extends PhabricatorCacheSpec {
$mem_used = $memory['used_memory'];
$mem_free = $memory['free_memory'];
$mem_junk = $memory['wasted_memory'];
$spec->setUsedMemory($mem_used + $mem_junk);
$spec->setTotalMemory($mem_used + $mem_junk + $mem_free);
$spec->setEntryCount($status['opcache_statistics']['num_cached_keys']);
} else {
$spec->setIsEnabled(false);
$spec->newissue(
pht('Enable Zend OPcache'),
pht(
'The "Zend OPcache" extension is currently disabled. Set '.
'"opcache.enable" to true to improve performance.'),
'opcache.enable');
}
$this->setUsedMemory($mem_used + $mem_junk);
$this->setTotalMemory($mem_used + $mem_junk + $mem_free);
$this->setEntryCount($status['opcache_statistics']['num_cached_keys']);
return $spec;
$is_dev = PhabricatorEnv::getEnvConfig('phabricator.developer-mode');
$validate = ini_get('opcache.validate_timestamps');
$freq = ini_get('opcache.revalidate_freq');
if ($is_dev && (!$validate || $freq)) {
$summary = pht(
'OPcache is not configured properly for development.');
$message = pht(
'In development, OPcache should be configured to always reload '.
'code so the webserver does not need to be restarted after making '.
'changes. To do this, enable "opcache.validate_timestamps" and '.
'set "opcache.revalidate_freq" to 0.');
$this
->newIssue('extension.opcache.devmode')
->setShortName(pht('OPcache Config'))
->setName(pht('OPCache Not Configured for Development'))
->setSummary($summary)
->setMessage($message)
->addPHPConfig('opcache.validate_timestamps')
->addPHPConfig('opcache.revalidate_freq')
->addPhabricatorConfig('phabricator.developer-mode');
} else if (!$is_dev && $validate) {
$summary = pht(
'OPcache is not configured ideally for production.');
$message = pht(
'In production, OPcache should be configured to never '.
'revalidate code. This will slightly improve performance. '.
'To do this, disable "opcache.validate_timestamps" in your PHP '.
'configuration.');
$this
->newIssue('extension.opcache.production')
->setShortName(pht('OPcache Config'))
->setName(pht('OPcache Not Configured for Production'))
->setSummary($summary)
->setMessage($message)
->addPHPConfig('opcache.validate_timestamps')
->addPhabricatorConfig('phabricator.developer-mode');
}
} else {
$this->setIsEnabled(false);
$summary = pht('Enabling OPcache will dramatically improve performance.');
$message = pht(
'The PHP "Zend OPcache" extension is installed, but not enabled in '.
'your PHP configuration. Enabling it will dramatically improve '.
'Phabricator performance. Edit the "opcache.enable" setting to '.
'enable the extension.');
$this->newIssue('extension.opcache.enable')
->setShortName(pht('OPcache Disabled'))
->setName(pht('Zend OPcache Not Enabled'))
->setSummary($summary)
->setMessage($message)
->addPHPConfig('opcache.enable');
}
}
private static function getNoneSpec(PhabricatorOpcodeCacheSpec $spec) {
private function initNoneSpec() {
if (version_compare(phpversion(), '5.5', '>=')) {
$spec->newIssue(
pht('Install OPcache'),
pht(
'Install the "Zend OPcache" PHP extension to improve performance.'));
} else {
$spec->newIssue(
pht('Install APC'),
pht(
'Install the "APC" PHP extension to improve performance.'));
}
$message = pht(
'Installing the "Zend OPcache" extension will dramatically improve '.
'performance.');
return $spec;
$this
->newIssue('extension.opcache')
->setShortName(pht('OPcache'))
->setName(pht('Zend OPcache Not Installed'))
->setMessage($message)
->addPHPExtension('Zend OPcache');
} else {
$this->raiseInstallAPCIssue();
}
}
}

View file

@ -1,89 +0,0 @@
<?php
final class PhabricatorAPCSetupCheck extends PhabricatorSetupCheck {
public function getDefaultGroup() {
return self::GROUP_OTHER;
}
protected function executeChecks() {
if (!extension_loaded('apc')) {
$message = pht(
"Installing the PHP extension 'APC' (Alternative PHP Cache) will ".
"dramatically improve performance. Note that APC versions 3.1.14 and ".
"3.1.15 are broken; 3.1.13 is recommended instead.");
$this
->newIssue('extension.apc')
->setShortName(pht('APC'))
->setName(pht("PHP Extension 'APC' Not Installed"))
->setMessage($message)
->addPHPExtension('apc');
return;
}
if (!ini_get('apc.enabled')) {
$summary = pht('Enabling APC will dramatically improve performance.');
$message = pht(
"The PHP extension 'APC' is installed, but not enabled in your PHP ".
"configuration. Enabling it will dramatically improve Phabricator ".
"performance. Edit the 'apc.enabled' setting to enable the extension.");
$this
->newIssue('extension.apc.enabled')
->setShortName(pht('APC Disabled'))
->setName(pht("PHP Extension 'APC' Not Enabled"))
->setSummary($summary)
->setMessage($message)
->addPHPConfig('apc.enabled');
return;
}
$is_dev = PhabricatorEnv::getEnvConfig('phabricator.developer-mode');
$is_apcu = extension_loaded('apcu');
$is_stat_enabled = ini_get('apc.stat');
$issue_key = null;
if ($is_stat_enabled && !$is_dev && !$is_apcu) {
$issue_key = 'extension.apc.stat-enabled';
$short = pht("'apc.stat' Enabled");
$long = pht("'apc.stat' Enabled in Production");
$summary = pht(
"'apc.stat' is currently enabled, but should probably be disabled.");
$message = pht(
"'apc.stat' is currently enabled in your PHP configuration. For most ".
"Phabricator installs, 'apc.stat' should be disabled. This will ".
"slightly improve performance (PHP will do fewer disk reads) and make ".
"updates safer (PHP won't read in the middle of a 'git pull').\n\n".
"(If you are developing for Phabricator, leave 'apc.stat' enabled but ".
"enable 'phabricator.developer-mode'.)");
} else if (!$is_stat_enabled && $is_dev && !$is_apcu) {
$issue_key = 'extension.apc.stat-disabled';
$short = pht("'apc.stat' Disabled");
$long = pht("'apc.stat' Disabled in Development");
$summary = pht(
"'apc.stat' is currently disabled, but should probably be enabled ".
"in development mode.");
$message = pht(
"'apc.stat' is disabled in your PHP configuration, but Phabricator is ".
"set to developer mode. Normally, you should enable 'apc.stat' for ".
"development installs so you don't need to restart your webserver ".
"after making changes to the code.\n\n".
"You can enable 'apc.stat', or disable 'phabricator.developer-mode', ".
"or safely ignore this warning if you have some reasoning behind ".
"your current configuration.");
}
if ($issue_key !== null) {
$this
->newIssue($issue_key)
->setShortName($short)
->setName($long)
->setSummary($summary)
->setMessage($message)
->addPHPConfig('apc.stat')
->addPhabricatorConfig('phabricator.developer-mode');
}
}
}

View file

@ -0,0 +1,20 @@
<?php
final class PhabricatorCacheSetupCheck extends PhabricatorSetupCheck {
public function getDefaultGroup() {
return self::GROUP_OTHER;
}
protected function executeChecks() {
$code_cache = PhabricatorOpcodeCacheSpec::getActiveCacheSpec();
$data_cache = PhabricatorDataCacheSpec::getActiveCacheSpec();
$issues = $code_cache->getIssues() + $data_cache->getIssues();
foreach ($issues as $issue) {
$this->addIssue($issue);
}
}
}

View file

@ -31,6 +31,11 @@ abstract class PhabricatorSetupCheck {
return $this->issues;
}
protected function addIssue(PhabricatorSetupIssue $issue) {
$this->issues[$issue->getIssueKey()] = $issue;
return $this;
}
public function getDefaultGroup() {
return null;
}

View file

@ -40,7 +40,6 @@ final class PhabricatorConfigCacheController
$this->renderCommonProperties($properties, $cache);
return id(new PHUIObjectBoxView())
->setFormErrors($this->renderIssues($cache->getIssues()))
->setHeaderText(pht('Opcode Cache'))
->addPropertyList($properties);
}
@ -146,20 +145,6 @@ final class PhabricatorConfigCacheController
}
private function renderIssues(array $issues) {
$result = array();
foreach ($issues as $issue) {
$title = $issue['title'];
$body = $issue['body'];
$result[] = array(
phutil_tag('strong', array(), $title.':'),
' ',
$body,
);
}
return $result;
}
private function renderYes($info) {
return array(
id(new PHUIIconView())->setIconFont('fa-check', 'green'),

View file

@ -209,7 +209,7 @@ final class PhabricatorCoreConfigOptions
->setLocked(true)
->setDescription(
pht('Custom HTML to show on the main Phabricator dashboard.')),
$this->newOption('phabricator.cache-namespace', 'string', null)
$this->newOption('phabricator.cache-namespace', 'string', 'phabricator')
->setLocked(true)
->setDescription(pht('Cache namespace.')),
$this->newOption('phabricator.allow-email-users', 'bool', false)