Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Core] Feature #3432, add the Healthcheck Page #3450

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions src/module-elasticsuite-core/Api/Healthcheck/CheckInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php
/**
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Smile ElasticSuite to newer
* versions in the future.
*
* @category Smile
* @package Smile\ElasticsuiteCore
* @author Vadym Honcharuk <[email protected]>
* @copyright 2024 Smile
* @license Open Software License ("OSL") v. 3.0
*/

namespace Smile\ElasticsuiteCore\Api\Healthcheck;

/**
* Health CheckInterface.
*/
interface CheckInterface
{
/**
* Warning status declaration.
*/
const WARNING_STATUS = 'warning';

/**
* Retrieve the unique identifier for the health check.
*
* @return string
*/
public function getIdentifier(): string;

/**
* Retrieve the description of the health check.
*
* @return string
*/
public function getDescription(): string;

/**
* Retrieve the status of the health check.
* Expected values: 'success', 'warning'.
*
* @return string
*/
public function getStatus(): string;

/**
* Retrieve the sort order for the health check, which determines
* the display order of checks in the admin panel.
*
* @return int
*/
public function getSortOrder(): int;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php
/**
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Smile ElasticSuite to newer
* versions in the future.
*
* @category Smile
* @package Smile\ElasticsuiteCore
* @author Vadym Honcharuk <[email protected]>
* @copyright 2024 Smile
* @license Open Software License ("OSL") v. 3.0
*/

namespace Smile\ElasticsuiteCore\Block\Adminhtml\Healthcheck;

use Magento\Backend\Block\Template;
use Magento\Backend\Block\Template\Context;
use Smile\ElasticsuiteCore\Api\Healthcheck\CheckInterface;
use Smile\ElasticsuiteCore\Model\Healthcheck\HealthcheckList;

/**
* Class Healthcheck.
*
* Block class for displaying Elasticsuite health checks in the Magento Admin panel.
*/
class Healthcheck extends Template
{
/**
* HealthcheckList instance to manage and retrieve health checks.
*
* @var HealthcheckList
*/
private $healthcheckList;

/**
* Constructor.
*
* @param Context $context Magento context object for backend blocks.
* @param HealthcheckList $healthcheckList The health check list object providing health check data.
* @param array $data Additional block data.
*/
public function __construct(Context $context, HealthcheckList $healthcheckList, array $data = [])
{
parent::__construct($context, $data);
$this->healthcheckList = $healthcheckList;
}

/**
* Retrieve all health checks.
*
* Provides an array of health check instances, each implementing the CheckInterface,
* sorted by their specified order.
*
* @return CheckInterface[]
*/
public function getHealthchecks(): array
{
return $this->healthcheckList->getChecks();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php
/**
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Smile ElasticSuite to newer
* versions in the future.
*
* @category Smile
* @package Smile\ElasticsuiteCore
* @author Vadym Honcharuk <[email protected]>
* @copyright 2024 Smile
* @license Open Software License ("OSL") v. 3.0
*/

namespace Smile\ElasticsuiteCore\Controller\Adminhtml\Healthcheck;

use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\View\Result\Page;
use Smile\ElasticsuiteIndices\Controller\Adminhtml\AbstractAction;

/**
* Class Index.
*/
class Index extends AbstractAction implements HttpGetActionInterface
{
/**
* @inheritdoc
*
* @return Page
*/
public function execute(): Page
{
$breadMain = __('Healthcheck');

/** @var Page $resultPage */
$resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE);
$resultPage->getConfig()->getTitle()->prepend($breadMain);

return $resultPage;
}
}
164 changes: 164 additions & 0 deletions src/module-elasticsuite-core/Model/Healthcheck/GhostIndicesCheck.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
<?php
/**
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Smile ElasticSuite to newer
* versions in the future.
*
* @category Smile
* @package Smile\ElasticsuiteCore
* @author Vadym Honcharuk <[email protected]>
* @copyright 2024 Smile
* @license Open Software License ("OSL") v. 3.0
*/

namespace Smile\ElasticsuiteCore\Model\Healthcheck;

use Exception;
use Magento\Framework\UrlInterface;
use Smile\ElasticsuiteCore\Api\Healthcheck\CheckInterface;
use Smile\ElasticsuiteIndices\Model\IndexStatsProvider;

/**
* Class GhostIndicesCheck.
*
* Health check to identify any ghost indices in the Elasticsearch cluster.
*/
class GhostIndicesCheck implements CheckInterface
{
/**
* Route to Elasticsuite -> Indices page.
*/
private const ROUTE_ELASTICSUITE_INDICES = 'smile_elasticsuite_indices';

public const GHOST_STATUS = 'ghost';

/**
* @var IndexStatsProvider
*/
private $indexStatsProvider;

/**
* @var UrlInterface
*/
private $urlBuilder;

/**
* Constructor.
*
* @param IndexStatsProvider $indexStatsProvider Index stats provider.
* @param UrlInterface $urlBuilder URL builder.
*/
public function __construct(
IndexStatsProvider $indexStatsProvider,
UrlInterface $urlBuilder
) {
$this->indexStatsProvider = $indexStatsProvider;
$this->urlBuilder = $urlBuilder;
}

/**
* Retrieve the unique identifier for this health check.
*
* @return string
*/
public function getIdentifier(): string
{
return 'ghost_indices_check';
}

/**
* Retrieve a brief description of this health check.
*
* @return string
* @throws Exception
*/
public function getDescription(): string
{
$ghostCount = $this->getNumberOfGhostIndices();

if ($ghostCount > 0) {
// Description when ghost indices are found.
// @codingStandardsIgnoreStart
return __(
'You have <strong>%1 ghost indices</strong>. Ghost indices have a footprint on your Elasticsearch cluster health. '
. 'You should consider removing them.<br/>'
. 'Click <a href="%2"><strong>here</strong></a> to go to the <strong>Elasticsuite Indices</strong> page to take appropriate actions.',
$ghostCount,
$this->getElasticsuiteIndicesUrl()
);
// @codingStandardsIgnoreEnd
}

// Description when no ghost indices are found.
return __('There are no ghost indexes in your Elasticsearch cluster. No action is required at this time.');
}

/**
* Retrieve the status of this health check.
* Returns 'warning' if ghost indices are found, otherwise 'success'.
*
* @return string
* @throws Exception
*/
public function getStatus(): string
{
return $this->hasGhostIndices() ? 'warning' : 'success';
}

/**
* Retrieve the sort order for this health check.
*
* @return int
*/
public function getSortOrder(): int
{
return 10; // Adjust as necessary.
}

/**
* Checks if there are any ghost indices.
*
* @return bool
* @throws Exception
*/
private function hasGhostIndices(): bool
{
return $this->getNumberOfGhostIndices() > 0;
}

/**
* Get number of ghost Elasticsuite indices.
*
* @return int
* @throws Exception
*/
private function getNumberOfGhostIndices(): int
{
$ghostIndices = 0;
$elasticsuiteIndices = $this->indexStatsProvider->getElasticSuiteIndices();

if ($elasticsuiteIndices !== null) {
foreach ($elasticsuiteIndices as $indexName => $indexAlias) {
$indexData = $this->indexStatsProvider->indexStats($indexName, $indexAlias);

if (array_key_exists('index_status', $indexData)
&& $indexData['index_status'] === self::GHOST_STATUS) {
$ghostIndices++;
}
}
}

return $ghostIndices;
}

/**
* Retrieve a URL to the Elasticsuite Indices page for more information.
*
* @return string
*/
private function getElasticsuiteIndicesUrl(): string
{
return $this->urlBuilder->getUrl(self::ROUTE_ELASTICSUITE_INDICES);
}
}
59 changes: 59 additions & 0 deletions src/module-elasticsuite-core/Model/Healthcheck/HealthcheckList.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php
/**
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Smile ElasticSuite to newer
* versions in the future.
*
* @category Smile
* @package Smile\ElasticsuiteCore
* @author Vadym Honcharuk <[email protected]>
* @copyright 2024 Smile
* @license Open Software License ("OSL") v. 3.0
*/

namespace Smile\ElasticsuiteCore\Model\Healthcheck;

use Smile\ElasticsuiteCore\Api\Healthcheck\CheckInterface;

/**
* Class HealthcheckList.
*
* Manages a list of health checks for the Elasticsuite module.
*/
class HealthcheckList
{
/**
* Array of health checks implementing the CheckInterface.
*
* @var CheckInterface[]
*/
private $checks;

/**
* Constructor.
*
* @param CheckInterface[] $checks Array of health checks to be managed by this list.
*/
public function __construct(array $checks = [])
{
$this->checks = $checks;
}

/**
* Retrieve all health checks, sorted by their sort order.
*
* Sorts the checks based on the value returned by each check's `getSortOrder` method.
*
* @return CheckInterface[] Array of health checks sorted by order.
* @SuppressWarnings(PHPMD.ShortVariable)
*/
public function getChecks(): array
{
usort($this->checks, function (CheckInterface $a, CheckInterface $b) {
return $a->getSortOrder() <=> $b->getSortOrder();
});

return $this->checks;
}
}
Loading