diff --git a/app/executor.php b/app/executor.php index 29f46ef5c9..06f06961ec 100644 --- a/app/executor.php +++ b/app/executor.php @@ -35,6 +35,7 @@ use Utopia\Validator\Boolean; use Utopia\Validator\Range; use Utopia\Validator\Text; +use function Swoole\Coroutine\batch; Runtime::enableCoroutine(true, SWOOLE_HOOK_ALL); @@ -665,47 +666,6 @@ App::post('/v1/execution') } ); -App::get('/v1/health') - ->desc("Get usage stats of host machine CPU usage from 0 to 100.") - ->inject('response') - ->action(function (Response $response) use ($orchestrationPool) { - // TODO: @Meldiron separate into dedicated http server - - $systemCores = System::getCPUCores(); // TODO: @Meldiron use new method - $systemUsage = System::getCPUUtilisation() / $systemCores; - $functionsUsage = []; - - try { - $orchestration = $orchestrationPool->get(); - $containerUsages = $orchestration->getStats( - filters: [ 'label' => 'openruntimes-executor=' . System::getHostname() ], - cycles: 3 - ); - - foreach ($containerUsages as $containerUsage) { - $functionsUsage[$containerUsage['name']] = $containerUsage['cpu'] * 100; - } - } catch (\Exception $error) { - logError($error, "healthError"); - - $response - ->setStatusCode(Response::STATUS_CODE_INTERNAL_SERVER_ERROR) - ->json([ - 'status' => 'fail' - ]); - } finally { - $orchestrationPool->put($orchestration); - } - - $response - ->setStatusCode(Response::STATUS_CODE_OK) - ->json([ - 'status' => 'pass', - 'hostUsage' => $systemUsage, - 'functionsUsage' => $functionsUsage - ]); - }); - App::setMode(App::MODE_TYPE_PRODUCTION); // Define Mode $http = new Server("0.0.0.0", 80); @@ -794,6 +754,74 @@ $http->on('start', function ($http) { global $orchestrationPool; global $activeRuntimes; + /** + * Start separate HTTP server for Health API + */ + \go(function() use ($orchestrationPool) { + $healthServer = new Swoole\Coroutine\Http\Server('0.0.0.0', 3000, false); + + // Get usage stats of host machine CPU usage from 0 to 100. + $healthServer->handle('/v1/health', function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) use ($orchestrationPool) { + // TODO: Check key of request + $orchestration = null; + + try { + $output = [ + 'status' => 'pass' + ]; + + batch([ + function () use (&$output) { + $output['hostUsage'] = System::getCPUUsage(5); + }, + function () use (&$output, &$orchestration, $orchestrationPool) { + $functionsUsage = []; + + $orchestration = $orchestrationPool->get(); + $containerUsages = $orchestration->getStats( + filters: [ 'label' => 'openruntimes-executor=' . System::getHostname() ], + cycles: 3 + ); + + foreach ($containerUsages as $containerUsage) { + $functionsUsage[$containerUsage['name']] = $containerUsage['cpu'] * 100; + } + + $output['functionsUsage'] = $functionsUsage; + } + ]); + + $swooleResponse->setStatusCode(200); + $swooleResponse->header('content-type', 'application/json; charset=UTF-8'); + $swooleResponse->write(\json_encode($output)); + $swooleResponse->end(); + } catch (\Throwable $th) { + logError($th, "healthError"); + + $output = [ + 'status' => 'fail', + + 'message' => 'Error: ' . $th->getMessage(), + 'code' => 500, + 'file' => $th->getFile(), + 'line' => $th->getLine(), + 'trace' => $th->getTrace() + ]; + + $swooleResponse->setStatusCode(500); + $swooleResponse->header('content-type', 'application/json; charset=UTF-8'); + $swooleResponse->write(\json_encode($output)); + $swooleResponse->end(); + } finally { + if($orchestration !== null) { + $orchestrationPool->put($orchestration); + } + } + }); + + $healthServer->start(); + }); + /** * Warmup: make sure images are ready to run fast 🚀 */ diff --git a/app/functionsProxy.php b/app/functionsProxy.php index 9ebeba317d..1d88318709 100644 --- a/app/functionsProxy.php +++ b/app/functionsProxy.php @@ -76,7 +76,7 @@ function fetchExecutorsState(RedisPool $redisPool, bool $forceShowError = false) $cache = new Cache(new Redis($redis)); try { - $endpoint = 'http://' . $executor . '/v1/health'; + $endpoint = 'http://' . $executor . ':3000/v1/health'; $ch = \curl_init(); diff --git a/composer.json b/composer.json index 2cf655e9a3..a5132e9458 100644 --- a/composer.json +++ b/composer.json @@ -43,7 +43,7 @@ "ext-sockets": "*", "appwrite/php-clamav": "1.1.*", "appwrite/php-runtimes": "dev-feat-upgrade-system-version as 0.11.0", - "utopia-php/system": "0.5.*", + "utopia-php/system": "dev-feat-cpu-usage as 0.5.0", "utopia-php/framework": "0.21.*", "utopia-php/logger": "0.3.*", "utopia-php/abuse": "0.14.*", diff --git a/composer.lock b/composer.lock index 3bd91da7a5..4fa217ba21 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0bcc1c352327423d6e64c8859d68cc6b", + "content-hash": "eeafbe6edd7f9b3c378a76acc7057a3d", "packages": [ { "name": "adhocore/jwt", @@ -931,6 +931,72 @@ }, "time": "2021-02-04T16:20:16+00:00" }, + { + "name": "laravel/pint", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/pint.git", + "reference": "1d276e4c803397a26cc337df908f55c2a4e90d86" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/pint/zipball/1d276e4c803397a26cc337df908f55c2a4e90d86", + "reference": "1d276e4c803397a26cc337df908f55c2a4e90d86", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "ext-tokenizer": "*", + "ext-xml": "*", + "php": "^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.11.0", + "illuminate/view": "^9.27", + "laravel-zero/framework": "^9.1.3", + "mockery/mockery": "^1.5.0", + "nunomaduro/larastan": "^2.2", + "nunomaduro/termwind": "^1.14.0", + "pestphp/pest": "^1.22.1" + }, + "bin": [ + "builds/pint" + ], + "type": "project", + "autoload": { + "psr-4": { + "App\\": "app/", + "Database\\Seeders\\": "database/seeders/", + "Database\\Factories\\": "database/factories/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "An opinionated code formatter for PHP.", + "homepage": "https://laravel.com", + "keywords": [ + "format", + "formatter", + "lint", + "linter", + "php" + ], + "support": { + "issues": "https://github.com/laravel/pint/issues", + "source": "https://github.com/laravel/pint" + }, + "time": "2022-09-13T15:07:15+00:00" + }, { "name": "matomo/device-detector", "version": "6.0.0", @@ -2661,19 +2727,20 @@ }, { "name": "utopia-php/system", - "version": "0.5.0", + "version": "dev-feat-cpu-usage", "source": { "type": "git", "url": "https://github.com/utopia-php/system.git", - "reference": "698a58aeaba0d939d2fec6a88a7422ce6e59e870" + "reference": "9847eb53d5fc6ddc008909cacdd39509e9966eb3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/system/zipball/698a58aeaba0d939d2fec6a88a7422ce6e59e870", - "reference": "698a58aeaba0d939d2fec6a88a7422ce6e59e870", + "url": "https://api.github.com/repos/utopia-php/system/zipball/9847eb53d5fc6ddc008909cacdd39509e9966eb3", + "reference": "9847eb53d5fc6ddc008909cacdd39509e9966eb3", "shasum": "" }, "require": { + "laravel/pint": "1.2.*", "php": ">=7.4" }, "require-dev": { @@ -2711,9 +2778,9 @@ ], "support": { "issues": "https://github.com/utopia-php/system/issues", - "source": "https://github.com/utopia-php/system/tree/0.5.0" + "source": "https://github.com/utopia-php/system/tree/feat-cpu-usage" }, - "time": "2022-09-23T13:24:58+00:00" + "time": "2022-10-19T06:19:09+00:00" }, { "name": "utopia-php/websocket", @@ -5370,11 +5437,18 @@ "version": "dev-feat-usage-stats", "alias": "0.6.0", "alias_normalized": "0.6.0.0" + }, + { + "package": "utopia-php/system", + "version": "dev-feat-cpu-usage", + "alias": "0.5.0", + "alias_normalized": "0.5.0.0" } ], "minimum-stability": "stable", "stability-flags": { "appwrite/php-runtimes": 20, + "utopia-php/system": 20, "utopia-php/orchestration": 20 }, "prefer-stable": false, diff --git a/docker-compose.yml b/docker-compose.yml index 60cf2aa3bf..abf2ce261d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -472,6 +472,7 @@ services: image: appwrite-dev ports: - 9507:80 + - 9508:3000 networks: appwrite: runtimes: @@ -516,7 +517,8 @@ services: stop_signal: SIGINT image: appwrite-dev ports: - - 9508:80 + - 9509:80 + - 9510:3000 networks: appwrite: runtimes: