diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 9632f1c275..09d57c2726 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -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', diff --git a/src/applications/cache/spec/PhabricatorCacheSpec.php b/src/applications/cache/spec/PhabricatorCacheSpec.php index 57ef0ebe74..31645ea97f 100644 --- a/src/applications/cache/spec/PhabricatorCacheSpec.php +++ b/src/applications/cache/spec/PhabricatorCacheSpec.php @@ -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'); + } } diff --git a/src/applications/cache/spec/PhabricatorDataCacheSpec.php b/src/applications/cache/spec/PhabricatorDataCacheSpec.php index 0d78f01ff5..89fbcd4775 100644 --- a/src/applications/cache/spec/PhabricatorDataCacheSpec.php +++ b/src/applications/cache/spec/PhabricatorDataCacheSpec.php @@ -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) { diff --git a/src/applications/cache/spec/PhabricatorOpcodeCacheSpec.php b/src/applications/cache/spec/PhabricatorOpcodeCacheSpec.php index f829f3640c..0c15e6e0e0 100644 --- a/src/applications/cache/spec/PhabricatorOpcodeCacheSpec.php +++ b/src/applications/cache/spec/PhabricatorOpcodeCacheSpec.php @@ -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(); + } } } diff --git a/src/applications/config/check/PhabricatorAPCSetupCheck.php b/src/applications/config/check/PhabricatorAPCSetupCheck.php deleted file mode 100644 index 942c797955..0000000000 --- a/src/applications/config/check/PhabricatorAPCSetupCheck.php +++ /dev/null @@ -1,89 +0,0 @@ -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'); - } - } - -} diff --git a/src/applications/config/check/PhabricatorCacheSetupCheck.php b/src/applications/config/check/PhabricatorCacheSetupCheck.php new file mode 100644 index 0000000000..fba241150e --- /dev/null +++ b/src/applications/config/check/PhabricatorCacheSetupCheck.php @@ -0,0 +1,20 @@ +getIssues() + $data_cache->getIssues(); + + foreach ($issues as $issue) { + $this->addIssue($issue); + } + } + +} diff --git a/src/applications/config/check/PhabricatorSetupCheck.php b/src/applications/config/check/PhabricatorSetupCheck.php index c5e6fae94e..b40dd4c8cc 100644 --- a/src/applications/config/check/PhabricatorSetupCheck.php +++ b/src/applications/config/check/PhabricatorSetupCheck.php @@ -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; } diff --git a/src/applications/config/controller/PhabricatorConfigCacheController.php b/src/applications/config/controller/PhabricatorConfigCacheController.php index cf2d78142d..973f064a5e 100644 --- a/src/applications/config/controller/PhabricatorConfigCacheController.php +++ b/src/applications/config/controller/PhabricatorConfigCacheController.php @@ -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'), diff --git a/src/applications/config/option/PhabricatorCoreConfigOptions.php b/src/applications/config/option/PhabricatorCoreConfigOptions.php index 2521e58f9c..b5df38633a 100644 --- a/src/applications/config/option/PhabricatorCoreConfigOptions.php +++ b/src/applications/config/option/PhabricatorCoreConfigOptions.php @@ -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)