Repository navigation
feat(settings): warn when PHP-FPM reaches pm.max_children #46570
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| /** | ||
| * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors | ||
| * SPDX-License-Identifier: AGPL-3.0-or-later | ||
| */ | ||
|
|
||
| namespace OCA\Settings\SetupChecks; | ||
|
|
||
| use OCP\IL10N; | ||
| use OCP\IURLGenerator; | ||
| use OCP\SetupCheck\ISetupCheck; | ||
| use OCP\SetupCheck\SetupResult; | ||
|
|
||
| class PhpSAPI implements ISetupCheck { | ||
| public function __construct( | ||
| private IL10N $l10n, | ||
| private IURLGenerator $urlGenerator, | ||
| ) { | ||
| } | ||
|
|
||
| #[\Override] | ||
| public function getName(): string { | ||
| return $this->l10n->t('PHP-FPM process limit'); | ||
| } | ||
|
|
||
| #[\Override] | ||
| public function getCategory(): string { | ||
| return 'php'; | ||
| } | ||
|
|
||
| #[\Override] | ||
| public function run(): SetupResult { | ||
| if (php_sapi_name() !== 'fpm-fcgi') { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From |
||
| return SetupResult::success(); | ||
| } | ||
|
|
||
| if (!function_exists('fpm_get_status')) { | ||
| return SetupResult::warning( | ||
| $this->l10n->t('PHP-FPM status is unavailable, so the max children check could not be completed.'), | ||
| $this->urlGenerator->linkToDocs('admin-php-fpm') | ||
| ); | ||
| } | ||
|
|
||
| $status = fpm_get_status(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we get a test for this? Wrapping |
||
| if ($status === false) { | ||
| return SetupResult::warning( | ||
| $this->l10n->t('PHP-FPM status could not be read, so the max children check could not be completed.'), | ||
| $this->urlGenerator->linkToDocs('admin-php-fpm') | ||
| ); | ||
| } | ||
|
|
||
| $maxChildrenReached = $status['max-children-reached'] ?? null; | ||
| $maxActiveProcesses = $status['max-active-processes'] ?? null; | ||
| $startTimeEpoch = $status['start-time'] ?? null; | ||
|
|
||
| if (!is_int($maxChildrenReached) || !is_int($maxActiveProcesses) || !is_int($startTimeEpoch)) { | ||
| return SetupResult::warning( | ||
| $this->l10n->t('PHP-FPM status is incomplete, so the max children check could not be completed.'), | ||
| $this->urlGenerator->linkToDocs('admin-php-fpm') | ||
| ); | ||
| } | ||
|
|
||
| if ($maxChildrenReached > 0) { | ||
| $startTime = date('Y-m-d H:i:s T', $startTimeEpoch); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| $timesReached = $this->l10n->n('once', '%n times', $maxChildrenReached); | ||
|
|
||
| $message = $this->l10n->t( | ||
| 'PHP-FPM reached its configured "pm.max_children" limit %s since its last restart at %s (peak active processes: %s).', | ||
| [$timesReached, $startTime, (string)$maxActiveProcesses], | ||
| ); | ||
| $message .= ' ' . $this->l10n->t( | ||
| 'When the pool is saturated, additional requests may be queued, time out, or fail. This can cause slow responses, client connection errors, or 502/504 gateway errors.' | ||
| ); | ||
| $message .= "\n\n" . $this->l10n->t( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think the setup checks list keeps line breaks in the web UI (no |
||
| 'The counter resets when PHP-FPM restarts. If saturation is ongoing or recurring, review pool configuration and server capacity and consider increasing "pm.max_children".' | ||
| ); | ||
|
|
||
| return SetupResult::warning( | ||
| $message, | ||
| $this->urlGenerator->linkToDocs('admin-php-fpm'), | ||
| ); | ||
| } | ||
|
|
||
| return SetupResult::success(); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick:
PhpSAPIsounds broader than what this checks. What aboutPhpFpmMaxChildren?