Skip to content

Commit f3f741a

Browse files
authored
feat: add checks for PHP FPM when not in cluster mode (#336)
1 parent c8f0fbd commit f3f741a

File tree

4 files changed

+120
-12
lines changed

4 files changed

+120
-12
lines changed

phpstan.neon.dist

+3
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@ parameters:
33
paths:
44
- src
55
reportUnmatchedIgnoredErrors: false
6+
ignoreErrors:
7+
-
8+
message: "#no value type specified in iterable type array#"

src/Components/Health/Checker/HealthChecker/PhpChecker.php

+5-12
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Frosh\Tools\Components\Health\Checker\CheckerInterface;
88
use Frosh\Tools\Components\Health\HealthCollection;
99
use Frosh\Tools\Components\Health\SettingsResult;
10+
use Frosh\Tools\FroshTools;
1011

1112
class PhpChecker implements HealthCheckerInterface, CheckerInterface
1213
{
@@ -19,14 +20,6 @@ public function collect(HealthCollection $collection): void
1920
$this->checkPcreJitActive($collection);
2021
}
2122

22-
private function formatSize(float $size): string
23-
{
24-
$base = log($size) / log(1024);
25-
$suffix = ['', 'k', 'M', 'G', 'T'][floor($base)];
26-
27-
return (1024 ** ($base - floor($base))) . $suffix;
28-
}
29-
3023
private function checkPhp(HealthCollection $collection): void
3124
{
3225
$minPhpVersion = '8.2.0';
@@ -90,8 +83,8 @@ private function checkMemoryLimit(HealthCollection $collection): void
9083
SettingsResult::error(
9184
'php-memory-limit',
9285
'Memory-Limit',
93-
$this->formatSize($currentMemoryLimit),
94-
'min ' . $this->formatSize($minMemoryLimit),
86+
FroshTools::formatSize($currentMemoryLimit),
87+
'min ' . FroshTools::formatSize($minMemoryLimit),
9588
),
9689
);
9790

@@ -101,8 +94,8 @@ private function checkMemoryLimit(HealthCollection $collection): void
10194
$collection->add(SettingsResult::ok(
10295
'php-memory-limit',
10396
'Memory-Limit',
104-
$this->formatSize($currentMemoryLimit),
105-
'min ' . $this->formatSize($minMemoryLimit),
97+
FroshTools::formatSize($currentMemoryLimit),
98+
'min ' . FroshTools::formatSize($minMemoryLimit),
10699
));
107100
}
108101

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Frosh\Tools\Components\Health\Checker\HealthChecker;
6+
7+
use Frosh\Tools\Components\Health\Checker\CheckerInterface;
8+
use Frosh\Tools\Components\Health\HealthCollection;
9+
use Frosh\Tools\Components\Health\SettingsResult;
10+
use Frosh\Tools\FroshTools;
11+
use Symfony\Component\DependencyInjection\Attribute\Autowire;
12+
13+
class PhpFpmChecker implements HealthCheckerInterface, CheckerInterface
14+
{
15+
public function __construct(
16+
#[Autowire(param: 'shopware.deployment.cluster_setup')]
17+
private readonly bool $clusterSetup,
18+
) {
19+
}
20+
21+
public function collect(HealthCollection $collection): void
22+
{
23+
if ($this->clusterSetup) {
24+
return;
25+
}
26+
27+
if (\function_exists('fpm_get_status') === false) {
28+
return;
29+
}
30+
31+
$fpmStatus = \fpm_get_status();
32+
33+
if ($fpmStatus === false) {
34+
return;
35+
}
36+
37+
$this->checkListenQueue($fpmStatus, $collection);
38+
$this->checkMaxChildren($fpmStatus, $collection);
39+
$this->checkMemoryPeak($fpmStatus, $collection);
40+
}
41+
42+
private function checkListenQueue(array $fpmStatus, HealthCollection $collection): void
43+
{
44+
$listenQueue = $fpmStatus['max-listen-queue'] ?? 0;
45+
46+
$status = SettingsResult::ok(
47+
'php-fpm-max-listen-queue',
48+
'PHP FPM max listen queue',
49+
(string) $listenQueue,
50+
'0',
51+
'https://www.php.net/manual/en/fpm.status.php#:~:text=a%20free%20process.-,max%20listen%20queue,-The%20maximum%20number'
52+
);
53+
54+
if ($listenQueue > 0) {
55+
$status->state = SettingsResult::WARNING;
56+
}
57+
58+
$collection->add($status);
59+
}
60+
61+
private function checkMaxChildren(array $fpmStatus, HealthCollection $collection): void
62+
{
63+
$maxChildrenReached = (bool) ($fpmStatus['max-children-reached'] ?? false);
64+
65+
$status = SettingsResult::ok(
66+
'php-fpm-max-children-reached',
67+
'PHP FPM max children reached',
68+
$maxChildrenReached ? 'yes' : 'no',
69+
'no',
70+
'https://www.php.net/manual/en/fpm.status.php#:~:text=max%20children%20reached'
71+
);
72+
73+
if ($maxChildrenReached) {
74+
$status->state = SettingsResult::WARNING;
75+
}
76+
77+
$collection->add($status);
78+
}
79+
80+
private function checkMemoryPeak(array $fpmStatus, HealthCollection $collection): void
81+
{
82+
// Skip this check if memory-peak is not available (PHP < 8.4)
83+
if (!isset($fpmStatus['memory-peak'])) {
84+
return;
85+
}
86+
87+
$memoryPeak = $fpmStatus['memory-peak'];
88+
$memoryPeak = FroshTools::formatSize($memoryPeak);
89+
90+
$collection->add(
91+
SettingsResult::ok(
92+
'php-fpm-memory-peak',
93+
'PHP FPM memory peak',
94+
$memoryPeak,
95+
'',
96+
'https://www.php.net/manual/en/fpm.status.php#:~:text=memory%20peak'
97+
)
98+
);
99+
}
100+
}

src/FroshTools.php

+12
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@ public function build(ContainerBuilder $container): void
2121
$container->addCompilerPass(new DisableElasticsearchCompilerPass());
2222
}
2323

24+
public static function formatSize(float $size): string
25+
{
26+
if ($size <= 0) {
27+
return '0';
28+
}
29+
30+
$base = log($size) / log(1024);
31+
$suffix = ['', 'k', 'M', 'G', 'T'][floor($base)];
32+
33+
return round(1024 ** ($base - floor($base)), 2) . $suffix;
34+
}
35+
2436
protected function createContainerExtension(): FroshToolsExtension
2537
{
2638
return new FroshToolsExtension();

0 commit comments

Comments
 (0)