Skip to content

Commit

Permalink
Merge pull request #66 from bram123/add-elasticsearch-check
Browse files Browse the repository at this point in the history
Add new ElasticSearch healthcheck
  • Loading branch information
Ocramius authored Jan 30, 2023
2 parents 67902c4 + 192bf3f commit d797ab6
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/Check/AbstractCheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ abstract class AbstractCheck implements CheckInterface
/**
* Explicitly set label.
*
* @var string
* @var ?string
*/
protected $label;

Expand Down
58 changes: 58 additions & 0 deletions src/Check/ElasticSearch.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

namespace Laminas\Diagnostics\Check;

use Exception;
use GuzzleHttp\ClientInterface as GuzzleClientInterface;
use Laminas\Diagnostics\Result\Failure;
use Laminas\Diagnostics\Result\ResultInterface;
use Laminas\Diagnostics\Result\Success;
use Laminas\Diagnostics\Result\Warning;

use function array_merge;
use function microtime;
use function trim;

/**
* Ensures a connection to ElasticSearch is possible and the cluster health is 'green'
*/
class ElasticSearch extends GuzzleHttpService
{
/**
* @param array $headers An array of headers used to create the request
* @param array $options An array of guzzle options used to create the request
* @param null|GuzzleClientInterface $guzzle Instance of guzzle to use
*/
public function __construct(string $elasticSearchUrl, array $headers = [], array $options = [], $guzzle = null)
{
$elasticSearchUrl .= '/_cat/health?h=status';

parent::__construct($elasticSearchUrl, $headers, $options, 200, null, $guzzle);
}

public function check(): ResultInterface
{
try {
$startTime = microtime(true);
$response = $this->guzzle->send($this->request, array_merge($this->options));
$health = trim((string) $response->getBody());
$responseTime = microtime(true) - $startTime;
} catch (Exception $e) {
return new Failure("Unable to connect to elasticsearch: " . $e->getMessage());
}

$serviceData = [
"responseTime" => $responseTime,
];

if ($health === 'green') {
return new Success("Cluster status green", $serviceData);
}

if ($health === 'yellow') {
return new Warning("Cluster status yellow", $serviceData);
}

return new Failure("Cluster status red", $serviceData);
}
}
53 changes: 53 additions & 0 deletions test/ElasticSearchTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace LaminasTest\Diagnostics;

use Exception;
use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\Psr7\Response;
use Laminas\Diagnostics\Check\ElasticSearch;
use Laminas\Diagnostics\Result\FailureInterface;
use Laminas\Diagnostics\Result\ResultInterface;
use Laminas\Diagnostics\Result\SuccessInterface;
use Laminas\Diagnostics\Result\WarningInterface;
use PHPUnit\Framework\TestCase;

/** @coversDefaultClass \Laminas\Diagnostics\Check\ElasticSearch */
class ElasticSearchTest extends TestCase
{
/**
* @dataProvider healthStatusProvider
* @param class-string<ResultInterface> $expectedResult
* @throws Exception
*/
public function testElasticSearch(string $clusterStatus, string $expectedResult): void
{
$mockHandler = new MockHandler([new Response(200, [], $clusterStatus)]);
$mockClient = new Client(['handler' => $mockHandler]);
$check = new ElasticSearch('localhost:9200', [], [], $mockClient);

// Assert the ElasticSearch check converts the API response to the correct ResultInterface implementation
$checkResult = $check->check();
static::assertInstanceOf($expectedResult, $checkResult);

// Assert ElasticSearch check returns extra data
$resultData = $checkResult->getData();
static::assertIsArray($resultData);
static::assertArrayHasKey('responseTime', $resultData);
static::assertIsNumeric($resultData['responseTime']);
}

/**
* @return array{array{string, class-string<ResultInterface>}}
*/
public function healthStatusProvider(): array
{
return [
["green\n", SuccessInterface::class],
["yellow\n", WarningInterface::class],
["red\n", FailureInterface::class],
["unknown\n", FailureInterface::class],
];
}
}
2 changes: 1 addition & 1 deletion test/TestAsset/Check/TriggerUserError.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

final class TriggerUserError extends AbstractCheck
{
/** @var string */
/** @var ?string */
protected $label = '';

private string $message;
Expand Down

0 comments on commit d797ab6

Please sign in to comment.