Skip to content

Commit 3e47f16

Browse files
vdrizherukMykhailo Sulyma
authored andcommitted
BAP-14878: Application health check endpoint (#18297)
- added LiipMonitorBundle dependency - added checks for main application`s third party services - added FileDriver for maintenance mode with custom logic of ttl option - added dev documentation - updated composer files in application to enable healthcheck package by default
0 parents  commit 3e47f16

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2321
-0
lines changed

Check/DoctrineDBALCheck.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Oro\Bundle\HealthCheckBundle\Check;
4+
5+
use Liip\MonitorBundle\Check\DoctrineDbal;
6+
7+
class DoctrineDBALCheck extends DoctrineDbal
8+
{
9+
/**
10+
* {@inheritdoc}
11+
*/
12+
public function getLabel()
13+
{
14+
return 'Check if Doctrine DBAL is available';
15+
}
16+
}

Check/ElasticsearchCheck.php

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
namespace Oro\Bundle\HealthCheckBundle\Check;
4+
5+
use Elasticsearch\Connections\Connection;
6+
use Oro\Bundle\ElasticSearchBundle\Client\ClientFactory;
7+
use Oro\Bundle\ElasticSearchBundle\Engine\ElasticSearch as ElasticsearchEngine;
8+
use ZendDiagnostics\Check\CheckInterface;
9+
use ZendDiagnostics\Result\ResultInterface;
10+
use ZendDiagnostics\Result\Success;
11+
use ZendDiagnostics\Result\Failure;
12+
use ZendDiagnostics\Result\Skip;
13+
14+
/**
15+
* Class for check Elasticsearch availability
16+
*/
17+
class ElasticsearchCheck implements CheckInterface
18+
{
19+
/** @var ClientFactory */
20+
protected $clientFactory;
21+
22+
/** @var string */
23+
protected $engineName;
24+
25+
/** @var array */
26+
protected $engineParameters;
27+
28+
/**
29+
* @param ClientFactory $clientFactory
30+
* @param string $engineName
31+
* @param array $engineParameters
32+
*/
33+
public function __construct(ClientFactory $clientFactory, string $engineName, array $engineParameters)
34+
{
35+
$this->clientFactory = $clientFactory;
36+
$this->engineName = $engineName;
37+
$this->engineParameters = $engineParameters;
38+
}
39+
40+
/**
41+
* {@inheritdoc}
42+
*/
43+
public function check(): ResultInterface
44+
{
45+
if ($this->isConfigured()) {
46+
$client = $this->clientFactory->create($this->engineParameters['client']);
47+
48+
$connection = $client->transport->getConnection();
49+
if (!$connection instanceof Connection) {
50+
return new Skip('Elasticsearch connection does not support ping. Check Skipped.');
51+
}
52+
53+
return $connection->ping() && $connection->isAlive() ? new Success() : new Failure();
54+
}
55+
56+
return new Skip('Elasticsearch connection is not configured. Check Skipped.');
57+
}
58+
59+
/**
60+
* @return bool
61+
*/
62+
protected function isConfigured(): bool
63+
{
64+
return ElasticsearchEngine::ENGINE_NAME === $this->engineName;
65+
}
66+
67+
/**
68+
* {@inheritdoc}
69+
*/
70+
public function getLabel(): string
71+
{
72+
return 'Check if Elasticsearch is available in case it is configured';
73+
}
74+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
namespace Oro\Bundle\HealthCheckBundle\Check;
4+
5+
use ZendDiagnostics\Check\DirWritable;
6+
use ZendDiagnostics\Check\CheckCollectionInterface;
7+
8+
/**
9+
* Class for check write permissions on folders
10+
*/
11+
class FileStorageCheckCollection implements CheckCollectionInterface
12+
{
13+
/** @var string */
14+
protected $rootDir;
15+
16+
/** @var array */
17+
protected $checkDirs;
18+
19+
/**
20+
* @param string $rootDir
21+
* @param array $checkDirs
22+
*/
23+
public function __construct(string $rootDir, array $checkDirs)
24+
{
25+
$this->rootDir = $rootDir;
26+
$this->checkDirs = $checkDirs;
27+
}
28+
29+
/**
30+
* {@inheritdoc}
31+
*/
32+
public function getChecks(): array
33+
{
34+
$checks = [];
35+
36+
foreach ($this->checkDirs as $checkDir) {
37+
$check = new DirWritable($checkDir);
38+
$check->setLabel(sprintf('Check if "%s" is writable', $checkDir));
39+
40+
$checks[$this->getCheckShortName($checkDir)] = $check;
41+
}
42+
43+
return $checks;
44+
}
45+
46+
/**
47+
* @param string $checkDir
48+
* @return string
49+
*/
50+
private function getCheckShortName(string $checkDir): string
51+
{
52+
if (strpos($checkDir, $this->rootDir) === 0) {
53+
$checkDir = ltrim(str_replace($this->rootDir, '', $checkDir), '/');
54+
}
55+
56+
$checkDir = preg_replace('/[^[:alpha:]]/', '_', $checkDir);
57+
58+
return preg_replace('/_{2,}/', '_', sprintf('fs_%s', $checkDir));
59+
}
60+
}

Check/MailTransportCheck.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace Oro\Bundle\HealthCheckBundle\Check;
4+
5+
use ZendDiagnostics\Check\CheckInterface;
6+
use ZendDiagnostics\Result\ResultInterface;
7+
use ZendDiagnostics\Result\Success;
8+
use ZendDiagnostics\Result\Failure;
9+
10+
/**
11+
* Class for check mail transport configuration
12+
*/
13+
class MailTransportCheck implements CheckInterface
14+
{
15+
/** @var \Swift_Mailer */
16+
protected $mailer;
17+
18+
/**
19+
* @param \Swift_Mailer $mailer
20+
*/
21+
public function __construct(\Swift_Mailer $mailer)
22+
{
23+
$this->mailer = $mailer;
24+
}
25+
26+
/**
27+
* @return Failure|Success
28+
*/
29+
public function check(): ResultInterface
30+
{
31+
$this->mailer->getTransport()->start();
32+
33+
return new Success();
34+
}
35+
36+
/**
37+
* {@inheritdoc}
38+
*/
39+
public function getLabel(): string
40+
{
41+
return 'Check if Mail Transport is available';
42+
}
43+
}

Check/MaintenanceModeCheck.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespace Oro\Bundle\HealthCheckBundle\Check;
4+
5+
use Lexik\Bundle\MaintenanceBundle\Drivers\DriverFactory;
6+
use Oro\Bundle\HealthCheckBundle\Drivers\FileDriver;
7+
use ZendDiagnostics\Check\CheckInterface;
8+
use ZendDiagnostics\Result\ResultInterface;
9+
use ZendDiagnostics\Result\Success;
10+
use ZendDiagnostics\Result\Failure;
11+
12+
/**
13+
* Class for check Maintenance Mode
14+
*/
15+
class MaintenanceModeCheck implements CheckInterface
16+
{
17+
/** @var DriverFactory */
18+
protected $driverFactory;
19+
20+
/**
21+
* @param DriverFactory $factory
22+
*/
23+
public function __construct(DriverFactory $factory)
24+
{
25+
$this->driverFactory = $factory;
26+
}
27+
28+
/**
29+
* @return Failure|Success
30+
*/
31+
public function check(): ResultInterface
32+
{
33+
$driver = $this->driverFactory->getDriver();
34+
35+
if (!$driver->decide()) {
36+
return new Success('Off');
37+
}
38+
39+
return $driver instanceof FileDriver && $driver->isExpired() ? new Failure('Expired') : new Success('On');
40+
}
41+
42+
/**
43+
* {@inheritdoc}
44+
*/
45+
public function getLabel(): string
46+
{
47+
return 'Check if Maintenance Mode is running and not expired';
48+
}
49+
}

Check/RabbitMQCheck.php

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
namespace Oro\Bundle\HealthCheckBundle\Check;
4+
5+
use Oro\Component\AmqpMessageQueue\Transport\Amqp\AmqpConnection;
6+
use ZendDiagnostics\Check\CheckInterface;
7+
use ZendDiagnostics\Result\ResultInterface;
8+
use ZendDiagnostics\Result\Success;
9+
use ZendDiagnostics\Result\Skip;
10+
11+
/**
12+
* Class for check RabbitMQ availability
13+
*/
14+
class RabbitMQCheck implements CheckInterface
15+
{
16+
/** @var array|null */
17+
protected $config;
18+
19+
/**
20+
* @param array|null $config
21+
*/
22+
public function __construct(array $config = null)
23+
{
24+
$this->config = $config;
25+
}
26+
27+
/**
28+
* {@inheritdoc}
29+
*/
30+
public function check(): ResultInterface
31+
{
32+
if ($this->isConfigured()) {
33+
$connection = AmqpConnection::createFromConfig([
34+
'host' => $this->config['host'],
35+
'port' => $this->config['port'],
36+
'user' => $this->config['user'],
37+
'password' => $this->config['password'],
38+
'vhost' => $this->config['vhost'],
39+
]);
40+
$connection->createSession()->createProducer();
41+
42+
return new Success();
43+
}
44+
45+
return new Skip('RabbitMQ connection is not configured. Check Skipped.');
46+
}
47+
48+
/**
49+
* {@inheritdoc}
50+
*/
51+
public function getLabel(): string
52+
{
53+
return 'Check if RabbitMQ is available in case it is configured';
54+
}
55+
56+
/**
57+
* @return bool
58+
*/
59+
protected function isConfigured(): bool
60+
{
61+
return is_array($this->config) &&
62+
isset(
63+
$this->config['host'],
64+
$this->config['port'],
65+
$this->config['user'],
66+
$this->config['password'],
67+
$this->config['vhost']
68+
);
69+
}
70+
}

Check/RedisCheck.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
namespace Oro\Bundle\HealthCheckBundle\Check;
4+
5+
use Predis\Client as PredisClient;
6+
use ZendDiagnostics\Check\CheckInterface;
7+
use ZendDiagnostics\Result\ResultInterface;
8+
use ZendDiagnostics\Result\Success;
9+
10+
/**
11+
* Validate that a Redis service is running
12+
*/
13+
class RedisCheck implements CheckInterface
14+
{
15+
/** @var PredisClient */
16+
protected $client;
17+
18+
/** @var string */
19+
protected $type;
20+
21+
/**
22+
* @param PredisClient $client
23+
* @param string $type
24+
*/
25+
public function __construct(PredisClient $client, string $type)
26+
{
27+
$this->client = $client;
28+
$this->type = $type;
29+
}
30+
31+
/**
32+
* {@inheritdoc}
33+
*/
34+
public function check(): ResultInterface
35+
{
36+
$this->client->ping();
37+
38+
return new Success();
39+
}
40+
41+
/**
42+
* {@inheritdoc}
43+
*/
44+
public function getLabel()
45+
{
46+
return sprintf('Check if %s is available', $this->type);
47+
}
48+
}

0 commit comments

Comments
 (0)