Skip to content

Commit

Permalink
feat: Use health checks for monitor command (#258)
Browse files Browse the repository at this point in the history
* feat: Use health checks for monitor command

* Fix PHP-CS-Fixer warnings

* Fix PHPStan warnings
  • Loading branch information
M-arcus authored Jun 7, 2024
1 parent 03454b5 commit b0a0b36
Show file tree
Hide file tree
Showing 34 changed files with 146 additions and 172 deletions.
2 changes: 1 addition & 1 deletion src/Command/DevRobotsTxtCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class DevRobotsTxtCommand extends Command
{
public function __construct(
#[Autowire('%kernel.project_dir%/public')]
private readonly string $envPath
private readonly string $envPath,
) {
parent::__construct();
}
Expand Down
2 changes: 1 addition & 1 deletion src/Command/EnvDelCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class EnvDelCommand extends Command
{
public function __construct(
#[Autowire('%kernel.project_dir%/.env')]
private readonly string $envPath
private readonly string $envPath,
) {
parent::__construct();
}
Expand Down
2 changes: 1 addition & 1 deletion src/Command/EnvGetCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class EnvGetCommand extends Command
{
public function __construct(
#[Autowire('%kernel.project_dir%/.env')]
private readonly string $envPath
private readonly string $envPath,
) {
parent::__construct();
}
Expand Down
2 changes: 1 addition & 1 deletion src/Command/EnvSetCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class EnvSetCommand extends Command
{
public function __construct(
#[Autowire('%kernel.project_dir%/.env')]
private readonly string $envPath
private readonly string $envPath,
) {
parent::__construct();
}
Expand Down
94 changes: 31 additions & 63 deletions src/Command/MonitorCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,13 @@

namespace Frosh\Tools\Command;

use Doctrine\DBAL\Connection;
use Frosh\Tools\Components\Health\Checker\HealthChecker\QueueChecker;
use Frosh\Tools\Components\Health\Checker\HealthChecker\TaskChecker;
use Frosh\Tools\Components\Health\HealthCollection;
use Frosh\Tools\Components\Health\SettingsResult;
use Shopware\Core\Content\Mail\Service\AbstractMailService;
use Shopware\Core\Content\Mail\Service\MailService;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\RangeFilter;
use Shopware\Core\Framework\MessageQueue\ScheduledTask\ScheduledTaskCollection;
use Shopware\Core\Framework\MessageQueue\ScheduledTask\ScheduledTaskDefinition;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
Expand All @@ -25,28 +21,25 @@
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\ParameterBag;

#[AsCommand('frosh:monitor', 'Monitor your scheduled tasks and queue with this command and get notified via email.')]
#[AsCommand('frosh:monitor', 'Monitor your scheduled tasks and message queue and get notified via email.')]
class MonitorCommand extends Command
{
private const MONITOR_EMAIL_OPTION = 'email';
private const MONITOR_SALESCHANNEL_ARG = 'sales-channel';

/**
* @param EntityRepository<ScheduledTaskCollection> $scheduledTaskRepository
*/
public function __construct(
#[Autowire(service: MailService::class)]
private readonly AbstractMailService $mailService,
private readonly SystemConfigService $configService,
private readonly Connection $connection,
private readonly EntityRepository $scheduledTaskRepository
private readonly QueueChecker $queueChecker,
private readonly TaskChecker $taskChecker,
) {
parent::__construct();
}

protected function configure(): void
{
$this->addArgument('sales-channel', InputArgument::REQUIRED, 'Sales Channel ID.');
$this->addArgument(self::MONITOR_SALESCHANNEL_ARG, InputArgument::REQUIRED, 'Sales Channel ID.');
$this->addOption(self::MONITOR_EMAIL_OPTION, 'em', InputOption::VALUE_OPTIONAL, 'Custom mail address');
}

Expand All @@ -55,30 +48,30 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$context = Context::createDefaultContext();

if ($input->getOption(self::MONITOR_EMAIL_OPTION)) {
$recepientMail = $input->getOption(self::MONITOR_EMAIL_OPTION);
$recipientMail = $input->getOption(self::MONITOR_EMAIL_OPTION);
$errorSource = 'CLI option';
} else {
$recepientMail = $this->configService->getString(
'FroshTools.config.monitorMail'
$recipientMail = $this->configService->getString(
'FroshTools.config.monitorMail',
);
$errorSource = 'plugin config';
}

if (!filter_var($recepientMail, \FILTER_VALIDATE_EMAIL)) {
$output->writeln('<error>Invalid email format in ' . $errorSource . '</error>');
if (empty($recipientMail) || !filter_var($recipientMail, \FILTER_VALIDATE_EMAIL)) {
$output->writeln('<error>Empty or invalid email format in ' . $errorSource . '</error>');

return self::INVALID;
}

if (!empty($recepientMail) && ($this->queueFailed() || $this->scheduledTaskFailed())) {
if ($this->checksFailed()) {
$data = new ParameterBag();
$data->set(
'recipients',
[
$recepientMail => 'Admin',
]
$recipientMail => 'Admin',
],
);
$data->set('senderName', 'Froshtools | Admin');
$data->set('senderName', 'FroshTools | Admin');

$htmlMailContent = <<<'MAIL'
<div>
Expand All @@ -92,57 +85,32 @@ protected function execute(InputInterface $input, OutputInterface $output): int
</p>
</div>
MAIL;
$plainMailContent = 'Dear Admin,your message queue or scheduled tasks are not working as expected.Check your queues and tasks {{ salesChannel.domains|first.url }}/admin#/frosh/tools/index/index';
$plainMailContent = 'Dear Admin, your message queue or scheduled tasks are not working as expected. Check your queues and tasks {{ salesChannel.domains|first.url }}/admin#/frosh/tools/index/index';

$data->set('contentHtml', $htmlMailContent);
$data->set('contentPlain', $plainMailContent);
$data->set('salesChannelId', $input->getArgument(self::MONITOR_SALESCHANNEL_ARG));
$data->set('subject', 'Froshtools message queue and scheduled task | Warning');
$data->set('subject', 'FroshTools message queue and scheduled task | Warning');

$this->mailService->send($data->all(), $context);
}

return self::SUCCESS;
}

private function queueFailed(): bool
private function checksFailed(): bool
{
/** @var string $availableAt */
$availableAt = $this->connection->fetchOne('SELECT IFNULL(MIN(available_at), 0) FROM messenger_messages');
$oldestMessage = (int) strtotime($availableAt);
$minutes = $this->configService->getInt(
'FroshTools.config.monitorQueueGraceTime'
);

return $oldestMessage && ($oldestMessage + ($minutes * 60)) < time();
}
$collection = new HealthCollection();
$this->queueChecker->collect($collection);
$this->taskChecker->collect($collection);

/** @var SettingsResult $result */
foreach ($collection as $result) {
if ($result->state !== SettingsResult::GREEN && $result->state !== SettingsResult::INFO) {
return true;
}
}

private function scheduledTaskFailed(): bool
{
$minutes = $this->configService->getInt(
'FroshTools.config.monitorTaskGraceTime'
);

$date = new \DateTime();
$date->modify(sprintf('-%d minutes', $minutes));

$criteria = new Criteria();
$criteria->addFilter(
new RangeFilter(
'nextExecutionTime',
['lte' => $date->format(\DATE_ATOM)]
)
);
$criteria->addFilter(new NotFilter(
NotFilter::CONNECTION_AND,
[
new EqualsFilter('status', ScheduledTaskDefinition::STATUS_INACTIVE),
]
));

$oldTasks = $this->scheduledTaskRepository
->searchIds($criteria, Context::createDefaultContext())->getIds();

return $oldTasks !== [];
return false;
}
}
6 changes: 3 additions & 3 deletions src/Command/UpdateComposerPluginsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class UpdateComposerPluginsCommand extends Command
public function __construct(
#[Autowire('%kernel.project_dir%')]
private readonly string $projectDir,
private readonly KernelPluginLoader $pluginLoader
private readonly KernelPluginLoader $pluginLoader,
) {
parent::__construct();
$this->application = new Application();
Expand Down Expand Up @@ -51,7 +51,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
'--working-dir' => $this->projectDir,
'--direct' => null,
'--format' => 'json',
]
],
);

$this->application->run($composerinput, $composerOutput);
Expand Down Expand Up @@ -87,7 +87,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
'command' => 'update',
'--working-dir' => $this->projectDir,
'packages' => $updates,
]
],
);
$this->application->run($composerUpdate, $composerOutput);

Expand Down
2 changes: 1 addition & 1 deletion src/Components/CacheHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ private static function getSizeFallback(string $path): int
$dirIterator = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS | \FilesystemIterator::SKIP_DOTS);
$iterator = new \RecursiveIteratorIterator(
$dirIterator,
\RecursiveIteratorIterator::LEAVES_ONLY
\RecursiveIteratorIterator::LEAVES_ONLY,
);

$size = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ final class AdminInfoSubscriberEventListener
{
public function __construct(
#[Autowire('%frosh_tools.elasticsearch.enabled%')]
private readonly bool $elasticsearchEnabled
private readonly bool $elasticsearchEnabled,
) {}

public function __invoke(ResponseEvent $event): void
Expand Down
2 changes: 1 addition & 1 deletion src/Components/Elasticsearch/ElasticsearchManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public function __construct(
private readonly ElasticsearchOutdatedIndexDetector $outdatedIndexDetector,
private readonly Connection $connection,
#[Autowire(service: 'shopware.increment.gateway.registry')]
private readonly IncrementGatewayRegistry $gatewayRegistry
private readonly IncrementGatewayRegistry $gatewayRegistry,
) {}

public function isEnabled(): bool
Expand Down
10 changes: 5 additions & 5 deletions src/Components/Health/Checker/HealthChecker/MysqlChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ private function checkMariadbVersion(HealthCollection $collection, string $versi
'mysql',
'MariaDB Version',
$version,
'min ' . $minVersion
'min ' . $minVersion,
));
}
}
Expand All @@ -69,7 +69,7 @@ private function checkMysqlVersion(HealthCollection $collection, string $version
'mysql',
$snippet,
$version,
$recommended
$recommended,
));

return;
Expand All @@ -80,7 +80,7 @@ private function checkMysqlVersion(HealthCollection $collection, string $version
'mysql',
$snippet,
$version,
$recommended
$recommended,
));

return;
Expand All @@ -90,7 +90,7 @@ private function checkMysqlVersion(HealthCollection $collection, string $version
'mysql',
$snippet,
$version,
'min ' . $minVersion
'min ' . $minVersion,
));
}

Expand All @@ -115,7 +115,7 @@ private static function getVersionNumber(string $versionString): string
if (!preg_match(
'/^(?:5\.5\.5-)?(mariadb-)?(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)/i',
$versionString,
$versionParts
$versionParts,
)) {
throw new \RuntimeException(sprintf('Invalid version string: %s', $versionString));
}
Expand Down
20 changes: 10 additions & 10 deletions src/Components/Health/Checker/HealthChecker/PhpChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ private function checkPhp(HealthCollection $collection): void
'php-version',
'PHP Version',
$currentPhpVersion,
'min ' . $minPhpVersion
)
'min ' . $minPhpVersion,
),
);

return;
Expand All @@ -49,8 +49,8 @@ private function checkPhp(HealthCollection $collection): void
'php-version',
'PHP Version',
$currentPhpVersion,
'min ' . $minPhpVersion
)
'min ' . $minPhpVersion,
),
);
}

Expand All @@ -64,8 +64,8 @@ private function checkMaxExecutionTime(HealthCollection $collection): void
'php-max-execution',
'Max-Execution-Time',
(string) $currentMaxExecutionTime,
'min ' . $minMaxExecutionTime
)
'min ' . $minMaxExecutionTime,
),
);

return;
Expand All @@ -75,7 +75,7 @@ private function checkMaxExecutionTime(HealthCollection $collection): void
'php-max-execution',
'Max-Execution-Time',
(string) $currentMaxExecutionTime,
'min ' . $minMaxExecutionTime
'min ' . $minMaxExecutionTime,
));
}

Expand All @@ -91,8 +91,8 @@ private function checkMemoryLimit(HealthCollection $collection): void
'php-memory-limit',
'Memory-Limit',
$this->formatSize($currentMemoryLimit),
'min ' . $this->formatSize($minMemoryLimit)
)
'min ' . $this->formatSize($minMemoryLimit),
),
);

return;
Expand All @@ -102,7 +102,7 @@ private function checkMemoryLimit(HealthCollection $collection): void
'php-memory-limit',
'Memory-Limit',
$this->formatSize($currentMemoryLimit),
'min ' . $this->formatSize($minMemoryLimit)
'min ' . $this->formatSize($minMemoryLimit),
));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class ProductionChecker implements HealthCheckerInterface, CheckerInterface
{
public function __construct(
#[Autowire('%kernel.environment%')]
private readonly string $environment
private readonly string $environment,
) {}

public function collect(HealthCollection $collection): void
Expand Down
Loading

0 comments on commit b0a0b36

Please sign in to comment.