diff --git a/README.md b/README.md index 61c59f5..ef745d9 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ The following metrics will be collected: | magento_catalog_category_count_total | status, menu_status, store_code | gauge | Count of Categories by store, status and menu status. | | magento_store_count_total | status | gauge | Total count of Stores by status. | | magento_website_count_total | | gauge | Total count websites. | +| magento_products_by_type_count_total | project_type | gauge | Total count of products by type. | ## Add you own Metric diff --git a/Test/Unit/Aggregator/Product/ProductByTypeCountAggregatorTest.php b/Test/Unit/Aggregator/Product/ProductByTypeCountAggregatorTest.php new file mode 100644 index 0000000..56b8ac0 --- /dev/null +++ b/Test/Unit/Aggregator/Product/ProductByTypeCountAggregatorTest.php @@ -0,0 +1,140 @@ +metricRepository = $this->createMock(MetricRepository::class); + $this->searchCriteriaBuilder = $this->createMock(SearchCriteriaBuilder::class); + $this->updateMetricService = $this->createMock(UpdateMetricService::class); + $this->resourceConnection = $this->createMock(ResourceConnection::class); + $this->searchCriteria = $this->createMock(SearchCriteriaInterface::class); + + $this->searchCriteriaBuilder->method('create')->willReturn($this->searchCriteria); + $this->searchCriteriaBuilder + ->expects($this->once()) + ->method('addFilter') + ->with('code', self::METRIC_CODE) + ->willReturnSelf(); + + $metric = $this->createMock(MetricInterface::class); + $metric->expects($this->once()) + ->method('setValue') + ->with('0'); + + $searchResultsMock = $this->createMock(\Magento\Framework\Api\SearchResultsInterface::class); + $searchResultsMock->expects($this->once()) + ->method('getItems') + ->willReturn([$metric]); + + $this->metricRepository->expects($this->once()) + ->method('getList') + ->with($this->searchCriteria) + ->willReturn($searchResultsMock); + + $this->metricRepository->expects($this->once()) + ->method('save') + ->with($metric); + + $this->subject = new ProductByTypeCountAggregator( + $this->metricRepository, + $this->searchCriteriaBuilder, + $this->updateMetricService, + $this->resourceConnection + ); + } + + private function getStatisticData(): array + { + return [ + ['PRODUCT_COUNT' => 111, 'PRODUCT_TYPE' => 'bundle'], + ['PRODUCT_COUNT' => 222, 'PRODUCT_TYPE' => 'configurable'], + ['PRODUCT_COUNT' => 333, 'PRODUCT_TYPE' => 'giftcard'], + ['PRODUCT_COUNT' => 444, 'PRODUCT_TYPE' => 'grouped'], + ['PRODUCT_COUNT' => 555, 'PRODUCT_TYPE' => 'simple'], + ['PRODUCT_COUNT' => 666, 'PRODUCT_TYPE' => 'virtual'] + ]; + } + + private function getSelectMock(): MockObject + { + $select = $this->createMock(Select::class); + $select->expects($this->once()) + ->method('from') + ->with(['p' => self::TABLE_PRODUCT]) + ->willReturn($select); + + $select->expects($this->once())->method('reset')->with(Select::COLUMNS)->willReturn($select); + $select->expects($this->once())->method('group')->with(['p.type_id']); + $select->expects($this->once()) + ->method('columns') + ->with(['PRODUCT_COUNT' => 'COUNT(*)', 'PRODUCT_TYPE' => 'p.type_id']) + ->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() + ->willReturn($connection); + + $connection->expects($this->once())->method('select')->willReturn($select); + $connection->method('getTableName') + ->with('catalog_product_entity') + ->willReturn(self::TABLE_PRODUCT); + $connection->expects($this->once())->method('fetchAll')->with($select)->willReturn($statisticData); + + $params = []; + foreach ($statisticData as $data) { + $params[] = [ + self::METRIC_CODE, + (string)$data['PRODUCT_COUNT'], + ['product_type' => $data['PRODUCT_TYPE']] + ]; + } + + $this->updateMetricService->expects($this->exactly(6)) + ->method('update') + ->withConsecutive(...$params); + + $this->subject->aggregate(); + } +} diff --git a/src/Aggregator/Product/ProductByTypeCountAggregator.php b/src/Aggregator/Product/ProductByTypeCountAggregator.php new file mode 100644 index 0000000..c9a5707 --- /dev/null +++ b/src/Aggregator/Product/ProductByTypeCountAggregator.php @@ -0,0 +1,103 @@ +metricRepository = $metricRepository; + $this->searchCriteriaBuilder = $searchCriteriaBuilder; + $this->updateMetricService = $updateMetricService; + $this->resourceConnection = $resourceConnection; + } + + public function getCode(): string + { + return self::METRIC_CODE; + } + + public function getHelp(): string + { + return 'Magento 2 Product by type Count'; + } + + public function getType(): string + { + return 'gauge'; + } + + public function aggregate(): bool + { + $this->resetMetrics(); + + $connection = $this->resourceConnection->getConnection(); + + $productSearchResult = $connection->fetchAll($this->getSelect($connection)); + + if (count($productSearchResult) === 0) { + return true; + } + + foreach ($productSearchResult as $result) { + $count = $result['PRODUCT_COUNT'] ?? 0; + $productType = $result['PRODUCT_TYPE'] ?? ''; + + $labels = ['product_type' => $productType]; + + $this->updateMetricService->update(self::METRIC_CODE, (string)$count, $labels); + } + + return true; + } + + + protected function resetMetrics(): void + { + $searchCriteriaMetrics = $this->searchCriteriaBuilder->addFilter('code', self::METRIC_CODE)->create(); + $metricsSearchResult = $this->metricRepository->getList($searchCriteriaMetrics); + $metrics = $metricsSearchResult->getItems(); + /** @var MetricInterface $metric */ + foreach ($metrics as $metric) { + $metric->setValue("0"); + $this->metricRepository->save($metric); + } + } + + private function getSelect(AdapterInterface $connection): Select + { + $select = $connection->select(); + + $select->from(['p' => $connection->getTableName('catalog_product_entity')]) + ->reset(Select::COLUMNS)->columns( + [ + 'PRODUCT_COUNT' => 'COUNT(*)', + 'PRODUCT_TYPE' => 'p.type_id' + ] + )->group(['p.type_id']); + + return $select; + } +} diff --git a/src/etc/di.xml b/src/etc/di.xml index 4c95652..f3423af 100644 --- a/src/etc/di.xml +++ b/src/etc/di.xml @@ -49,6 +49,7 @@ RunAsRoot\PrometheusExporter\Aggregator\Product\ProductCountAggregator + RunAsRoot\PrometheusExporter\Aggregator\Product\ProductByTypeCountAggregator RunAsRoot\PrometheusExporter\Aggregator\Shipping\ActiveShippingMethodsCountAggregator