From eb459e386359a0fdc16bde52533579317f8c0d21 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 17 May 2022 13:56:42 +0100 Subject: [PATCH 01/18] Add New Methods (See Desc) + Added getCPUCores() + Added UNIX Helper functions + Added getCPUUtilisation + Added getMemoryTotal() + Added getMemoryFree() + Added getDiskTotal() + Added getDiskFree() + Added getDiskStats() + Added getIOUsage() + Added getNetworkUsage() Most of these methods are currently Linux only --- src/System/System.php | 374 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 374 insertions(+) diff --git a/src/System/System.php b/src/System/System.php index 6131249..f3e9f35 100644 --- a/src/System/System.php +++ b/src/System/System.php @@ -14,6 +14,33 @@ class System private const RegExARM = '/(aarch*|arm*)/'; private const RegExPPC = '/(ppc*)/'; + /** + * A list of Linux Disks that are not considered valid + * These are usually virtual drives or other non-physical devices such as loopback or ram. + * + * This list is ran through a contains, meaning for example if 'loop' was in the list, + * A 'loop0' interface would be considered invalid and not computed. + */ + private const InvalidDisks = [ + 'loop', + 'ram', + ]; + + /** + * A list of Linux Network Interfaces that are not considered valid + * These are usually virtual interfaces created by tools such as Docker or VirtualBox + * + * This list is ran through a contains, meaning for example if 'vboxnet' was in the list, + * A 'vboxnet0' interface would be considered invalid and not computed. + */ + private const InvalidNetInterfaces = [ + 'veth', + 'docker', + 'lo', + 'tun', + 'vboxnet' + ]; + /** * Returns the system's OS. * @return string @@ -128,4 +155,351 @@ static public function isArch(string $arch): bool break; } } + + /** + * Gets the system's total amount of CPU cores. + * + * @return int + * + * @throws Exception + */ + static public function getCPUCores(): int + { + switch (self::getOS()) { + case 'Linux': + $cpuinfo = file_get_contents('/proc/cpuinfo'); + preg_match_all('/^processor/m', $cpuinfo, $matches); + return count($matches[0]); + case 'Darwin': + return shell_exec('sysctl -n hw.ncpu'); + case 'Windows': + return shell_exec('wmic cpu get NumberOfCores'); + default: + throw new Exception(self::getOS() . " not supported."); + } + } + + /** + * Helper function to read a Linux System's /proc/stat data and convert it into an array. + * + * @return array + */ + static private function getProcStatData(): array + { + $data = []; + + $totalCPUExists = false; + + $cpustats = file_get_contents('/proc/stat'); + + $cpus = explode("\n", $cpustats); + + // Remove non-CPU lines + $cpus = array_filter($cpus, function ($cpu) { + return preg_match('/^cpu[0-999]/', $cpu); + }); + + foreach ($cpus as $cpu) { + $cpu = explode(' ', $cpu); + + // get CPU number + $cpuNumber = substr($cpu[0], 3); + + if ($cpu[0] === 'cpu') { + $totalCPUExists = true; + $cpuNumber = 'total'; + } + + $data[$cpuNumber]['user'] = $cpu[1]; + $data[$cpuNumber]['nice'] = $cpu[2]; + $data[$cpuNumber]['system'] = $cpu[3]; + $data[$cpuNumber]['idle'] = $cpu[4]; + $data[$cpuNumber]['iowait'] = $cpu[5]; + $data[$cpuNumber]['irq'] = $cpu[6]; + $data[$cpuNumber]['softirq'] = $cpu[7]; + + // These might not exist on older kernels. + $data[$cpuNumber]['steal'] = isset($cpu[8]) ? $cpu[8] : 0; + $data[$cpuNumber]['guest'] = isset($cpu[9]) ? $cpu[9] : 0; + } + + if (!$totalCPUExists) { + // Combine all values + $data['total'] = [ + 'user' => 0, + 'nice' => 0, + 'system' => 0, + 'idle' => 0, + 'iowait' => 0, + 'irq' => 0, + 'softirq' => 0, + 'steal' => 0, + 'guest' => 0 + ]; + + foreach ($data as $cpu) { + $data['total']['user'] += $cpu['user']; + $data['total']['nice'] += $cpu['nice']; + $data['total']['system'] += $cpu['system']; + $data['total']['idle'] += $cpu['idle']; + $data['total']['iowait'] += $cpu['iowait']; + $data['total']['irq'] += $cpu['irq']; + $data['total']['softirq'] += $cpu['softirq']; + $data['total']['steal'] += $cpu['steal']; + $data['total']['guest'] += $cpu['guest']; + } + } + + return $data; + } + + /** + * Gets the current usage of a core as a percentage. Passing 0 will return the usage of all cores combined. + * + * @param int $core + * + * @return int + * + * @throws Exception + */ + static public function getCPUUtilisation(int $id = 0): int + { + switch (self::getOS()) { + case 'Linux': + $cpuNow = self::getProcStatData(); + $i = 0; + + $data = []; + + foreach ($cpuNow as $cpu) { + // Check if this is the total CPU + $cpuTotal = $cpu['user'] + $cpu['nice'] + $cpu['system'] + $cpu['idle'] + $cpu['iowait'] + $cpu['irq'] + $cpu['softirq'] + $cpu['steal']; + + $cpuIdle = $cpu['idle']; + + $idleDelta = $cpuIdle - (isset($lastData[$i]) ? $lastData[$i]['idle'] : 0); + + $totalDelta = $cpuTotal - (isset($lastData[$i]) ? $lastData[$i]['total'] : 0); + + $lastData[$i]['total'] = $cpuTotal; + $lastData[$i]['idle'] = $cpuIdle; + + $result = (1.0 - ($idleDelta / $totalDelta)) * 100; + + $data[$i] = $result; + + $i++; + } + + if ($id === 0) { + return array_sum($data); + } else { + return $data[$id]; + } + } + } + + /** + * Returns the total amount of RAM available on the system as Megabytes. + * + * @return int + * + * @throws Exception + */ + static public function getMemoryTotal(): int + { + switch (self::getOS()) { + case 'Linux': + $meminfo = file_get_contents('/proc/meminfo'); + preg_match('/MemTotal:\s+(\d+)/', $meminfo, $matches); + return intval(intval($matches[1]) / 1024); + break; + case 'Darwin': + return intval((intval(shell_exec('sysctl -n hw.memsize'))) / 1024 / 1024); + } + } + + /** + * Returns the total amount of Free RAM available on the system as Megabytes. + * + * @return int + * + * @throws Exception + */ + static public function getMemoryFree(): int + { + switch (self::getOS()) { + case 'Linux': + $meminfo = file_get_contents('/proc/meminfo'); + preg_match('/MemFree:\s+(\d+)/', $meminfo, $matches); + return ($matches[1] / 1024); + case 'Darwin': + return intval(intval(shell_exec('sysctl -n vm.page_free_count')) / 1024 / 1024); + } + } + + /** + * Returns the total amount of Disk space on the system as Megabytes. + * + * @return int + * + * @throws Exception + */ + static public function getDiskTotal(): int + { + $totalSpace = disk_total_space(__DIR__); + + if ($totalSpace === false) { + throw new Exception('Unable to get disk space'); + } + + return intval($totalSpace / 1024 / 1024); + } + + /** + * Returns the total amount of Disk space free on the system as Megabytes. + * + * @return int + * + * @throws Exception + */ + static public function getDiskFree(): int + { + $totalSpace = disk_free_space(__DIR__); + + if ($totalSpace === false) { + throw new Exception('Unable to get free disk space'); + } + + return intval($totalSpace / 1024 / 1024); + } + + /** + * Helper function to read a Linux System's /proc/diskstats data and convert it into an array. + * + * @return array + */ + static private function getDiskStats() + { + // Read /proc/diskstats + $diskstats = file_get_contents('/proc/diskstats'); + + // Split the data + $diskstats = explode("\n", $diskstats); + + // Remove excess spaces + $diskstats = array_map(function ($data) { + return preg_replace('/\s+/', ' ', trim($data)); + }, $diskstats); + + // Remove empty lines + $diskstats = array_filter($diskstats, function ($data) { + return !empty($data); + }); + + $data = []; + foreach ($diskstats as $disk) { + // Breakdown the data + $disk = explode(' ', $disk); + + $data[$disk[2]] = $disk; + } + + return $data; + } + + /** + * Returns an array of all the available storage devices on the system containing + * the current read and write usage in Megabytes. + * There is also a ['total'] key that contains the total amount of read and write usage. + * + * @return array + * + * @throws Exception + */ + static public function getIOUsage(): array + { + $diskStat = self::getDiskStats(); + sleep(1); + $diskStat2 = self::getDiskStats(); + + // Remove invalid disks + $diskStat = array_filter($diskStat, function ($disk) { + foreach (self::InvalidDisks as $filter) { + if (str_contains($disk[2], $filter)) { + return false; + } + } + + return true; + }); + + $diskStat2 = array_filter($diskStat2, function ($disk) { + foreach (self::InvalidDisks as $filter) { + if (str_contains($disk[2], $filter)) { + return false; + } + } + + return true; + }); + + $stats = []; + + // Compute Delta + foreach ($diskStat as $key => $disk) { + $stats[$key]['read'] = (((intval($diskStat2[$key][5]) - intval($disk[5])) * 512) / 1048576); + $stats[$key]['write'] = (((intval($diskStat2[$key][9]) - intval($disk[9])) * 512) / 1048576); + } + + $stats['total']['read'] = array_sum(array_column($stats, 'read')); + $stats['total']['write'] = array_sum(array_column($stats, 'write')); + + return $stats; + } + + /** + * Returns an array of all the available network interfaces on the system containing + * the current download and upload usage in Megabytes. + * There is also a ['total'] key that contains the total amount of download and upload + * + * @return array + * + * @throws Exception + */ + static public function getNetworkUsage(): array + { + // Create a list of interfaces + $interfaces = scandir('/sys/class/net', SCANDIR_SORT_NONE); + + // Remove all unwanted interfaces + $interfaces = array_filter($interfaces, function ($interface) { + foreach (self::InvalidDisks as $filter) { + if (str_contains($interface, $filter)) { + return false; + } + } + + return true; + }); + + // Get the total IO Usage + $IOUsage = []; + + foreach ($interfaces as $interface) { + $tx1 = intval(file_get_contents('/sys/class/net/' . $interface . '/statistics/tx_bytes')); + $rx1 = intval(file_get_contents('/sys/class/net/' . $interface . '/statistics/rx_bytes')); + sleep(1); + $tx2 = intval(file_get_contents('/sys/class/net/' . $interface . '/statistics/tx_bytes')); + $rx2 = intval(file_get_contents('/sys/class/net/' . $interface . '/statistics/rx_bytes')); + + $IOUsage[$interface]['download'] = round(($rx2 - $rx1) / 1048576, 2); + $IOUsage[$interface]['upload'] = round(($tx2 - $tx1) / 1048576, 2); + } + + $IOUsage['total']['download'] = array_sum(array_column($IOUsage, 'download')); + $IOUsage['total']['upload'] = array_sum(array_column($IOUsage, 'upload')); + + return $IOUsage; + } } From 2900fbe45489447298da2181ac6cad0f4747c1b4 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 17 May 2022 16:33:24 +0100 Subject: [PATCH 02/18] Update System.php --- src/System/System.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/System/System.php b/src/System/System.php index f3e9f35..1b36f9f 100644 --- a/src/System/System.php +++ b/src/System/System.php @@ -171,9 +171,9 @@ static public function getCPUCores(): int preg_match_all('/^processor/m', $cpuinfo, $matches); return count($matches[0]); case 'Darwin': - return shell_exec('sysctl -n hw.ncpu'); + return intval(shell_exec('sysctl -n hw.ncpu')); case 'Windows': - return shell_exec('wmic cpu get NumberOfCores'); + return intval(shell_exec('wmic cpu get NumberOfCores')); default: throw new Exception(self::getOS() . " not supported."); } @@ -389,7 +389,7 @@ static private function getDiskStats() // Remove excess spaces $diskstats = array_map(function ($data) { - return preg_replace('/\s+/', ' ', trim($data)); + return preg_replace('/\t+/', ' ', trim($data)); }, $diskstats); // Remove empty lines From 30140434dab094f3b4aa0496626dc7aacae5d159 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 30 May 2022 11:25:47 +0100 Subject: [PATCH 03/18] Add Tests and fix invalid filter list being used --- src/System/System.php | 18 +++++++--- tests/System/SystemTest.php | 65 +++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 5 deletions(-) diff --git a/src/System/System.php b/src/System/System.php index 1b36f9f..e0948a0 100644 --- a/src/System/System.php +++ b/src/System/System.php @@ -38,7 +38,8 @@ class System 'docker', 'lo', 'tun', - 'vboxnet' + 'vboxnet', + '.' ]; /** @@ -292,10 +293,12 @@ static public function getCPUUtilisation(int $id = 0): int } if ($id === 0) { - return array_sum($data); + return intval(array_sum($data)); } else { return $data[$id]; } + default: + throw new Exception(self::getOS() . " not supported."); } } @@ -316,7 +319,10 @@ static public function getMemoryTotal(): int break; case 'Darwin': return intval((intval(shell_exec('sysctl -n hw.memsize'))) / 1024 / 1024); - } + break; + default: + throw new Exception(self::getOS() . " not supported."); + } } /** @@ -332,9 +338,11 @@ static public function getMemoryFree(): int case 'Linux': $meminfo = file_get_contents('/proc/meminfo'); preg_match('/MemFree:\s+(\d+)/', $meminfo, $matches); - return ($matches[1] / 1024); + return intval($matches[1] / 1024); case 'Darwin': return intval(intval(shell_exec('sysctl -n vm.page_free_count')) / 1024 / 1024); + default: + throw new Exception(self::getOS() . " not supported."); } } @@ -474,7 +482,7 @@ static public function getNetworkUsage(): array // Remove all unwanted interfaces $interfaces = array_filter($interfaces, function ($interface) { - foreach (self::InvalidDisks as $filter) { + foreach (self::InvalidNetInterfaces as $filter) { if (str_contains($interface, $filter)) { return false; } diff --git a/tests/System/SystemTest.php b/tests/System/SystemTest.php index 8504ae1..0bf80a9 100644 --- a/tests/System/SystemTest.php +++ b/tests/System/SystemTest.php @@ -41,4 +41,69 @@ public function testOs() $this->expectException("Exception"); System::isArch("throw"); } + + public function testGetCPUCores() + { + $this->assertIsInt(System::getCPUCores()); + } + + public function testGetDiskTotal() + { + $this->assertIsInt(System::getDiskTotal()); + } + + public function testGetDiskFree() + { + $this->assertIsInt(System::getDiskFree()); + } + + // Methods only implemented for Linux + public function testGetCPUUtilisation() + { + if (System::getOS() === 'Linux') { + $this->assertIsInt(System::getCPUUtilisation()); + } else { + $this->expectException("Exception"); + System::getCPUUtilisation(); + } + } + + public function testGetMemoryTotal() + { + if (System::getOS() === 'Linux') { + $this->assertIsInt(System::getMemoryTotal()); + } else { + $this->expectException("Exception"); + System::getMemoryTotal(); + } + } + + public function testGetMemoryFree() + { + if (System::getOS() === 'Linux') { + $this->assertIsInt(System::getMemoryFree()); + } else { + $this->expectException("Exception"); + System::getMemoryFree(); + } + } + + public function testGetIOUsage() + { + if (System::getOS() === 'Linux') { + $this->assertIsArray(System::getIOUsage()); + } else { + $this->expectException("Exception"); + System::getIOUsage(); + } + } + + public function testGetNetworkUsage() { + if (System::getOS() === 'Linux') { + $this->assertIsArray(System::getNetworkUsage()); + } else { + $this->expectException("Exception"); + System::getNetworkUsage(); + } + } } From b553066849957fa577a405abc407420527b067a4 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 30 May 2022 11:56:55 +0100 Subject: [PATCH 04/18] Update System.php --- src/System/System.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/System/System.php b/src/System/System.php index e0948a0..cf3a9a6 100644 --- a/src/System/System.php +++ b/src/System/System.php @@ -39,7 +39,8 @@ class System 'lo', 'tun', 'vboxnet', - '.' + '.', + 'bonding_masters' ]; /** From 8629080df0f2239f19f36677cb5486bddd9aae9f Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 21 Jun 2022 14:01:56 +0100 Subject: [PATCH 05/18] Update System.php --- src/System/System.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/System/System.php b/src/System/System.php index cf3a9a6..36ffbe0 100644 --- a/src/System/System.php +++ b/src/System/System.php @@ -422,14 +422,15 @@ static private function getDiskStats() * the current read and write usage in Megabytes. * There is also a ['total'] key that contains the total amount of read and write usage. * + * @param int $duration * @return array * * @throws Exception */ - static public function getIOUsage(): array + static public function getIOUsage($duration = 1): array { $diskStat = self::getDiskStats(); - sleep(1); + sleep($duration); $diskStat2 = self::getDiskStats(); // Remove invalid disks @@ -472,11 +473,12 @@ static public function getIOUsage(): array * the current download and upload usage in Megabytes. * There is also a ['total'] key that contains the total amount of download and upload * + * @param int $duration * @return array * * @throws Exception */ - static public function getNetworkUsage(): array + static public function getNetworkUsage($duration = 1): array { // Create a list of interfaces $interfaces = scandir('/sys/class/net', SCANDIR_SORT_NONE); @@ -498,7 +500,7 @@ static public function getNetworkUsage(): array foreach ($interfaces as $interface) { $tx1 = intval(file_get_contents('/sys/class/net/' . $interface . '/statistics/tx_bytes')); $rx1 = intval(file_get_contents('/sys/class/net/' . $interface . '/statistics/rx_bytes')); - sleep(1); + sleep($duration); $tx2 = intval(file_get_contents('/sys/class/net/' . $interface . '/statistics/tx_bytes')); $rx2 = intval(file_get_contents('/sys/class/net/' . $interface . '/statistics/rx_bytes')); From 2eb81a79facc9bfc0271bf43204928fac5c1ab68 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 6 Jul 2022 11:57:11 +0100 Subject: [PATCH 06/18] Address Eldad's Comments --- Dockerfile | 39 +++++++++++++++++++++++++++++++++++++++ README.md | 7 +++++++ docker-compose.yml | 12 ++++++++++++ src/System/System.php | 36 ++++++++++++++++++++++++++++++++---- 4 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..668b676 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,39 @@ +FROM composer:2.0 as composer + +ARG TESTING=false +ENV TESTING=$TESTING + +WORKDIR /usr/local/src/ + +COPY composer.lock /usr/local/src/ +COPY composer.json /usr/local/src/ + +RUN composer update --ignore-platform-reqs --optimize-autoloader \ + --no-plugins --no-scripts --prefer-dist + +FROM php:8.0-cli-alpine as compile + +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +RUN \ + apk update \ + && apk add --no-cache make automake autoconf gcc g++ git brotli-dev \ + && docker-php-ext-install opcache \ + && rm -rf /var/cache/apk/* + +FROM compile as final + +LABEL maintainer="team@appwrite.io" + +WORKDIR /usr/src/code + +RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" + +RUN echo "opcache.enable_cli=1" >> $PHP_INI_DIR/php.ini + +COPY --from=composer /usr/local/src/vendor /usr/src/code/vendor + +# Add Source Code +COPY . /usr/src/code + +CMD [ "tail", "-f", "/dev/null" ] diff --git a/README.md b/README.md index a8a6a45..10a27af 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,13 @@ echo System::isX86(); // bool Utopia Framework requires PHP 7.4 or later. We recommend using the latest PHP version whenever possible. +## Supported Methods +| | getCPUCores | getCPUUtilisation | getMemoryTotal | getMemoryFree | getDiskTotal | getDiskFree | getIOUsage | getNetworkUsage | +|---------|-------------|-------------------|----------------|---------------|--------------|-------------|------------|-----------------| +| Windows | ✅ | | | | ✅ | ✅ | | | +| MacOS | ✅ | | ✅ | ✅ | ✅ | ✅ | | | +| Linux | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | + ## Authors **Eldad Fux** diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..2131adb --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,12 @@ +version: '3.1' + +services: + main-test: + build: + context: . + mem_limit: 512m + mem_reservation: 128M + cpus: 0.5 + command: tail -f /dev/null + volumes: + - ./:/usr/src/code diff --git a/src/System/System.php b/src/System/System.php index 36ffbe0..704819d 100644 --- a/src/System/System.php +++ b/src/System/System.php @@ -20,6 +20,10 @@ class System * * This list is ran through a contains, meaning for example if 'loop' was in the list, * A 'loop0' interface would be considered invalid and not computed. + * + * Documentation: + * Loop - https://man7.org/linux/man-pages/man4/loop.4.html + * Ram - https://man7.org/linux/man-pages/man4/ram.4.html */ private const InvalidDisks = [ 'loop', @@ -32,6 +36,14 @@ class System * * This list is ran through a contains, meaning for example if 'vboxnet' was in the list, * A 'vboxnet0' interface would be considered invalid and not computed. + * + * Documentation: + * veth - https://man7.org/linux/man-pages/man4/veth.4.html + * docker - https://docs.docker.com/network/ + * lo - Localhost Loopback device, https://man7.org/linux/man-pages/man4/loop.4.html + * tun - Linux Layer 3 Interface, https://www.kernel.org/doc/html/v5.8/networking/tuntap.html + * vboxnet - Virtual Machine Networking Interface, https://www.virtualbox.org/manual/ch06.html + * bonding_masters - https://www.kernel.org/doc/Documentation/networking/bonding.txt */ private const InvalidNetInterfaces = [ 'veth', @@ -221,8 +233,8 @@ static private function getProcStatData(): array $data[$cpuNumber]['softirq'] = $cpu[7]; // These might not exist on older kernels. - $data[$cpuNumber]['steal'] = isset($cpu[8]) ? $cpu[8] : 0; - $data[$cpuNumber]['guest'] = isset($cpu[9]) ? $cpu[9] : 0; + $data[$cpuNumber]['steal'] = $cpu[8] ?? 0; + $data[$cpuNumber]['guest'] = $cpu[9] ?? 0; } if (!$totalCPUExists) { @@ -316,7 +328,12 @@ static public function getMemoryTotal(): int case 'Linux': $meminfo = file_get_contents('/proc/meminfo'); preg_match('/MemTotal:\s+(\d+)/', $meminfo, $matches); - return intval(intval($matches[1]) / 1024); + + if (isset($matches[1])) { + return intval(intval($matches[1]) / 1024); + } else { + throw new Exception('Could not find MemTotal in /proc/meminfo.'); + } break; case 'Darwin': return intval((intval(shell_exec('sysctl -n hw.memsize'))) / 1024 / 1024); @@ -339,7 +356,11 @@ static public function getMemoryFree(): int case 'Linux': $meminfo = file_get_contents('/proc/meminfo'); preg_match('/MemFree:\s+(\d+)/', $meminfo, $matches); - return intval($matches[1] / 1024); + if (isset($matches[1])) { + return intval(intval($matches[1]) / 1024); + } else { + throw new Exception('Could not find MemFree in /proc/meminfo.'); + } case 'Darwin': return intval(intval(shell_exec('sysctl -n vm.page_free_count')) / 1024 / 1024); default: @@ -436,6 +457,9 @@ static public function getIOUsage($duration = 1): array // Remove invalid disks $diskStat = array_filter($diskStat, function ($disk) { foreach (self::InvalidDisks as $filter) { + if (!$disk[2]) { + return false; + } if (str_contains($disk[2], $filter)) { return false; } @@ -446,6 +470,10 @@ static public function getIOUsage($duration = 1): array $diskStat2 = array_filter($diskStat2, function ($disk) { foreach (self::InvalidDisks as $filter) { + if (!$disk[2]) { + return false; + } + if (str_contains($disk[2], $filter)) { return false; } From d6edbb6b1aa0db7d01ae70ee9a5172c575948d6a Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Thu, 28 Jul 2022 14:36:43 +0100 Subject: [PATCH 07/18] Fix null safety --- composer.json | 3 +- src/System/System.php | 66 +++++++++++++++++++++---------------------- 2 files changed, 35 insertions(+), 34 deletions(-) diff --git a/composer.json b/composer.json index 5c27a0a..de97f14 100644 --- a/composer.json +++ b/composer.json @@ -23,6 +23,7 @@ }, "require-dev": { "phpunit/phpunit": "^9.3", - "vimeo/psalm": "4.0.1" + "vimeo/psalm": "4.0.1", + "squizlabs/php_codesniffer": "^3.6" } } diff --git a/src/System/System.php b/src/System/System.php index 704819d..d0f1562 100644 --- a/src/System/System.php +++ b/src/System/System.php @@ -224,13 +224,13 @@ static private function getProcStatData(): array $cpuNumber = 'total'; } - $data[$cpuNumber]['user'] = $cpu[1]; - $data[$cpuNumber]['nice'] = $cpu[2]; - $data[$cpuNumber]['system'] = $cpu[3]; - $data[$cpuNumber]['idle'] = $cpu[4]; - $data[$cpuNumber]['iowait'] = $cpu[5]; - $data[$cpuNumber]['irq'] = $cpu[6]; - $data[$cpuNumber]['softirq'] = $cpu[7]; + $data[$cpuNumber]['user'] = $cpu[1] ?? 0; + $data[$cpuNumber]['nice'] = $cpu[2] ?? 0; + $data[$cpuNumber]['system'] = $cpu[3] ?? 0; + $data[$cpuNumber]['idle'] = $cpu[4] ?? 0; + $data[$cpuNumber]['iowait'] = $cpu[5] ?? 0; + $data[$cpuNumber]['irq'] = $cpu[6] ?? 0; + $data[$cpuNumber]['softirq'] = $cpu[7] ?? 0; // These might not exist on older kernels. $data[$cpuNumber]['steal'] = $cpu[8] ?? 0; @@ -252,15 +252,15 @@ static private function getProcStatData(): array ]; foreach ($data as $cpu) { - $data['total']['user'] += $cpu['user']; - $data['total']['nice'] += $cpu['nice']; - $data['total']['system'] += $cpu['system']; - $data['total']['idle'] += $cpu['idle']; - $data['total']['iowait'] += $cpu['iowait']; - $data['total']['irq'] += $cpu['irq']; - $data['total']['softirq'] += $cpu['softirq']; - $data['total']['steal'] += $cpu['steal']; - $data['total']['guest'] += $cpu['guest']; + $data['total']['user'] += intval($cpu['user']); + $data['total']['nice'] += intval($cpu['nice'] ?? 0); + $data['total']['system'] += intval($cpu['system'] ?? 0); + $data['total']['idle'] += intval($cpu['idle'] ?? 0); + $data['total']['iowait'] += intval($cpu['iowait'] ?? 0); + $data['total']['irq'] += intval($cpu['irq'] ?? 0); + $data['total']['softirq'] += intval($cpu['softirq'] ?? 0); + $data['total']['steal'] += intval($cpu['steal'] ?? 0); + $data['total']['guest'] += intval($cpu['guest'] ?? 0); } } @@ -325,22 +325,22 @@ static public function getCPUUtilisation(int $id = 0): int static public function getMemoryTotal(): int { switch (self::getOS()) { - case 'Linux': - $meminfo = file_get_contents('/proc/meminfo'); - preg_match('/MemTotal:\s+(\d+)/', $meminfo, $matches); - - if (isset($matches[1])) { - return intval(intval($matches[1]) / 1024); - } else { - throw new Exception('Could not find MemTotal in /proc/meminfo.'); - } - break; - case 'Darwin': - return intval((intval(shell_exec('sysctl -n hw.memsize'))) / 1024 / 1024); - break; - default: - throw new Exception(self::getOS() . " not supported."); + case 'Linux': + $meminfo = file_get_contents('/proc/meminfo'); + preg_match('/MemTotal:\s+(\d+)/', $meminfo, $matches); + + if (isset($matches[1])) { + return intval(intval($matches[1]) / 1024); + } else { + throw new Exception('Could not find MemTotal in /proc/meminfo.'); } + break; + case 'Darwin': + return intval((intval(shell_exec('sysctl -n hw.memsize'))) / 1024 / 1024); + break; + default: + throw new Exception(self::getOS() . " not supported."); + } } /** @@ -457,7 +457,7 @@ static public function getIOUsage($duration = 1): array // Remove invalid disks $diskStat = array_filter($diskStat, function ($disk) { foreach (self::InvalidDisks as $filter) { - if (!$disk[2]) { + if (!isset($disk[2])) { return false; } if (str_contains($disk[2], $filter)) { @@ -470,7 +470,7 @@ static public function getIOUsage($duration = 1): array $diskStat2 = array_filter($diskStat2, function ($disk) { foreach (self::InvalidDisks as $filter) { - if (!$disk[2]) { + if (!isset($disk[2])) { return false; } From 2c27348148541e1bfee57387889701dd495a4b19 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 1 Aug 2022 09:40:39 +0100 Subject: [PATCH 08/18] Run Linter --- src/System/System.php | 93 ++++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/src/System/System.php b/src/System/System.php index d0f1562..5552255 100644 --- a/src/System/System.php +++ b/src/System/System.php @@ -25,7 +25,7 @@ class System * Loop - https://man7.org/linux/man-pages/man4/loop.4.html * Ram - https://man7.org/linux/man-pages/man4/ram.4.html */ - private const InvalidDisks = [ + private const INVALIDDISKS = [ 'loop', 'ram', ]; @@ -45,7 +45,7 @@ class System * vboxnet - Virtual Machine Networking Interface, https://www.virtualbox.org/manual/ch06.html * bonding_masters - https://www.kernel.org/doc/Documentation/networking/bonding.txt */ - private const InvalidNetInterfaces = [ + private const INVALIDNETINTERFACES = [ 'veth', 'docker', 'lo', @@ -57,6 +57,7 @@ class System /** * Returns the system's OS. + * * @return string */ static public function getOS(): string @@ -85,19 +86,19 @@ static public function getArchEnum(): string { $arch = self::getArch(); switch (1) { - case preg_match(self::RegExX86, $arch): - return System::X86; - break; - case preg_match(self::RegExPPC, $arch): - return System::PPC; - break; - case preg_match(self::RegExARM, $arch): - return System::ARM; - break; + case preg_match(self::RegExX86, $arch): + return System::X86; + break; + case preg_match(self::RegExPPC, $arch): + return System::PPC; + break; + case preg_match(self::RegExARM, $arch): + return System::ARM; + break; - default: - throw new Exception("'{$arch}' enum not found."); - break; + default: + throw new Exception("'{$arch}' enum not found."); + break; } } @@ -154,19 +155,19 @@ static public function isPPC(): bool static public function isArch(string $arch): bool { switch ($arch) { - case self::X86: - return self::isX86(); - break; - case self::PPC: - return self::isPPC(); - break; - case self::ARM: - return self::isArm(); - break; + case self::X86: + return self::isX86(); + break; + case self::PPC: + return self::isPPC(); + break; + case self::ARM: + return self::isArm(); + break; - default: - throw new Exception("'{$arch}' not found."); - break; + default: + throw new Exception("'{$arch}' not found."); + break; } } @@ -353,18 +354,18 @@ static public function getMemoryTotal(): int static public function getMemoryFree(): int { switch (self::getOS()) { - case 'Linux': - $meminfo = file_get_contents('/proc/meminfo'); - preg_match('/MemFree:\s+(\d+)/', $meminfo, $matches); - if (isset($matches[1])) { - return intval(intval($matches[1]) / 1024); - } else { - throw new Exception('Could not find MemFree in /proc/meminfo.'); - } - case 'Darwin': - return intval(intval(shell_exec('sysctl -n vm.page_free_count')) / 1024 / 1024); - default: - throw new Exception(self::getOS() . " not supported."); + case 'Linux': + $meminfo = file_get_contents('/proc/meminfo'); + preg_match('/MemFree:\s+(\d+)/', $meminfo, $matches); + if (isset($matches[1])) { + return intval(intval($matches[1]) / 1024); + } else { + throw new Exception('Could not find MemFree in /proc/meminfo.'); + } + case 'Darwin': + return intval(intval(shell_exec('sysctl -n vm.page_free_count')) / 1024 / 1024); + default: + throw new Exception(self::getOS() . " not supported."); } } @@ -456,7 +457,7 @@ static public function getIOUsage($duration = 1): array // Remove invalid disks $diskStat = array_filter($diskStat, function ($disk) { - foreach (self::InvalidDisks as $filter) { + foreach (self::INVALIDDISKS as $filter) { if (!isset($disk[2])) { return false; } @@ -469,7 +470,7 @@ static public function getIOUsage($duration = 1): array }); $diskStat2 = array_filter($diskStat2, function ($disk) { - foreach (self::InvalidDisks as $filter) { + foreach (self::INVALIDDISKS as $filter) { if (!isset($disk[2])) { return false; } @@ -497,11 +498,13 @@ static public function getIOUsage($duration = 1): array } /** - * Returns an array of all the available network interfaces on the system containing - * the current download and upload usage in Megabytes. - * There is also a ['total'] key that contains the total amount of download and upload + * Returns an array of all the available network interfaces on the system + * containing the current download and upload usage in Megabytes. + * There is also a ['total'] key that contains the total amount of download + * and upload + * + * @param int $duration The buffer duration to fetch the data points * - * @param int $duration * @return array * * @throws Exception @@ -513,7 +516,7 @@ static public function getNetworkUsage($duration = 1): array // Remove all unwanted interfaces $interfaces = array_filter($interfaces, function ($interface) { - foreach (self::InvalidNetInterfaces as $filter) { + foreach (self::INVALIDNETINTERFACES as $filter) { if (str_contains($interface, $filter)) { return false; } From 741f4732eb130d77ff533c8fe2521fbe4499bd3b Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 8 Aug 2022 10:18:06 +0100 Subject: [PATCH 09/18] Try and fix tests --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index b3681e1..f0c391f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ language: php +dist: focal + arch: - amd64 - ppc64le From 95f0847fcae01b991d28bd3db7b34e75ff1186b4 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 8 Aug 2022 12:00:37 +0100 Subject: [PATCH 10/18] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f0c391f..828955e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: php -dist: focal +dist: xenial arch: - amd64 From 6368f26427cc52ae968f8d45b2fef1687581022d Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Thu, 22 Sep 2022 09:20:30 +0100 Subject: [PATCH 11/18] Update .travis.yml --- .travis.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 828955e..4976fe6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,9 @@ language: php -dist: xenial +dist: focal arch: - amd64 -- ppc64le - arm64 php: @@ -22,5 +21,4 @@ script: - vendor/bin/phpunit --configuration phpunit.xml --testsuite General - vendor/bin/psalm --show-info=true - if [ "$TRAVIS_CPU_ARCH" = "amd64" ]; then vendor/bin/phpunit --configuration phpunit.xml --testsuite X86; fi -- if [ "$TRAVIS_CPU_ARCH" = "ppc64le" ]; then vendor/bin/phpunit --configuration phpunit.xml --testsuite PPC; fi - if [ "$TRAVIS_CPU_ARCH" = "arm64" ]; then vendor/bin/phpunit --configuration phpunit.xml --testsuite ARM; fi From d96dcf7748bbb1064ffbbca6cfe8a2eecd0d5fc6 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Thu, 22 Sep 2022 09:25:19 +0100 Subject: [PATCH 12/18] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4976fe6..9a23507 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ notifications: email: - team@appwrite.io -before_script: composer install --ignore-platform-reqs +before_script: apt-get install libargon2-0 && composer install --ignore-platform-reqs script: - vendor/bin/phpunit --configuration phpunit.xml --testsuite General From 28c0e79af9dd03b5b8e55b7f27cf3917c880050b Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Thu, 22 Sep 2022 10:51:12 +0100 Subject: [PATCH 13/18] Update .travis.yml --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9a23507..5578ee1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,14 +8,14 @@ arch: php: - 7.4 -- 8.0 +- 8.0.23 - nightly notifications: email: - team@appwrite.io -before_script: apt-get install libargon2-0 && composer install --ignore-platform-reqs +before_script: sudo apt-get install libargon2-0 && composer install --ignore-platform-reqs script: - vendor/bin/phpunit --configuration phpunit.xml --testsuite General From 59bc762eb7d4b13176ef8b27b723141d47162966 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Thu, 22 Sep 2022 13:43:14 +0100 Subject: [PATCH 14/18] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5578ee1..6b3a7b6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: php -dist: focal +dist: xenial arch: - amd64 From b677c2bf129deb14710cf092a3ef3c1b6fa6420a Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Thu, 22 Sep 2022 15:14:46 +0100 Subject: [PATCH 15/18] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6b3a7b6..5cdd30f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ notifications: email: - team@appwrite.io -before_script: sudo apt-get install libargon2-0 && composer install --ignore-platform-reqs +before_script: composer install --ignore-platform-reqs script: - vendor/bin/phpunit --configuration phpunit.xml --testsuite General From 66039d96bceab966c402a4e633faa2301e417abd Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Thu, 22 Sep 2022 18:08:01 +0100 Subject: [PATCH 16/18] Update .travis.yml --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5cdd30f..e9b1897 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: php -dist: xenial +dist: bionic arch: - amd64 @@ -9,7 +9,6 @@ arch: php: - 7.4 - 8.0.23 -- nightly notifications: email: From eac63e3a95802d1a5769d278411eb27fc0fc583d Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Thu, 22 Sep 2022 18:14:54 +0100 Subject: [PATCH 17/18] Update .travis.yml --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e9b1897..dd74e2d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: php -dist: bionic +dist: xenial arch: - amd64 @@ -8,7 +8,7 @@ arch: php: - 7.4 -- 8.0.23 +- 8.0 notifications: email: From b0d7bf4907ab0e25bba758c44cf470c1629e0662 Mon Sep 17 00:00:00 2001 From: Qasim Abdullah <89213175+qasim-at-tci@users.noreply.github.com> Date: Thu, 22 Sep 2022 22:26:33 +0500 Subject: [PATCH 18/18] Check argon2 manual installation --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index dd74e2d..912d3d6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,10 @@ arch: php: - 7.4 - 8.0 +- 8.0.23 + +before_install: + - git clone https://github.com/P-H-C/phc-winner-argon2.git libargon2 && cd libargon2 && make test && sudo make install PREFIX=/usr && cd .. notifications: email: