Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
- add state fix for console command
- add command option resolving fix
- add shipments aggregator
- add shipments count aggregator unit tests coverage.
  • Loading branch information
swnsma committed Nov 13, 2021
1 parent 6b30bc1 commit 4861c2c
Show file tree
Hide file tree
Showing 4 changed files with 253 additions and 3 deletions.
135 changes: 135 additions & 0 deletions Test/Unit/Aggregator/Shipment/ShipmentCountAggregatorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<?php declare(strict_types=1);

namespace RunAsRoot\PrometheusExporter\Test\Unit\Aggregator\Shipment;

use Magento\Framework\App\ResourceConnection;
use Magento\Framework\DB\Adapter\AdapterInterface;
use Magento\Framework\DB\Select;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use RunAsRoot\PrometheusExporter\Aggregator\Shipment\ShipmentCountAggregator;
use RunAsRoot\PrometheusExporter\Service\UpdateMetricService;

final class ShipmentCountAggregatorTest extends TestCase
{
private const METRIC_CODE = 'magento_shipments_count_total';
private const T_SHIP = 'm2_sales_shipment';
private const T_INV_SHIP = 'm2_inventory_shipment_source';
private const T_STORE = 'm2_store';

private ShipmentCountAggregator $subject;

/** @var MockObject|UpdateMetricService */
private $updateMetricService;

/** @var MockObject|ResourceConnection */
private $resourceConnection;

protected function setUp(): void
{
$this->updateMetricService = $this->createMock(UpdateMetricService::class);
$this->resourceConnection = $this->createMock(ResourceConnection::class);

$this->subject = new ShipmentCountAggregator(
$this->updateMetricService,
$this->resourceConnection
);
}

private function getStatisticData(): array
{
return [
[
'SHIPMENT_COUNT' => 111,
'STORE_CODE' => 'default',
'SOURCE_CODE' => 'default'
],
[
'SHIPMENT_COUNT' => 222,
'STORE_CODE' => 'default',
'SOURCE_CODE' => 'eu'
],
[
'SHIPMENT_COUNT' => 333,
'STORE_CODE' => 'nl',
'SOURCE_CODE' => 'eu'
]
];
}

private function getSelectMock(): MockObject
{
$select = $this->createMock(Select::class);
$select->expects($this->once())
->method('from')
->with(['ss' => self::T_SHIP])
->willReturn($select);

$select->expects($this->exactly(2))
->method('joinInner')
->withConsecutive(
[
['iss' => self::T_INV_SHIP],
'ss.entity_id = iss.shipment_id',
['source_code']
],
[
['s' => self::T_STORE],
'ss.store_id = s.store_id',
['code']
]

)->willReturn($select);
$select->expects($this->once())->method('reset')->with(Select::COLUMNS)->willReturn($select);
$select->expects($this->once())->method('group')->with(['s.code', 'iss.source_code']);
$select->expects($this->once())
->method('columns')
->with(
[
'SHIPMENT_COUNT' => 'COUNT(ss.entity_id)',
'STORE_CODE' => 's.code',
'SOURCE_CODE' => 'iss.source_code'
]
)->willReturn($select);

return $select;
}

public function testAggregate(): void
{
$connection = $this->createMock(AdapterInterface::class);
$statisticData = $this->getStatisticData();
$select = $this->getSelectMock();

$this->resourceConnection->expects($this->once())
->method('getConnection')
->with('sales')
->willReturn($connection);
$connection->expects($this->once())->method('select')->willReturn($select);
$connection->expects($this->once())->method('fetchAll')->with($select)->willReturn($statisticData);
$connection->expects($this->exactly(3))
->method('getTableName')
->willReturnMap(
[
['sales_shipment', self::T_SHIP],
['inventory_shipment_source', self::T_INV_SHIP],
['store', self::T_STORE]
]
);

$params = [];
foreach ($statisticData as $datum) {
$params[] = [
self::METRIC_CODE,
$datum['SHIPMENT_COUNT'],
['source' => $datum['SOURCE_CODE'], 'store_code' => $datum['STORE_CODE']]
];
}

$this->updateMetricService->expects($this->exactly(3))
->method('update')
->withConsecutive(...$params);

$this->subject->aggregate();
}
}
89 changes: 89 additions & 0 deletions src/Aggregator/Shipment/ShipmentCountAggregator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php declare(strict_types=1);

namespace RunAsRoot\PrometheusExporter\Aggregator\Shipment;

use Magento\Framework\App\ResourceConnection;
use Magento\Framework\DB\Adapter\AdapterInterface;
use Magento\Framework\DB\Select;
use RunAsRoot\PrometheusExporter\Api\MetricAggregatorInterface;
use RunAsRoot\PrometheusExporter\Service\UpdateMetricService;

class ShipmentCountAggregator implements MetricAggregatorInterface
{
private const METRIC_CODE = 'magento_shipments_count_total';

private UpdateMetricService $updateMetricService;

private ResourceConnection $resourceConnection;

/**
* @param UpdateMetricService $updateMetricService
* @param ResourceConnection $resourceConnection
*/
public function __construct(
UpdateMetricService $updateMetricService,
ResourceConnection $resourceConnection
) {
$this->updateMetricService = $updateMetricService;
$this->resourceConnection = $resourceConnection;
}

public function getCode(): string
{
return self::METRIC_CODE;
}

public function getHelp(): string
{
return 'Magento 2 Shipments amount by store and source.';
}

public function getType(): string
{
return 'counter';
}

public function aggregate(): bool
{
$connection = $this->resourceConnection->getConnection('sales');

$statistic = $connection->fetchAll($this->getSelect($connection));

foreach ($statistic as $result) {
$count = $result['SHIPMENT_COUNT'] ?? 0;
$store = $result['STORE_CODE'] ?? '';
$source = $result['SOURCE_CODE'] ?? '';

$labels = ['source' => $source, 'store_code' => $store];

$this->updateMetricService->update(self::METRIC_CODE, (string)$count, $labels);
}

return true;
}

private function getSelect(AdapterInterface $connection): Select
{
$select = $connection->select();

$select->from(['ss' => $connection->getTableName('sales_shipment')])
->joinInner(
['iss' => $connection->getTableName('inventory_shipment_source')],
'ss.entity_id = iss.shipment_id',
['source_code']
)->joinInner(
['s' => $connection->getTableName('store')],
'ss.store_id = s.store_id',
['code']
)->reset(Select::COLUMNS)
->columns(
[
'SHIPMENT_COUNT' => 'COUNT(ss.entity_id)',
'STORE_CODE' => 's.code',
'SOURCE_CODE' => 'iss.source_code'
]
)->group(['s.code', 'iss.source_code']);

return $select;
}
}
29 changes: 26 additions & 3 deletions src/Console/Command/CollectMetricsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

namespace RunAsRoot\PrometheusExporter\Console\Command;

use Magento\Framework\App\Area;
use Magento\Framework\App\State;
use Magento\Framework\Exception\LocalizedException;
use RunAsRoot\PrometheusExporter\Cron\AggregateMetricsCron;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
Expand All @@ -17,11 +20,20 @@ class CollectMetricsCommand extends Command

private $aggregateMetricsCron;

public function __construct(AggregateMetricsCron $aggregateMetricsCron)
{
private State $state;

/**
* @param AggregateMetricsCron $aggregateMetricsCron
* @param State $state
*/
public function __construct(
AggregateMetricsCron $aggregateMetricsCron,
State $state
) {
parent::__construct();

$this->aggregateMetricsCron = $aggregateMetricsCron;
$this->state = $state;
}

protected function configure()
Expand All @@ -35,7 +47,18 @@ protected function configure()

protected function execute(InputInterface $input, OutputInterface $output)
{
try {
$this->state->getAreaCode();
} catch (LocalizedException $exception) {
$this->state->setAreaCode(Area::AREA_CRONTAB);
}

$onlyOption = $input->getOption('only');
$output->write($this->aggregateMetricsCron->executeOnly($onlyOption), true);

if ($onlyOption) {
$output->write($this->aggregateMetricsCron->executeOnly($onlyOption), true);
} else {
$this->aggregateMetricsCron->execute();
}
}
}
3 changes: 3 additions & 0 deletions src/etc/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
<item name="OrderItemAmountAggregator" xsi:type="object">RunAsRoot\PrometheusExporter\Aggregator\Order\OrderItemAmountAggregator</item>
<item name="OrderItemCountAggregator" xsi:type="object">RunAsRoot\PrometheusExporter\Aggregator\Order\OrderItemCountAggregator</item>

<!-- Shipment Aggregator -->
<item name="ShipmentCountAggregator" xsi:type="object">RunAsRoot\PrometheusExporter\Aggregator\Shipment\ShipmentCountAggregator</item>

<!-- Payment Aggregator -->
<item name="ActivePaymentMethodsCountAggregator" xsi:type="object">RunAsRoot\PrometheusExporter\Aggregator\Payment\ActivePaymentMethodsCountAggregator</item>

Expand Down

0 comments on commit 4861c2c

Please sign in to comment.