From 6675f7b8758b7ab9d8ddbf001b35d57ae43dd259 Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Tue, 21 May 2024 16:57:31 +0200 Subject: [PATCH 01/26] Symplify autowiring and remove backticks - remove ORM dependency --- composer.json | 1 - src/Controller/InfoController.php | 13 +++-- .../Compiler/HealthCheckPass.php | 48 ------------------- .../OpenConextMonitorExtension.php | 13 ----- .../DoctrineConnectionHealthCheck.php | 27 +++++------ src/HealthCheck/HealthCheckChain.php | 9 +++- src/OpenConextMonitorBundle.php | 1 - src/Resources/config/routing.yml | 8 ++-- src/Resources/config/services.yml | 36 +++++--------- 9 files changed, 44 insertions(+), 112 deletions(-) delete mode 100644 src/DependencyInjection/Compiler/HealthCheckPass.php diff --git a/composer.json b/composer.json index 2e70275..9299fa4 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,6 @@ "minimum-stability": "stable", "require": { "php": ">=8.2, <9.0-dev", - "doctrine/orm": "^2.9", "doctrine/dbal": "^3.1", "endroid/installer": "^1.4", "symfony/dependency-injection": "^5.4|^6.3|^7.0", diff --git a/src/Controller/InfoController.php b/src/Controller/InfoController.php index c968f40..bdbd97e 100644 --- a/src/Controller/InfoController.php +++ b/src/Controller/InfoController.php @@ -19,11 +19,10 @@ namespace OpenConext\MonitorBundle\Controller; use OpenConext\MonitorBundle\Value\BuildInformationFactory; -use OpenConext\MonitorBundle\Value\BuildPathFactory; use OpenConext\MonitorBundle\Value\Information; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpFoundation\JsonResponse; -use Symfony\Component\HttpFoundation\Response; /** * Display specific information about the application. @@ -43,15 +42,23 @@ class InfoController extends AbstractController { private array $systemInfo = []; + private readonly string $buildPath; public function __construct( - private readonly string $buildPath, + #[Autowire(param: 'kernel.project_dir')] + private readonly string $projectDir, + #[Autowire(param: 'kernel.environment')] private readonly string $environment, + #[Autowire(param: 'kernel.debug')] private readonly bool $debuggerEnabled, + #[Autowire(env: 'default::string:OPENCONEXT_APP_VERSION')] private readonly ?string $version, + #[Autowire(env: 'default::string:OPENCONEXT_GIT_SHA')] private readonly ?string $revision, + #[Autowire(env: 'default::string:OPENCONEXT_COMMIT_DATE')] private readonly ?string $commitDate, ) { + $this->buildPath = basename(realpath($this->projectDir)); if (function_exists('opcache_get_status')) { $this->systemInfo['opcache'] = opcache_get_status(false); diff --git a/src/DependencyInjection/Compiler/HealthCheckPass.php b/src/DependencyInjection/Compiler/HealthCheckPass.php deleted file mode 100644 index 680fe6c..0000000 --- a/src/DependencyInjection/Compiler/HealthCheckPass.php +++ /dev/null @@ -1,48 +0,0 @@ -has('openconext.monitor.health_check_chain')) { - return; - } - - $definition = $container->findDefinition('openconext.monitor.health_check_chain'); - - // find all service IDs with the openconext.monitor.health_check tag - $taggedServices = $container->findTaggedServiceIds('openconext.monitor.health_check'); - - foreach ($taggedServices as $id => $tags) { - $definition->addMethodCall('addHealthCheck', array(new Reference($id))); - } - } -} diff --git a/src/DependencyInjection/OpenConextMonitorExtension.php b/src/DependencyInjection/OpenConextMonitorExtension.php index ab1e0c4..53e76f0 100644 --- a/src/DependencyInjection/OpenConextMonitorExtension.php +++ b/src/DependencyInjection/OpenConextMonitorExtension.php @@ -38,19 +38,6 @@ public function load(array $configs, ContainerBuilder $container): void { $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); $loader->load('services.yml'); - - $this->setInfoControllerArguments($container); } - private function setInfoControllerArguments(ContainerBuilder $container) - { - // The buildPath is the installation directory of the project. And is derived from the kernel.project_dir - // (which is the app folder). - $rootDir = $container->getParameter('kernel.project_dir'); - $buildPath = basename(realpath($rootDir)); - - $container - ->getDefinition('openconext.monitor.controller.info') - ->replaceArgument(0, $buildPath); - } } diff --git a/src/HealthCheck/DoctrineConnectionHealthCheck.php b/src/HealthCheck/DoctrineConnectionHealthCheck.php index 3c204d6..4aea193 100644 --- a/src/HealthCheck/DoctrineConnectionHealthCheck.php +++ b/src/HealthCheck/DoctrineConnectionHealthCheck.php @@ -18,9 +18,10 @@ namespace OpenConext\MonitorBundle\HealthCheck; -use Doctrine\ORM\EntityManager; +use Doctrine\DBAL\Connection; use Exception; use OpenConext\MonitorBundle\Value\HealthReport; +use Symfony\Component\DependencyInjection\Attribute\Autowire; /** * Test if there is a working database connection. @@ -30,34 +31,28 @@ */ class DoctrineConnectionHealthCheck implements HealthCheckInterface { - /** - * @var EntityManager|null - */ - private $entityManager; - /** - * @param EntityManager $entityManager - */ - public function setEntityManager(EntityManager $entityManager) - { - $this->entityManager = $entityManager; + public function __construct( + #[Autowire(service: 'doctrine.dbal.default_connection')] + private readonly ?Connection $connection + ) { } public function check(HealthReportInterface $report): HealthReportInterface { // Was the entityManager injected? When it is not the project does not use Doctrine ORM - if (!is_null($this->entityManager)) { + if (!is_null($this->connection)) { try { // Get the schema manager and grab the first table to later query on - $sm = $this->entityManager->getConnection()->createSchemaManager(); + $sm = $this->connection->createSchemaManager(); $tables = $sm->listTables(); if (!empty($tables)) { $table = reset($tables); // Perform a light-weight query on the chosen table - $query = 'SELECT * FROM `%s` LIMIT 1'; - $this->entityManager->getConnection()->executeQuery(sprintf($query, $table->getName())); + $query = "SELECT * FROM %s LIMIT 1"; + $this->connection->executeQuery(sprintf($query, $table->getName())); } - } catch (Exception $e) { + } catch (Exception) { return HealthReport::buildStatusDown('Unable to execute a query on the database.'); } } diff --git a/src/HealthCheck/HealthCheckChain.php b/src/HealthCheck/HealthCheckChain.php index acfa308..9122b3a 100644 --- a/src/HealthCheck/HealthCheckChain.php +++ b/src/HealthCheck/HealthCheckChain.php @@ -19,6 +19,7 @@ namespace OpenConext\MonitorBundle\HealthCheck; use OpenConext\MonitorBundle\Value\HealthReport; +use Symfony\Component\DependencyInjection\Attribute\TaggedIterator; /** * Collect HealthCheck instances and checks them for UP or DOWN status. @@ -30,9 +31,15 @@ class HealthCheckChain */ private $checks; - public function __construct() + public function __construct( + #[TaggedIterator('openconext.monitor.health_check')] private readonly iterable $healthChecks + ) { $this->checks = []; + + foreach ($healthChecks as $healthCheck) { + $this->addHealthCheck($healthCheck); + } } public function addHealthCheck(HealthCheckInterface $healthCheck) diff --git a/src/OpenConextMonitorBundle.php b/src/OpenConextMonitorBundle.php index 21f7513..d565b75 100644 --- a/src/OpenConextMonitorBundle.php +++ b/src/OpenConextMonitorBundle.php @@ -26,6 +26,5 @@ class OpenConextMonitorBundle extends Bundle { public function build(ContainerBuilder $container): void { - $container->addCompilerPass(new HealthCheckPass()); } } diff --git a/src/Resources/config/routing.yml b/src/Resources/config/routing.yml index fcfda87..c5bbf74 100644 --- a/src/Resources/config/routing.yml +++ b/src/Resources/config/routing.yml @@ -3,22 +3,22 @@ monitor.info: path: /info methods: [GET] defaults: - _controller: openconext.monitor.controller.info + _controller: OpenConext\MonitorBundle\Controller\InfoController monitor.health: path: /health methods: [GET] defaults: - _controller: openconext.monitor.controller.health + _controller: OpenConext\MonitorBundle\Controller\HealthController monitor.internal_info: path: /internal/info methods: [GET] defaults: - _controller: openconext.monitor.controller.info + _controller: OpenConext\MonitorBundle\Controller\InfoController monitor.internal_health: path: /internal/health methods: [GET] defaults: - _controller: openconext.monitor.controller.health + _controller: OpenConext\MonitorBundle\Controller\HealthController diff --git a/src/Resources/config/services.yml b/src/Resources/config/services.yml index bb09adf..de286e8 100644 --- a/src/Resources/config/services.yml +++ b/src/Resources/config/services.yml @@ -1,35 +1,21 @@ services: - openconext.monitor.controller.info: - class: OpenConext\MonitorBundle\Controller\InfoController - arguments: - - '~' - - '%kernel.environment%' - - '%kernel.debug%' - - '%env(default::string:OPENCONEXT_APP_VERSION)%' - - '%env(default::string:OPENCONEXT_GIT_SHA)%' - - '%env(default::string:OPENCONEXT_COMMIT_DATE)%' + _defaults: + autowire: true # Automatically injects dependencies in your services. + autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. - autowire: true - tags: ['controller.service_arguments', 'container.service_subscriber'] - - openconext.monitor.controller.health: - class: OpenConext\MonitorBundle\Controller\HealthController - arguments: - - '@openconext.monitor.health_check_chain' - autowire: true - tags: ['controller.service_arguments', 'container.service_subscriber'] + OpenConext\MonitorBundle\: + resource: '../../' + exclude: '../../{Entity,Repository,Tests,Resources,DependencyInjection,OpenConextMonitorBundle.php}' openconext.monitor.health_check_chain: class: OpenConext\MonitorBundle\HealthCheck\HealthCheckChain openconext.monitor.session_health_check: class: OpenConext\MonitorBundle\HealthCheck\SessionHealthCheck - tags: - - { name: openconext.monitor.health_check } - openconext.monitor.database_health_check: + openconext.monitor.doctrine_health_check: class: OpenConext\MonitorBundle\HealthCheck\DoctrineConnectionHealthCheck - calls: - - [ setEntityManager, ['@?doctrine.orm.entity_manager']] - tags: - - { name: openconext.monitor.health_check } + + _instanceof: + OpenConext\MonitorBundle\HealthCheck\HealthCheckInterface: + tags: ['openconext.monitor.health_check'] From 6ec9b2310137c2b7d8516fd76878e5d33a88c7eb Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Tue, 21 May 2024 17:17:50 +0200 Subject: [PATCH 02/26] Fix tests using iterator --- .../HealthCheck/SessionHealthCheckChainTest.php | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Tests/HealthCheck/SessionHealthCheckChainTest.php b/src/Tests/HealthCheck/SessionHealthCheckChainTest.php index 9e90502..bb1e70a 100644 --- a/src/Tests/HealthCheck/SessionHealthCheckChainTest.php +++ b/src/Tests/HealthCheck/SessionHealthCheckChainTest.php @@ -57,10 +57,9 @@ public function testChain() ->once() ->andReturn($statusOk); - $chain = new HealthCheckChain(); - $chain->addHealthCheck($checker1); - $chain->addHealthCheck($checker2); - $chain->addHealthCheck($checker3); + $iterator = new \ArrayIterator([$checker1, $checker2, $checker3]); + + $chain = new HealthCheckChain($iterator); $result = $chain->check(); $this->assertEquals($statusOk, $result); @@ -93,10 +92,9 @@ public function testChainStopsWhenCheckFails() $checker3 = m::mock(HealthCheckInterface::class); $checker3->shouldNotReceive('check'); - $chain = new HealthCheckChain(); - $chain->addHealthCheck($checker1); - $chain->addHealthCheck($checker2); - $chain->addHealthCheck($checker3); + $iterator = new \ArrayIterator([$checker1, $checker2, $checker3]); + + $chain = new HealthCheckChain($iterator); $result = $chain->check(); $this->assertEquals($statusDown, $result); From 906b17bb09218fb4f6776f12f54ffd8b8f11bf4b Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Tue, 21 May 2024 17:53:57 +0200 Subject: [PATCH 03/26] Update composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 9299fa4..cd4d633 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "minimum-stability": "stable", "require": { "php": ">=8.2, <9.0-dev", - "doctrine/dbal": "^3.1", + "doctrine/dbal": "^3.1|^4.0", "endroid/installer": "^1.4", "symfony/dependency-injection": "^5.4|^6.3|^7.0", "symfony/framework-bundle": "^5.4|^6.3|^7.0", From 1c77aa2e413cc89813e70f07a2b8681eb5821b52 Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Tue, 21 May 2024 18:44:14 +0200 Subject: [PATCH 04/26] Remove obsolete service definitions --- src/Resources/config/services.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/Resources/config/services.yml b/src/Resources/config/services.yml index de286e8..d511355 100644 --- a/src/Resources/config/services.yml +++ b/src/Resources/config/services.yml @@ -7,15 +7,6 @@ services: resource: '../../' exclude: '../../{Entity,Repository,Tests,Resources,DependencyInjection,OpenConextMonitorBundle.php}' - openconext.monitor.health_check_chain: - class: OpenConext\MonitorBundle\HealthCheck\HealthCheckChain - - openconext.monitor.session_health_check: - class: OpenConext\MonitorBundle\HealthCheck\SessionHealthCheck - - openconext.monitor.doctrine_health_check: - class: OpenConext\MonitorBundle\HealthCheck\DoctrineConnectionHealthCheck - _instanceof: OpenConext\MonitorBundle\HealthCheck\HealthCheckInterface: tags: ['openconext.monitor.health_check'] From 208ea2b05204909c9fcba839e86b907ba053f8b5 Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Tue, 21 May 2024 19:01:42 +0200 Subject: [PATCH 05/26] Symplify checks because they are already iterable --- src/HealthCheck/HealthCheckChain.php | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/src/HealthCheck/HealthCheckChain.php b/src/HealthCheck/HealthCheckChain.php index 9122b3a..fbe3646 100644 --- a/src/HealthCheck/HealthCheckChain.php +++ b/src/HealthCheck/HealthCheckChain.php @@ -26,25 +26,9 @@ */ class HealthCheckChain { - /** - * @var HealthCheckInterface[] - */ - private $checks; - public function __construct( #[TaggedIterator('openconext.monitor.health_check')] private readonly iterable $healthChecks - ) - { - $this->checks = []; - - foreach ($healthChecks as $healthCheck) { - $this->addHealthCheck($healthCheck); - } - } - - public function addHealthCheck(HealthCheckInterface $healthCheck) - { - $this->checks[] = $healthCheck; + ) { } /** @@ -53,8 +37,8 @@ public function addHealthCheck(HealthCheckInterface $healthCheck) public function check(): HealthReportInterface { $report = HealthReport::buildStatusUp(); - if (!empty($this->checks)) { - foreach ($this->checks as $check) { + if (!empty($this->healthChecks)) { + foreach ($this->healthChecks as $check) { $report = $check->check($report); if ($report->isDown()) { return $report; From 0b1ad67eb76c3db378fcdb9e386903d8f222ed75 Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Tue, 21 May 2024 19:11:32 +0200 Subject: [PATCH 06/26] Simplify bundle config --- .../OpenConextMonitorExtension.php | 43 ------------------- src/OpenConextMonitorBundle.php | 9 ++-- 2 files changed, 5 insertions(+), 47 deletions(-) delete mode 100644 src/DependencyInjection/OpenConextMonitorExtension.php diff --git a/src/DependencyInjection/OpenConextMonitorExtension.php b/src/DependencyInjection/OpenConextMonitorExtension.php deleted file mode 100644 index 53e76f0..0000000 --- a/src/DependencyInjection/OpenConextMonitorExtension.php +++ /dev/null @@ -1,43 +0,0 @@ -load('services.yml'); - } - -} diff --git a/src/OpenConextMonitorBundle.php b/src/OpenConextMonitorBundle.php index d565b75..0c66c5e 100644 --- a/src/OpenConextMonitorBundle.php +++ b/src/OpenConextMonitorBundle.php @@ -18,13 +18,14 @@ namespace OpenConext\MonitorBundle; -use OpenConext\MonitorBundle\DependencyInjection\Compiler\HealthCheckPass; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\HttpKernel\Bundle\Bundle; +use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; +use Symfony\Component\HttpKernel\Bundle\AbstractBundle; -class OpenConextMonitorBundle extends Bundle +class OpenConextMonitorBundle extends AbstractBundle { - public function build(ContainerBuilder $container): void + public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void { + $container->import('../config/services.yml'); } } From 0bd6c60343bbc5abe36b7ec75a32b2f2063a2836 Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Tue, 21 May 2024 19:15:04 +0200 Subject: [PATCH 07/26] Move services to main config --- {src/Resources/config => config}/services.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {src/Resources/config => config}/services.yml (100%) diff --git a/src/Resources/config/services.yml b/config/services.yml similarity index 100% rename from src/Resources/config/services.yml rename to config/services.yml From 3baac8b867c8edb0e1b8ee55dcc7f02a56704155 Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Tue, 21 May 2024 19:20:30 +0200 Subject: [PATCH 08/26] Move routes to main config --- {src/Resources/config => config}/routing.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {src/Resources/config => config}/routing.yml (100%) diff --git a/src/Resources/config/routing.yml b/config/routing.yml similarity index 100% rename from src/Resources/config/routing.yml rename to config/routing.yml From a72ca0ddb68c97e95ab477bce02b757493537e9c Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Tue, 21 May 2024 19:33:23 +0200 Subject: [PATCH 09/26] Refactor services to new filestructure --- config/{routing.yml => routing.yaml} | 0 config/{services.yml => services.yaml} | 4 ++-- src/OpenConextMonitorBundle.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename config/{routing.yml => routing.yaml} (100%) rename config/{services.yml => services.yaml} (73%) diff --git a/config/routing.yml b/config/routing.yaml similarity index 100% rename from config/routing.yml rename to config/routing.yaml diff --git a/config/services.yml b/config/services.yaml similarity index 73% rename from config/services.yml rename to config/services.yaml index d511355..7e21b69 100644 --- a/config/services.yml +++ b/config/services.yaml @@ -4,8 +4,8 @@ services: autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. OpenConext\MonitorBundle\: - resource: '../../' - exclude: '../../{Entity,Repository,Tests,Resources,DependencyInjection,OpenConextMonitorBundle.php}' + resource: '../src/' + exclude: '../src/{Entity,Repository,Tests,Resources,DependencyInjection,OpenConextMonitorBundle.php}' _instanceof: OpenConext\MonitorBundle\HealthCheck\HealthCheckInterface: diff --git a/src/OpenConextMonitorBundle.php b/src/OpenConextMonitorBundle.php index 0c66c5e..04238d7 100644 --- a/src/OpenConextMonitorBundle.php +++ b/src/OpenConextMonitorBundle.php @@ -26,6 +26,6 @@ class OpenConextMonitorBundle extends AbstractBundle { public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void { - $container->import('../config/services.yml'); + $container->import('../config/services.yaml'); } } From 7db89e361e4608772bc5eb9797098f79d140862b Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Tue, 21 May 2024 19:41:16 +0200 Subject: [PATCH 10/26] Adjust file location --- .install/symfony/config/routes/open_conext_monitor.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.install/symfony/config/routes/open_conext_monitor.yaml b/.install/symfony/config/routes/open_conext_monitor.yaml index ca03974..148183a 100644 --- a/.install/symfony/config/routes/open_conext_monitor.yaml +++ b/.install/symfony/config/routes/open_conext_monitor.yaml @@ -1,5 +1,5 @@ open_conext_monitor: - resource: "@OpenConextMonitorBundle/Resources/config/routing.yml" + resource: "@OpenConextMonitorBundle/config/routing.yaml" prefix: / From 719fd95166395b82d8e9eceb5bcaa7c4c1deb0a9 Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Tue, 21 May 2024 19:51:46 +0200 Subject: [PATCH 11/26] Add / adjust instructions --- README.md | 41 ++++++++++------------------------------- 1 file changed, 10 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index a266d65..9026b14 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ When a health check failed the HTTP Response status code will be 503. And the JS * Include the routing configuration in `config/routes.yaml` by adding: ```yaml open_conext_monitor: - resource: "@OpenConextMonitorBundle/Resources/config/routing.yml" + resource: "@OpenConextMonitorBundle/config/routing.yaml" prefix: / ``` @@ -78,24 +78,18 @@ use OpenConext\MonitorBundle\Value\HealthReport; class ApiHealthCheck implements HealthCheckInterface { - /** - * @var MyService - */ - private $testService; - - public function __construct(MyService $service) + public function __construct(private readonly MyService $service) { - $this->testService = $service; } public function check(HealthReportInterface $report): HealthReportInterface { - if (!$this->testService->everythingOk()) { + if (!$this->service->everythingOk()) { // Return a HealthReport with a DOWN status when there are indications the application is not functioning as // intended. You can provide an optional message that is displayed alongside the DOWN status. return HealthReport::buildStatusDown('Not everything is allright.'); } - // By default return the report that was passed along as a parameter to the check method + // By default, return the report that was passed along as a parameter to the check method return $report; } } @@ -104,35 +98,20 @@ class ApiHealthCheck implements HealthCheckInterface registered health checkers. If everything was OK, just return the report that was passed to the method. ### Register the checker -To actually include the home made checker simply tag it with 'surfnet.monitor.health_check' - -Example service definition in `services.yml` - -```yaml -services: - acme.monitor.my_custom_health_check: - class: Acme\AppBundle\HealthCheck\MyCustomHealthCheck - arguments: - - @test_service - tags: - - { name: surfnet.monitor.health_check } -``` +By implementing the `HealthCheckInterface` you can register your own health check. +This interface is tagged with `openconext.monitor.health_check` so you don't have to do it yourself. ## Overriding a default HealthCheck To run a custom query with the DoctrineConnectionHealthCheck you will need to override it in your own project. -For example in your ACME bunde that is using the monitor bundle: +For example in your ACME bundle that is using the monitor bundle: -`services.yml` +`services.yaml` ```yaml - # Override the service, service names can be found in `/src/Resources/config/services.yml` - openconext.monitor.database_health_check: + # Override the service in `/src/config/services.yaml` + OpenConext\MonitorBundle\HealthCheck\DoctrineConnectionHealthCheck: # Point to your own implementation of the check class: Acme\GreatSuccessBundle\HealthCheck\DoctrineConnectionHealthCheck - # Do not forget to apply the correct tag - tags: - - { name: openconext.monitor.health_check } - ``` The rest of the service configuration is up to your own needs. You can inject arguments, factory calls and other service features as need be. From 4c76eab668caa98c6b53df59491f3ec36ed7c6ca Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Wed, 22 May 2024 01:26:15 +0200 Subject: [PATCH 12/26] Add AutoConfigureTag --- README.md | 2 +- config/services.yaml | 4 ---- src/HealthCheck/HealthCheckInterface.php | 3 +++ 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9026b14..905b9b8 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A Symfony 5/6/7 bundle that adds an /internal/health and /internal/info endpoint The endpoints return JSON responses. The `/internal/info` endpoint tries to give as much information about the currently installed version of the application as possible. This information is based on the build path of the installation. But also -includes the Symfony environment that is currently active and whether or not the debugger is enabled. +includes the Symfony environment that is currently active and whether the debugger is enabled. The `/internal/health` endpoint reports on the health of the application. This information could be used for example by a load balancer. Example output: diff --git a/config/services.yaml b/config/services.yaml index 7e21b69..7317294 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -6,7 +6,3 @@ services: OpenConext\MonitorBundle\: resource: '../src/' exclude: '../src/{Entity,Repository,Tests,Resources,DependencyInjection,OpenConextMonitorBundle.php}' - - _instanceof: - OpenConext\MonitorBundle\HealthCheck\HealthCheckInterface: - tags: ['openconext.monitor.health_check'] diff --git a/src/HealthCheck/HealthCheckInterface.php b/src/HealthCheck/HealthCheckInterface.php index bf49b49..0a6342d 100644 --- a/src/HealthCheck/HealthCheckInterface.php +++ b/src/HealthCheck/HealthCheckInterface.php @@ -18,9 +18,12 @@ namespace OpenConext\MonitorBundle\HealthCheck; +use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag; + /** * Contract for a HealthCheck. */ +#[AutoconfigureTag('openconext.monitor.health_check')] interface HealthCheckInterface { public function check(HealthReportInterface $report): HealthReportInterface; From 086a2802e9fb4cb4825db9b7fa20471c66bb9978 Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Wed, 22 May 2024 01:32:23 +0200 Subject: [PATCH 13/26] Remove 5.4 as supported version --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index cd4d633..8a4fd20 100644 --- a/composer.json +++ b/composer.json @@ -9,8 +9,8 @@ "php": ">=8.2, <9.0-dev", "doctrine/dbal": "^3.1|^4.0", "endroid/installer": "^1.4", - "symfony/dependency-injection": "^5.4|^6.3|^7.0", - "symfony/framework-bundle": "^5.4|^6.3|^7.0", + "symfony/dependency-injection": "^6.3|^7.0", + "symfony/framework-bundle": "^6.3|^7.0", "webmozart/assert": "^1.10" }, "require-dev": { From a374adb62575d82147044cb5e994fb6c8b79a512 Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Wed, 22 May 2024 01:46:16 +0200 Subject: [PATCH 14/26] Remove tag name and use the interface --- src/HealthCheck/HealthCheckChain.php | 3 ++- src/HealthCheck/HealthCheckInterface.php | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/HealthCheck/HealthCheckChain.php b/src/HealthCheck/HealthCheckChain.php index fbe3646..9d8a377 100644 --- a/src/HealthCheck/HealthCheckChain.php +++ b/src/HealthCheck/HealthCheckChain.php @@ -27,7 +27,8 @@ class HealthCheckChain { public function __construct( - #[TaggedIterator('openconext.monitor.health_check')] private readonly iterable $healthChecks + #[TaggedIterator(HealthCheckInterface::class)] + private readonly iterable $healthChecks ) { } diff --git a/src/HealthCheck/HealthCheckInterface.php b/src/HealthCheck/HealthCheckInterface.php index 0a6342d..0312fb1 100644 --- a/src/HealthCheck/HealthCheckInterface.php +++ b/src/HealthCheck/HealthCheckInterface.php @@ -23,7 +23,7 @@ /** * Contract for a HealthCheck. */ -#[AutoconfigureTag('openconext.monitor.health_check')] +#[AutoconfigureTag()] interface HealthCheckInterface { public function check(HealthReportInterface $report): HealthReportInterface; From 33fe6a02f8d1a8a351e3c4d704b3f47f08484204 Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Wed, 22 May 2024 10:50:17 +0200 Subject: [PATCH 15/26] Solved "error"? I am unsure if it was an error as the test results do not change after this fix. This is a smell of an untrusted test --- src/Tests/HealthCheck/SessionHealthCheckChainTest.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Tests/HealthCheck/SessionHealthCheckChainTest.php b/src/Tests/HealthCheck/SessionHealthCheckChainTest.php index bb1e70a..7d72620 100644 --- a/src/Tests/HealthCheck/SessionHealthCheckChainTest.php +++ b/src/Tests/HealthCheck/SessionHealthCheckChainTest.php @@ -18,6 +18,7 @@ namespace OpenConext\MonitorBundle\Tests\HealthCheck; +use ArrayIterator; use Mockery as m; use OpenConext\MonitorBundle\HealthCheck\HealthCheckChain; use OpenConext\MonitorBundle\HealthCheck\HealthCheckInterface; @@ -57,7 +58,7 @@ public function testChain() ->once() ->andReturn($statusOk); - $iterator = new \ArrayIterator([$checker1, $checker2, $checker3]); + $iterator = new ArrayIterator([$checker1, $checker2, $checker3]); $chain = new HealthCheckChain($iterator); @@ -73,7 +74,7 @@ public function testChainStopsWhenCheckFails() ->andReturn(false); $statusDown = m::mock(HealthReport::buildStatusDown('Lorem ipsum dolor sit')); - $statusOk + $statusDown ->shouldReceive('isDown') ->andReturn(true); @@ -92,7 +93,7 @@ public function testChainStopsWhenCheckFails() $checker3 = m::mock(HealthCheckInterface::class); $checker3->shouldNotReceive('check'); - $iterator = new \ArrayIterator([$checker1, $checker2, $checker3]); + $iterator = new ArrayIterator([$checker1, $checker2, $checker3]); $chain = new HealthCheckChain($iterator); From 32d15a7855d32f177ba74e1f3d54bf43bee1b3c6 Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Wed, 22 May 2024 11:05:04 +0200 Subject: [PATCH 16/26] Remove unused dependencies --- composer.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/composer.json b/composer.json index 8a4fd20..d83cd2d 100644 --- a/composer.json +++ b/composer.json @@ -16,9 +16,6 @@ "require-dev": { "php-parallel-lint/php-parallel-lint": "^1.3", "phpmd/phpmd": "^2.13", - "matthiasnoback/symfony-config-test": "^4.3", - "phpdocumentor/reflection-docblock": "^5.2", - "phpunit/php-token-stream": "^3.1.3|^4.0.4", "phpunit/phpunit": "^9.6|^10.4", "sebastian/phpcpd": "^4.1|^5.0|^6.0", "squizlabs/php_codesniffer": "^3.6", From c8857dd32143599cf3fa15f0f5ff7181f683610c Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Wed, 22 May 2024 11:10:24 +0200 Subject: [PATCH 17/26] Adjust description --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index d83cd2d..cdf2749 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "openconext/monitor-bundle", "type": "symfony-bundle", - "description": "A Symfony 5/6/7 bundle that facilitates health and info endpoints to a Symfony application.", + "description": "A Symfony 6/7 bundle that facilitates health and info endpoints to a Symfony application.", "keywords": ["SURFnet", "StepUp", "OpenConext", "monitoring", "health"], "license": "Apache-2.0", "minimum-stability": "stable", From a3500613d6e70f963bcabf3ef94eb37eb32283df Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Wed, 22 May 2024 11:13:05 +0200 Subject: [PATCH 18/26] Move tests out of src --- README.md | 2 +- composer.json | 10 +++++----- phpunit.xml | 6 +++--- .../HealthCheck/SessionHealthCheckChainTest.php | 0 .../Value/BuildInformationFactoryTest.php | 0 {src/Tests => tests}/Value/BuildPathFactoryTest.php | 0 {src/Tests => tests}/Value/EnvVarFactoryTest.php | 0 7 files changed, 9 insertions(+), 9 deletions(-) rename {src/Tests => tests}/HealthCheck/SessionHealthCheckChainTest.php (100%) rename {src/Tests => tests}/Value/BuildInformationFactoryTest.php (100%) rename {src/Tests => tests}/Value/BuildPathFactoryTest.php (100%) rename {src/Tests => tests}/Value/EnvVarFactoryTest.php (100%) diff --git a/README.md b/README.md index 905b9b8..375db9a 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ registered health checkers. If everything was OK, just return the report that wa ### Register the checker By implementing the `HealthCheckInterface` you can register your own health check. -This interface is tagged with `openconext.monitor.health_check` so you don't have to do it yourself. +This interface is tagged automatically, so you don't have to do it yourself. ## Overriding a default HealthCheck To run a custom query with the DoctrineConnectionHealthCheck you will need to override it in your own project. diff --git a/composer.json b/composer.json index cdf2749..6747f8f 100644 --- a/composer.json +++ b/composer.json @@ -29,16 +29,16 @@ }, "autoload-dev": { "psr-4": { - "App\\Tests\\": "src/Tests/" + "App\\Tests\\": "tests/" } }, "scripts": { "tests": { - "docheader": "vendor/bin/docheader check src/", - "phpcs": "vendor/bin/phpcs src --report=full --standard=phpcs.xml --extensions=php --warning-severity=0", - "phpcpd": "vendor/bin/phpcpd src --exclude=src/Tests/*", + "docheader": "vendor/bin/docheader check src/ tests/", + "phpcs": "vendor/bin/phpcs src tests --report=full --standard=phpcs.xml --extensions=php --warning-severity=0", + "phpcpd": "vendor/bin/phpcpd src", "phpunit": "vendor/bin/phpunit --coverage-text", - "phpmd": "vendor/bin/phpmd src text phpmd.xml --exclude 'src/Tests/*'" + "phpmd": "vendor/bin/phpmd src text phpmd.xml" }, "post-update-cmd": [ "@tests" diff --git a/phpunit.xml b/phpunit.xml index ff1f970..76f82cd 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -19,7 +19,7 @@ - + z @@ -30,12 +30,12 @@ .github - src/Tests + tests - src/Tests + tests diff --git a/src/Tests/HealthCheck/SessionHealthCheckChainTest.php b/tests/HealthCheck/SessionHealthCheckChainTest.php similarity index 100% rename from src/Tests/HealthCheck/SessionHealthCheckChainTest.php rename to tests/HealthCheck/SessionHealthCheckChainTest.php diff --git a/src/Tests/Value/BuildInformationFactoryTest.php b/tests/Value/BuildInformationFactoryTest.php similarity index 100% rename from src/Tests/Value/BuildInformationFactoryTest.php rename to tests/Value/BuildInformationFactoryTest.php diff --git a/src/Tests/Value/BuildPathFactoryTest.php b/tests/Value/BuildPathFactoryTest.php similarity index 100% rename from src/Tests/Value/BuildPathFactoryTest.php rename to tests/Value/BuildPathFactoryTest.php diff --git a/src/Tests/Value/EnvVarFactoryTest.php b/tests/Value/EnvVarFactoryTest.php similarity index 100% rename from src/Tests/Value/EnvVarFactoryTest.php rename to tests/Value/EnvVarFactoryTest.php From 4f71bbc4286cd302e31d9dc94ba8aa729f9fc514 Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Wed, 22 May 2024 11:26:34 +0200 Subject: [PATCH 19/26] Remove extra character --- src/HealthCheck/DoctrineConnectionHealthCheck.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/HealthCheck/DoctrineConnectionHealthCheck.php b/src/HealthCheck/DoctrineConnectionHealthCheck.php index 4aea193..af7a97a 100644 --- a/src/HealthCheck/DoctrineConnectionHealthCheck.php +++ b/src/HealthCheck/DoctrineConnectionHealthCheck.php @@ -40,7 +40,6 @@ public function __construct( public function check(HealthReportInterface $report): HealthReportInterface { - // Was the entityManager injected? When it is not the project does not use Doctrine ORM if (!is_null($this->connection)) { try { // Get the schema manager and grab the first table to later query on From 1d6bec8c1acd741f5492d0a337364f505e645c05 Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Wed, 22 May 2024 11:29:28 +0200 Subject: [PATCH 20/26] Remove obsolete settings --- phpunit.xml | 49 +++++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/phpunit.xml b/phpunit.xml index 76f82cd..18d25eb 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -13,32 +13,29 @@ > - - - - - - - z - - + + + + + + - - - src - - - .github - tests - - - - - tests - - - - - + + + src + + + .github + tests + + + + + tests + + + + + From bcc01a28a07235bc67a8e5006e29b10148cad169 Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Wed, 22 May 2024 19:30:10 +0200 Subject: [PATCH 21/26] Fix deprecation (see https://github.com/symfony/symfony/commit/4bc6bedfdb21f8de6cfcfd9860aa10490a321b95) --- src/HealthCheck/HealthCheckChain.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/HealthCheck/HealthCheckChain.php b/src/HealthCheck/HealthCheckChain.php index 9d8a377..698d697 100644 --- a/src/HealthCheck/HealthCheckChain.php +++ b/src/HealthCheck/HealthCheckChain.php @@ -19,7 +19,7 @@ namespace OpenConext\MonitorBundle\HealthCheck; use OpenConext\MonitorBundle\Value\HealthReport; -use Symfony\Component\DependencyInjection\Attribute\TaggedIterator; +use Symfony\Component\DependencyInjection\Attribute\AutowireIterator; /** * Collect HealthCheck instances and checks them for UP or DOWN status. @@ -27,7 +27,7 @@ class HealthCheckChain { public function __construct( - #[TaggedIterator(HealthCheckInterface::class)] + #[AutowireIterator(HealthCheckInterface::class)] private readonly iterable $healthChecks ) { } From 642f8038241117e09673c5597fee2b44b2568574 Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Thu, 23 May 2024 17:48:11 +0200 Subject: [PATCH 22/26] Switch to attribute routes --- config/routing.yaml | 24 ------------------------ src/Controller/HealthController.php | 3 +++ src/Controller/InfoController.php | 3 +++ 3 files changed, 6 insertions(+), 24 deletions(-) delete mode 100644 config/routing.yaml diff --git a/config/routing.yaml b/config/routing.yaml deleted file mode 100644 index c5bbf74..0000000 --- a/config/routing.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# Deprecated routes: /info and /health are moving to /internal/info and internal/health respectively. -monitor.info: - path: /info - methods: [GET] - defaults: - _controller: OpenConext\MonitorBundle\Controller\InfoController - -monitor.health: - path: /health - methods: [GET] - defaults: - _controller: OpenConext\MonitorBundle\Controller\HealthController - -monitor.internal_info: - path: /internal/info - methods: [GET] - defaults: - _controller: OpenConext\MonitorBundle\Controller\InfoController - -monitor.internal_health: - path: /internal/health - methods: [GET] - defaults: - _controller: OpenConext\MonitorBundle\Controller\HealthController diff --git a/src/Controller/HealthController.php b/src/Controller/HealthController.php index e37f091..59f583a 100644 --- a/src/Controller/HealthController.php +++ b/src/Controller/HealthController.php @@ -21,6 +21,7 @@ use OpenConext\MonitorBundle\HealthCheck\HealthCheckChain; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\Routing\Attribute\Route; /** * Display the health state of the application. @@ -35,6 +36,8 @@ public function __construct( ) { } + #[Route('/health', name: 'monitor.health', methods: ['GET'])] + #[Route('/internal/health', name: 'monitor.internal_health', methods: ['GET'])] public function __invoke(): JsonResponse { $statusResponse = $this->healthChecker->check(); diff --git a/src/Controller/InfoController.php b/src/Controller/InfoController.php index bdbd97e..243ddf9 100644 --- a/src/Controller/InfoController.php +++ b/src/Controller/InfoController.php @@ -23,6 +23,7 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\Routing\Attribute\Route; /** * Display specific information about the application. @@ -65,6 +66,8 @@ public function __construct( } } + #[Route('/info', name: 'monitor.info', methods: ['GET'])] + #[Route('/internal/info', name: 'monitor.internal_info', methods: ['GET'])] public function __invoke(): JsonResponse { $buildInformation = BuildInformationFactory::build( From c24912838e75e79cec00c119c197d34cb65d86e7 Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Thu, 23 May 2024 17:56:36 +0200 Subject: [PATCH 23/26] Add correct routes to config installer --- .install/symfony/config/routes/open_conext_monitor.yaml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.install/symfony/config/routes/open_conext_monitor.yaml b/.install/symfony/config/routes/open_conext_monitor.yaml index 148183a..856e844 100644 --- a/.install/symfony/config/routes/open_conext_monitor.yaml +++ b/.install/symfony/config/routes/open_conext_monitor.yaml @@ -1,5 +1,4 @@ open_conext_monitor: - resource: "@OpenConextMonitorBundle/config/routing.yaml" - prefix: / - - + resource: "@OpenConextMonitorBundle/src/Controller" + type: attribute + prefix: / From 04cabafe910aac005680d196dc6b6d4fc04631ad Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Thu, 23 May 2024 18:04:23 +0200 Subject: [PATCH 24/26] Update with routing --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 375db9a..1f13bf2 100644 --- a/README.md +++ b/README.md @@ -46,8 +46,9 @@ When a health check failed the HTTP Response status code will be 503. And the JS * Include the routing configuration in `config/routes.yaml` by adding: ```yaml open_conext_monitor: - resource: "@OpenConextMonitorBundle/config/routing.yaml" - prefix: / + resource: "@OpenConextMonitorBundle/src/Controller" + type: attribute + prefix: / ``` * Add security exceptions in `config/packages/security.yaml` (if this is required at all) From 9bfb3f20089362c7925f9defcd29537e3fde4ceb Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Thu, 23 May 2024 18:15:57 +0200 Subject: [PATCH 25/26] Add information about the routin installer --- README.md | 1 + composer.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1f13bf2..01e3c63 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ When a health check failed the HTTP Response status code will be 503. And the JS type: attribute prefix: / ``` +_Note: this is currently done by the bundle itself, with an external dependency called https://github.com/endroid/installer_ * Add security exceptions in `config/packages/security.yaml` (if this is required at all) ```yaml diff --git a/composer.json b/composer.json index 6747f8f..04a3f59 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ }, "autoload": { "psr-4": { - "OpenConext\\MonitorBundle\\": "src" + "OpenConext\\MonitorBundle\\": "src/" } }, "autoload-dev": { From e83bde5e9e21fc81c0ec0aa2de3eb5635cdd706c Mon Sep 17 00:00:00 2001 From: Paul Rijke Date: Thu, 30 May 2024 12:33:01 +0200 Subject: [PATCH 26/26] Re-anabled the tags --- src/HealthCheck/HealthCheckChain.php | 2 +- src/HealthCheck/HealthCheckInterface.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/HealthCheck/HealthCheckChain.php b/src/HealthCheck/HealthCheckChain.php index 698d697..16e2940 100644 --- a/src/HealthCheck/HealthCheckChain.php +++ b/src/HealthCheck/HealthCheckChain.php @@ -27,7 +27,7 @@ class HealthCheckChain { public function __construct( - #[AutowireIterator(HealthCheckInterface::class)] + #[AutowireIterator(tag: 'surfnet.monitor.health_check')] private readonly iterable $healthChecks ) { } diff --git a/src/HealthCheck/HealthCheckInterface.php b/src/HealthCheck/HealthCheckInterface.php index 0312fb1..aa002a5 100644 --- a/src/HealthCheck/HealthCheckInterface.php +++ b/src/HealthCheck/HealthCheckInterface.php @@ -23,7 +23,7 @@ /** * Contract for a HealthCheck. */ -#[AutoconfigureTag()] +#[AutoconfigureTag('surfnet.monitor.health_check')] interface HealthCheckInterface { public function check(HealthReportInterface $report): HealthReportInterface;