├── .gitignore ├── Api ├── Data │ ├── RedisReportInterface.php │ └── RedisReportSearchResultsInterface.php └── RedisReportRepositoryInterface.php ├── Controller └── Adminhtml │ └── Index │ └── Index.php ├── Cron ├── Clean.php └── Log.php ├── LICENSE ├── Model ├── RedisInfo.php ├── RedisReport.php ├── RedisReportRepository.php └── ResourceModel │ ├── RedisReport.php │ └── RedisReport │ └── Collection.php ├── README.md ├── Scope └── Config.php ├── composer.json ├── etc ├── acl.xml ├── adminhtml │ ├── menu.xml │ ├── routes.xml │ └── system.xml ├── config.xml ├── crontab.xml ├── db_schema.xml ├── di.xml └── module.xml ├── registration.php └── view └── adminhtml ├── layout └── redis_report_index_index.xml ├── templates ├── info │ ├── activity.phtml │ ├── connections.phtml │ ├── databases.phtml │ └── memory.phtml └── wrapper.phtml └── web ├── css └── module.css └── js └── chart.js /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | node_modules/ 3 | -------------------------------------------------------------------------------- /Api/Data/RedisReportInterface.php: -------------------------------------------------------------------------------- 1 | resultPageFactory = $resultPageFactory; 28 | } 29 | 30 | public function execute(): Page 31 | { 32 | $resultPage = $this->resultPageFactory->create(); 33 | $resultPage->getConfig()->getTitle()->prepend(__('Redis Report')); 34 | 35 | return $resultPage; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Cron/Clean.php: -------------------------------------------------------------------------------- 1 | redisReportRepository = $redisReportRepository; 34 | $this->moduleConfig = $moduleConfig; 35 | $this->searchCriteriaBuilderFactory = $searchCriteriaBuilderFactory; 36 | $this->dateTimeFactory = $dateTimeFactory; 37 | } 38 | 39 | /** 40 | * Delete old Redis report data. 41 | * 42 | * @return void 43 | * @throws CouldNotDeleteException 44 | */ 45 | public function execute(): void 46 | { 47 | if (!($days = $this->moduleConfig->getRedisReportLogTruncateDays())) { 48 | return; 49 | } 50 | 51 | $lastException = null; 52 | 53 | /** @var DateTime $cutoff */ 54 | $cutoff = $this->dateTimeFactory->create(date(DateTime::DATETIME_PHP_FORMAT, strtotime("-$days day"))); 55 | 56 | /** @var SearchCriteriaBuilder $searchCriteriaBuilder */ 57 | $searchCriteriaBuilder = $this->searchCriteriaBuilderFactory->create(); 58 | $searchCriteria = $searchCriteriaBuilder->addFilter( 59 | RedisReportInterface::CREATED_AT, 60 | $cutoff, 61 | 'lt' 62 | )->create(); 63 | 64 | /** @var RedisReportInterface[] $redisReportsToDelete */ 65 | $redisReportsToDelete = $this->redisReportRepository->getList($searchCriteria)->getItems(); 66 | 67 | foreach ($redisReportsToDelete as $redisReport) { 68 | try { 69 | $this->redisReportRepository->delete($redisReport); 70 | } catch (CouldNotDeleteException $e) { 71 | $lastException = $e; // store exception as not to stop execution 72 | } 73 | } 74 | 75 | if ($lastException instanceof Exception) { 76 | throw $lastException; // re-throw exception to make noise 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Cron/Log.php: -------------------------------------------------------------------------------- 1 | redisReportRepository = $redisReportRepository; 31 | $this->redisInfo = $redisInfo; 32 | $this->redisReportFactory = $redisReportFactory; 33 | $this->moduleConfig = $moduleConfig; 34 | } 35 | 36 | /** 37 | * Store Redis report data. 38 | * 39 | * @return void 40 | * @throws CouldNotSaveException 41 | */ 42 | public function execute(): void 43 | { 44 | if (!$this->moduleConfig->isRedisReportLoggingCronEnabled()) { 45 | return; 46 | } 47 | 48 | /** @var RedisReportInterface $redisReportModel */ 49 | $redisReportModel = $this->redisReportFactory->create(); 50 | $allRedisData = $this->redisInfo->get(); 51 | 52 | if (array_key_exists('chart-data', $allRedisData)) { 53 | $redisReportModel->setChartData($allRedisData['chart-data']); 54 | unset($allRedisData['chart-data']); 55 | } 56 | 57 | $redisReportModel->setReportData($allRedisData); 58 | $this->redisReportRepository->save($redisReportModel); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 element119 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Model/RedisInfo.php: -------------------------------------------------------------------------------- 1 | cache = $cache; 35 | $this->deploymentConfig = $deploymentConfig; 36 | $this->resourceConnection = $resourceConnection; 37 | $this->redis = $this->cache->getFrontend()->getBackend(); 38 | } 39 | 40 | public function get(): array 41 | { 42 | if (!($redisInfo = $this->getAllRedisInfo())) { 43 | return []; 44 | } 45 | 46 | return [ 47 | 'version' => $redisInfo['redis_version'], 48 | 'databases' => $this->getDatabaseKeyspaceInfo($redisInfo), 49 | 'memory' => [ 50 | 'Used Memory' => $redisInfo['used_memory_human'], 51 | 'Used Memory Peak' => $redisInfo['used_memory_peak_human'], 52 | 'Used Memory Peak Percentage' => $redisInfo['used_memory_peak_perc'], 53 | 'Used Memory Dataset Percentage' => $redisInfo['used_memory_dataset_perc'], 54 | 'Percentage of Keys Used by Magento' => $this->getMagentoKeyUsagePercentage($redisInfo) . '%', 55 | 'Total System Memory' => $redisInfo['total_system_memory_human'], 56 | 'Max. Memory' => $redisInfo['maxmemory_human'], 57 | 'Max. Memory Policy' => $redisInfo['maxmemory_policy'], 58 | ], 59 | 'connections' => [ 60 | 'Cluster Enabled' => $redisInfo['cluster_enabled'], 61 | 'Max. Clients' => $redisInfo['maxclients'], 62 | 'Connected Clients' => $redisInfo['connected_clients'], 63 | 'Cluster Connections' => $redisInfo['cluster_connections'], 64 | 'Rejected Connections' => $redisInfo['rejected_connections'], 65 | ], 66 | 'activity' => [ 67 | 'Uptime in Days' => $redisInfo['uptime_in_days'], 68 | 'Uptime in Seconds' => $redisInfo['uptime_in_seconds'], 69 | 'Keyspace Hits' => $redisInfo['keyspace_hits'], 70 | 'Keyspace Misses' => $redisInfo['keyspace_misses'], 71 | 'Hit Rate' => $this->redis->getHitMissPercentage() . '%', 72 | 'Total Error Replies' => $redisInfo['total_error_replies'], 73 | 'Evicted Keys' => $redisInfo['evicted_keys'], 74 | 'Expired Keys' => $redisInfo['expired_keys'], 75 | 'Used CPU Time (Sys)' => round((float)$redisInfo['used_cpu_sys'], 2) . ' seconds', 76 | 'Used CPU Time (User)' => round((float)$redisInfo['used_cpu_user'], 2) . ' seconds', 77 | 'RDB Last Save Time' => date('r', (int)$redisInfo['rdb_last_save_time']), 78 | 'RDB Changes Since Last Save' => $redisInfo['rdb_changes_since_last_save'], 79 | 'Total Reads Processed' => $redisInfo['total_reads_processed'], 80 | 'Total Writes Processed' => $redisInfo['total_writes_processed'], 81 | ], 82 | 'chart-data' => [ 83 | 'memory' => [ 84 | 'Used Memory' => $redisInfo['used_memory'], 85 | 'Used Memory Peak' => $redisInfo['used_memory_peak'], 86 | 'Used Memory Peak Percentage' => $redisInfo['used_memory_peak_perc'], 87 | 'Used Memory Dataset Percentage' => $redisInfo['used_memory_dataset_perc'], 88 | 'Percentage of Keys Used by Magento' => $this->getMagentoKeyUsagePercentage($redisInfo), 89 | ], 90 | 'activity' => [ 91 | 'Keyspace Hits' => $redisInfo['keyspace_hits'], 92 | 'Keyspace Misses' => $redisInfo['keyspace_misses'], 93 | 'Hit Rate' => $this->redis->getHitMissPercentage(), 94 | 'Total Error Replies' => $redisInfo['total_error_replies'], 95 | 'Evicted Keys' => $redisInfo['evicted_keys'], 96 | 'Expired Keys' => $redisInfo['expired_keys'], 97 | 'Used CPU Time (Sys)' => round((float)$redisInfo['used_cpu_sys'], 2), 98 | 'Used CPU Time (User)' => round((float)$redisInfo['used_cpu_user'], 2), 99 | 'Total Reads Processed' => $redisInfo['total_reads_processed'], 100 | 'Total Writes Processed' => $redisInfo['total_writes_processed'], 101 | ], 102 | ], 103 | ]; 104 | } 105 | 106 | public function getDatabaseKeyspaceInfo(array $redisInfo): array 107 | { 108 | $redisDatabaseInfo = []; 109 | $dbKeys = preg_grep('/^db(\d*)/m', array_keys($redisInfo)); // db0, db1 ... db(n-1), db(n) 110 | 111 | foreach ($dbKeys as $dbKey) { 112 | // keyspace info e.g. key count, expiring key count, and average ttl 113 | $dbInfo = explode(',', $redisInfo[$dbKey]); 114 | 115 | foreach ($dbInfo as $info) { 116 | $data = explode('=', $info); 117 | 118 | array_key_exists($dbKey, $redisDatabaseInfo) 119 | ? $redisDatabaseInfo[$dbKey] += [$data[0] => (int)$data[1]] // append 120 | : $redisDatabaseInfo[$dbKey] = [$data[0] => (int)$data[1]]; // initialise 121 | } 122 | 123 | $avgTtlKey = array_key_last($redisDatabaseInfo[$dbKey]); 124 | $redisDatabaseInfo[$dbKey][$avgTtlKey] = ($redisDatabaseInfo[$dbKey][$avgTtlKey] / 1000) . ' seconds'; 125 | } 126 | 127 | return $redisDatabaseInfo; 128 | } 129 | 130 | public function getMagentoKeyUsagePercentage(array $redisInfo): float 131 | { 132 | $cacheConfig = $this->deploymentConfig->get('cache'); 133 | 134 | if (!isset($cacheConfig['frontend']['default']['id_prefix'])) { 135 | return -1.0; 136 | } 137 | 138 | $allTags = $this->redis->getTags() + $this->redis->getIds(); 139 | $redisKeyPrefix = $cacheConfig['frontend']['default']['id_prefix']; 140 | $tagsWithPrefix = preg_grep('/^' . preg_quote($redisKeyPrefix) . '/m', $allTags); 141 | 142 | return round((count($tagsWithPrefix) / count($allTags)) * 100, 2); 143 | } 144 | 145 | /** 146 | * Return historic Redis data, keyed by creation timestamp. 147 | * 148 | * @return array 149 | * @throws Zend_Db_Statement_Exception 150 | */ 151 | public function getHistoricRedisReportData(): array 152 | { 153 | $reportData = []; 154 | $connection = $this->resourceConnection->getConnection(); 155 | $redisReportSelect = $connection->select()->from( 156 | $this->resourceConnection->getTableName(RedisReportRepositoryInterface::MAIN_TABLE), 157 | [ 158 | RedisReportInterface::REPORT_DATA, 159 | RedisReportInterface::CHART_DATA, 160 | RedisReportInterface::CREATED_AT, 161 | ] 162 | ); 163 | 164 | foreach ($connection->query($redisReportSelect)->fetchAll() as $dbData) { 165 | $reportData[$dbData[RedisReportInterface::CREATED_AT]] = json_decode( 166 | $dbData[RedisReportInterface::REPORT_DATA], true 167 | ); 168 | 169 | if ($dbData[RedisReportInterface::CHART_DATA]) { 170 | $chartData = json_decode($dbData[RedisReportInterface::CHART_DATA], true); 171 | $chartData[RedisReportInterface::CREATED_AT] = $dbData[RedisReportInterface::CREATED_AT]; 172 | 173 | $reportData[$dbData[RedisReportInterface::CREATED_AT]][RedisReportInterface::CHART_DATA] = $chartData; 174 | } 175 | } 176 | 177 | return $reportData; 178 | } 179 | 180 | /** 181 | * Get all Redis information. 182 | * 183 | * This function exists solely to ease extensibility. 184 | * 185 | * @link https://redis.io/commands/info/ 186 | * 187 | * @return array 188 | */ 189 | public function getAllRedisInfo(): array 190 | { 191 | return $this->redis instanceof Cm_Cache_Backend_Redis && method_exists($this->redis, 'getInfo') 192 | ? $this->redis->getInfo() 193 | : []; 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /Model/RedisReport.php: -------------------------------------------------------------------------------- 1 | _init(RedisReportResourceModel::class); 22 | } 23 | 24 | /** 25 | * @inheritDoc 26 | */ 27 | public function getEntityId(): int 28 | { 29 | return (int)$this->getData(self::ENTITY_ID); 30 | } 31 | 32 | /** 33 | * @inheritDoc 34 | */ 35 | public function setEntityId($entityId): self 36 | { 37 | return $this->setData(self::ENTITY_ID, $entityId); 38 | } 39 | 40 | /** 41 | * @inheritDoc 42 | */ 43 | public function getReportData(): array 44 | { 45 | return $this->getData(json_decode(self::REPORT_DATA)); 46 | } 47 | 48 | /** 49 | * @inheritDoc 50 | */ 51 | public function setReportData(array $reportData): RedisReportInterface 52 | { 53 | return $this->setData(self::REPORT_DATA, json_encode($reportData)); 54 | } 55 | 56 | /** 57 | * @inheritDoc 58 | */ 59 | public function getChartData(): array 60 | { 61 | return $this->getData(json_decode(self::CHART_DATA)); 62 | } 63 | 64 | /** 65 | * @inheritDoc 66 | */ 67 | public function setChartData(array $chartData): RedisReportInterface 68 | { 69 | return $this->setData(self::CHART_DATA, json_encode($chartData)); 70 | } 71 | 72 | /** 73 | * @inheritDoc 74 | */ 75 | public function getCreatedAt(): string 76 | { 77 | return $this->getData(self::CREATED_AT); 78 | } 79 | 80 | /** 81 | * @inheritDoc 82 | */ 83 | public function setCreatedAt(string $createdAt): RedisReportInterface 84 | { 85 | return $this->setData(self::CREATED_AT, $createdAt); 86 | } 87 | 88 | /** 89 | * @inheritDoc 90 | */ 91 | public function getUpdatedAt(): string 92 | { 93 | return $this->getData(self::UPDATED_AT); 94 | } 95 | 96 | /** 97 | * @inheritDoc 98 | */ 99 | public function setUpdatedAt(string $updatedAt): RedisReportInterface 100 | { 101 | return $this->setData(self::UPDATED_AT, $updatedAt); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Model/RedisReportRepository.php: -------------------------------------------------------------------------------- 1 | redisReportCollectionFactory = $redisReportCollectionFactory; 40 | $this->redisReportFactory = $redisReportFactory; 41 | $this->resource = $resource; 42 | $this->searchResultsFactory = $searchResultsFactory; 43 | $this->collectionProcessor = $collectionProcessor; 44 | } 45 | 46 | /** 47 | * @inheritDoc 48 | */ 49 | public function save(RedisReportInterface $redisReport): RedisReportInterface 50 | { 51 | try { 52 | $this->resource->save($redisReport); 53 | } catch (Exception $e) { 54 | throw new CouldNotSaveException(__('Could not save the report: %1', $e->getMessage())); 55 | } 56 | 57 | return $redisReport; 58 | } 59 | 60 | /** 61 | * @inheritDoc 62 | */ 63 | public function getById($redisReportId): RedisReportInterface 64 | { 65 | $redisReport = $this->redisReportFactory->create(); 66 | $this->resource->load($redisReport, $redisReportId); 67 | 68 | if (!$redisReport->getId()) { 69 | throw new NoSuchEntityException(__('Redis report with entity ID "%1" does not exist.', $redisReportId)); 70 | } 71 | 72 | return $redisReport; 73 | } 74 | 75 | /** 76 | * @inheritDoc 77 | */ 78 | public function getList(SearchCriteriaInterface $searchCriteria): SearchResults 79 | { 80 | $collection = $this->redisReportCollectionFactory->create(); 81 | 82 | $this->collectionProcessor->process($searchCriteria, $collection); 83 | 84 | $searchResults = $this->searchResultsFactory->create(); 85 | $searchResults->setSearchCriteria($searchCriteria); 86 | 87 | $items = []; 88 | 89 | foreach ($collection as $redisReport) { 90 | $items[] = $redisReport; 91 | } 92 | 93 | $searchResults->setItems($items); 94 | $searchResults->setTotalCount($collection->getSize()); 95 | 96 | return $searchResults; 97 | } 98 | 99 | /** 100 | * @inheritDoc 101 | */ 102 | public function delete(RedisReportInterface $redisReport): bool 103 | { 104 | try { 105 | /** @var RedisReportInterface $redisReportModel */ 106 | $redisReportModel = $this->redisReportFactory->create(); 107 | 108 | $this->resource->load($redisReportModel, $redisReport->getEntityId()); 109 | $this->resource->delete($redisReportModel); 110 | } catch (Exception $e) { 111 | throw new CouldNotDeleteException(__('Could not delete the Redis report with ID: %1', $e->getMessage())); 112 | } 113 | 114 | return true; 115 | } 116 | 117 | /** 118 | * @inheritDoc 119 | */ 120 | public function deleteById($redisReportId): bool 121 | { 122 | return $this->delete($this->getById($redisReportId)); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /Model/ResourceModel/RedisReport.php: -------------------------------------------------------------------------------- 1 | _init(RedisReportRepositoryInterface::MAIN_TABLE, RedisReportInterface::ENTITY_ID); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Model/ResourceModel/RedisReport/Collection.php: -------------------------------------------------------------------------------- 1 | _init(RedisReport::class, RedisReportResourceModel::class); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 |
6 | 7 |

element119 | Admin Redis Report

8 | 9 | ## 📝 Features 10 | ✔️ See a snapshot of the health of Redis from the comfort of the Magento admin 11 | 12 | ✔️ Visualise historic Redis health statistics 13 | 14 | ✔️ Supports Magento Open Source, Adobe Commerce, and Mage-OS 15 | 16 | ✔️ Built in accordance with Magento best practises 17 | 18 | ✔️ Dedicated module configuration section and custom admin user controls 19 | 20 | ✔️ Seamless integration with Magento 21 | 22 | ✔️ Built with developers and extensibility in mind to make customisations as easy as possible 23 | 24 | ✔️ Installable via Composer 25 | 26 | ✔️ Theme agnostic 27 | 28 | ### Upcoming 29 | ⏳ Ability to filter historic charts by date range 30 | 31 |
32 | 33 | ## ⛔️ Incompatibilities 34 | 35 | > [!CAUTION] 36 | > This module is not compatible with Magento instances that utilise the Redis L2 cache and/or the 37 | > `Magento\Framework\Cache\Backend\RemoteSynchronizedCache` class for the Redis backend cache. 38 | > 39 | > More information is available in the Magento documentation: 40 | > - [Redis L2 Cache](https://experienceleague.adobe.com/en/docs/commerce-operations/implementation-playbook/best-practices/planning/redis-service-configuration#configure-redis-l2-cache) 41 | > - [Available Redis Backend Cache Classes](https://experienceleague.adobe.com/en/docs/commerce-cloud-service/user-guide/configure/env/stage/variables-deploy#redis_backend) 42 | 43 |
44 | 45 | ## 🔌 Installation 46 | Run the following command to *install* this module: 47 | ```bash 48 | composer require element119/module-admin-redis-report 49 | php bin/magento setup:upgrade 50 | ``` 51 | 52 |
53 | 54 | ## ⏫ Updating 55 | Run the following command to *update* this module: 56 | ```bash 57 | composer update element119/module-admin-redis-report 58 | php bin/magento setup:upgrade 59 | ``` 60 | 61 |
62 | 63 | ## ❌ Uninstallation 64 | Run the following command to *uninstall* this module: 65 | ```bash 66 | composer remove element119/module-admin-redis-report 67 | php bin/magento setup:upgrade 68 | ``` 69 | 70 |
71 | 72 | ## 📚 User Guide 73 | Configuration for this module can be found in the Magento admin under `Stores -> Settings -> Configuration -> Advanced 74 | -> System -> Redis Report`. 75 | 76 |
77 | 78 | ### Redis Report 79 | The Redis information can be found in the admin under `System -> Tools -> Redis Report`. 80 | 81 |
82 | 83 | ### Enable/Disable Historic Data 84 | The periodic capture of Redis information can be disabled by setting this option to `No`. This is set to `Yes` by 85 | default. 86 | 87 |
88 | 89 | ### Historic Data Retention Period 90 | The value specified here determines how long Magento will store historic Redis report data, measured in days. 91 | An empty value means data will be kept indefinitely. 92 | 93 | ## 📸 Screenshots & GIFs 94 | ### Admin Configuration 95 | ![admin-config](https://github.com/element119/module-admin-redis-report/assets/40261741/853aea10-d995-4cb1-a4d7-9dc7cdccafd3) 96 | 97 |
98 | 99 | ### Admin Report 100 | ![admin-report](https://github.com/element119/module-admin-redis-report/assets/40261741/5015905d-fb0d-40fe-99f5-b5ec29b207ee) 101 | -------------------------------------------------------------------------------- /Scope/Config.php: -------------------------------------------------------------------------------- 1 | scopeConfig = $scopeConfig; 23 | } 24 | 25 | public function isRedisReportLoggingCronEnabled(): bool 26 | { 27 | return $this->scopeConfig->isSetFlag(self::XML_PATH_LOG_CRON_ENABLED); 28 | } 29 | 30 | public function getRedisReportLogTruncateDays(): int 31 | { 32 | return (int)$this->scopeConfig->getValue(self::XML_PATH_LOG_TRUNCATE_DAYS); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "element119/module-admin-redis-report", 3 | "type": "magento2-module", 4 | "description": "A Magento 2 module that displays Redis information in the admin.", 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "element119", 9 | "email": "hello@element119.co.uk" 10 | } 11 | ], 12 | "require": { 13 | "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", 14 | "magento/module-backend": "*", 15 | "ext-json": "*" 16 | }, 17 | "suggest": { 18 | "ethanyehuda/magento2-cronjobmanager": "A module for managing scheduled cron jobs from magento's admin panel" 19 | }, 20 | "autoload": { 21 | "psr-4": { 22 | "Element119\\AdminRedisReport\\": "" 23 | }, 24 | "files": [ 25 | "registration.php" 26 | ] 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /etc/acl.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /etc/adminhtml/menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 11 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /etc/adminhtml/routes.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /etc/adminhtml/system.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 11 |
12 | 19 | 20 | 28 | 29 | The default schedule is every 30 minutes but this may have been changed. 30 | Magento\Config\Model\Config\Source\Yesno 31 | 32 | 40 | 41 | Absence of a value means historic report data will not be deleted. 42 | integer validate-digits validate-not-negative-number 43 | 44 | 1 45 | 46 | 47 | 48 |
49 |
50 |
51 | -------------------------------------------------------------------------------- /etc/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 11 | 12 | 13 | 1 14 | 28 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /etc/crontab.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 11 | 14 | 0 * * * * 15 | 16 | 19 | 0 1 * * * 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /etc/db_schema.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 11 | 17 | 21 | 25 | 31 | 37 | 38 | 39 | 40 |
41 |
42 | -------------------------------------------------------------------------------- /etc/di.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 11 | 13 | 15 | 17 | 18 | -------------------------------------------------------------------------------- /etc/module.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /registration.php: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | Element119\AdminRedisReport\Model\RedisInfo 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /view/adminhtml/templates/info/activity.phtml: -------------------------------------------------------------------------------- 1 | getData('redis_info'); 18 | $historicData = $block->getData('historic_redis_data'); 19 | $historicChartData = array_column($historicData, RedisReportInterface::CHART_DATA); 20 | ?> 21 |
22 |

escapeHtml(__('Activity')); ?>

23 | 24 |
25 |
26 |

escapeHtml(__('Live Data Snapshot')); ?>

27 |
    28 | $value): ?> 29 |
  • 30 | escapeHtml(__($key)); ?>: 31 | escapeHtml($value); ?> 32 |
  • 33 | 34 |
35 |
36 | 37 | 38 |
39 |

escapeHtml(__('History')); ?>

40 |
41 | 44 | 123 |
124 |
125 | 128 | 172 |
173 |
174 | 177 | 229 |
230 |
231 | 234 | 286 |
287 |
288 | 289 |
290 |
291 | -------------------------------------------------------------------------------- /view/adminhtml/templates/info/connections.phtml: -------------------------------------------------------------------------------- 1 | getData('redis_info'); 17 | $historicData = $block->getData('historic_redis_data'); 18 | $connectionsHistory = array_column($historicData, 'connections'); 19 | ?> 20 |
21 |

escapeHtml(__('Connections')); ?>

22 | 23 |
24 |
25 |

escapeHtml(__('Live Data Snapshot')); ?>

26 |
    27 | $value): ?> 28 |
  • 29 | escapeHtml(__($key)); ?>: 30 | escapeHtml($value); ?> 31 |
  • 32 | 33 |
34 |
35 | 36 | 37 |
38 |

escapeHtml(__('History')); ?>

39 |
40 | 43 | 99 |
100 |
101 | 102 |
103 |
104 | -------------------------------------------------------------------------------- /view/adminhtml/templates/info/databases.phtml: -------------------------------------------------------------------------------- 1 | getData('redis_info'); 17 | $historicData = $block->getData('historic_redis_data'); 18 | $databasesHistory = array_column($historicData, 'databases'); 19 | ?> 20 |
21 |

escapeHtml(__('Database(s)')); ?>

22 | 23 |
24 | $data): ?> 25 |
26 |
27 |

escapeHtml(__('Live Data Snapshot')); ?>

28 | escapeHtml($dbNumber); ?> 29 |
    30 | $value): ?> 31 |
  • 32 | escapeHtml(ucwords(str_replace('_', ' ', $key))); ?>: 33 | escapeHtml($value); ?> 34 |
  • 35 | 36 |
37 |
38 | 39 | 42 |
43 |
44 |

escapeHtml(__('History')); ?>

45 | 50 | 90 |
91 |
92 | 95 | 140 |
141 |
142 | 143 |
144 | 145 |
146 |
147 | -------------------------------------------------------------------------------- /view/adminhtml/templates/info/memory.phtml: -------------------------------------------------------------------------------- 1 | getData('redis_info'); 18 | $historicData = $block->getData('historic_redis_data'); 19 | $historicChartData = array_column($historicData, RedisReportInterface::CHART_DATA); 20 | ?> 21 |
22 |

escapeHtml(__('Memory')); ?>

23 | 24 |
25 |
26 |

escapeHtml(__('Live Data Snapshot')); ?>

27 |
    28 | $value): ?> 29 |
  • 30 | escapeHtml(__($key)); ?>: 31 | escapeHtml($value); ?> 32 |
  • 33 | 34 |
35 |
36 | 37 | 38 |
39 |

escapeHtml(__('History')); ?>

40 |
41 | 44 | 100 |
101 |
102 | 105 | 181 |
182 |
183 | 184 |
185 |
186 | -------------------------------------------------------------------------------- /view/adminhtml/templates/wrapper.phtml: -------------------------------------------------------------------------------- 1 | getData('redis_info_view_model'); 16 | $redisInfo = $redisInfoViewModel->get(); 17 | $redisHistory = $redisInfoViewModel->getHistoricRedisReportData(); 18 | ?> 19 | 20 | escapeHtml(__('Could not retrieve Redis information at this time.')); ?> 21 | 22 | 23 | getChildNames() as $childName): ?> 24 | getChildBlock($childName) 25 | ->setData('redis_info', $redisInfo) 26 | ->setData('historic_redis_data', $redisHistory); ?> 27 | 28 | 29 |
30 |
31 | 32 | escapeHtml(__('Redis Info Command Documentation')); ?> 33 | 34 | 35 | 36 | escapeHtml(__('Redis Version: %1', $redisInfo['version']), ['b']); ?> 37 | 38 |
39 | 40 |
41 | getChildHtml(); ?> 42 |
43 |
44 | 45 | -------------------------------------------------------------------------------- /view/adminhtml/web/css/module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © element119. All rights reserved. 3 | * See LICENCE.txt for licence details. 4 | */ 5 | /* Before Section Grid */ 6 | #misc-info { 7 | display: flex; 8 | flex-direction: column; 9 | margin-bottom: 2rem; 10 | } 11 | 12 | section { 13 | padding: 2rem 0; 14 | } 15 | 16 | h2 { 17 | font-weight: bold; 18 | padding-bottom: 1rem; 19 | } 20 | 21 | .data-list { 22 | list-style-type: none; 23 | } 24 | 25 | h2, 26 | .data-list { 27 | margin: 0; 28 | } 29 | 30 | #databases .database-info, 31 | #memory .memory-wrapper, 32 | #activity .activity-wrapper, 33 | #connections .connections-wrapper { 34 | border: 2px solid #000000; 35 | border-radius: 2rem; 36 | display: flex; 37 | margin-bottom: 3rem; 38 | padding: 2rem; 39 | } 40 | 41 | .database-data, 42 | .memory-data, 43 | .activity-data, 44 | .connections-data { 45 | padding-right: 3rem; 46 | } 47 | 48 | .database-charts, 49 | .memory-charts, 50 | .activity-charts, 51 | .connections-charts { 52 | border-left: 1px dashed black; 53 | padding-left: 3rem; 54 | } 55 | 56 | .database-chart, 57 | .memory-chart, 58 | .activity-chart, 59 | .connections-chart { 60 | padding-bottom: 5rem; 61 | } 62 | 63 | #databases li { 64 | padding-left: 2rem; 65 | } 66 | -------------------------------------------------------------------------------- /view/adminhtml/web/js/chart.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © element119. All rights reserved. 3 | * See LICENCE.txt for licence details. 4 | */ 5 | define([ 6 | 'chartJs', 7 | ], function (Chart) { 8 | 'use strict'; 9 | 10 | return function (config, element) { 11 | new Chart(element, { 12 | type: config.type, 13 | data: config.data, 14 | options: config.options, 15 | }); 16 | }; 17 | }); 18 | --------------------------------------------------------------------------------