1
0
Fork 0
mirror of synced 2024-07-01 20:50:49 +12:00
appwrite/app/controllers/api/health.php

361 lines
13 KiB
PHP
Raw Normal View History

2019-05-09 18:54:39 +12:00
<?php
2019-08-21 03:43:01 +12:00
use Appwrite\ClamAV\Network;
2020-12-28 06:57:35 +13:00
use Appwrite\Event\Event;
2022-05-03 02:34:01 +12:00
use Appwrite\Extend\Exception;
2021-12-15 03:17:55 +13:00
use Appwrite\Utopia\Response;
2020-06-29 05:31:21 +12:00
use Utopia\App;
2021-12-21 00:34:48 +13:00
use Utopia\Database\Document;
2022-05-03 02:34:01 +12:00
use Utopia\Registry\Registry;
use Utopia\Storage\Device;
2021-01-22 21:28:33 +13:00
use Utopia\Storage\Device\Local;
2022-05-24 02:54:50 +12:00
use Utopia\Storage\Storage;
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App::get('/v1/health')
2020-05-17 03:22:30 +12:00
->desc('Get HTTP')
2020-06-26 06:32:12 +12:00
->groups(['api', 'health'])
2020-05-17 03:34:37 +12:00
->label('scope', 'health.read')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
2019-05-09 18:54:39 +12:00
->label('sdk.namespace', 'health')
2020-01-31 05:18:46 +13:00
->label('sdk.method', 'get')
2020-05-01 20:39:45 +12:00
->label('sdk.description', '/docs/references/health/get.md')
2021-12-15 03:17:55 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_HEALTH_STATUS)
2020-12-27 04:10:45 +13:00
->inject('response')
2022-05-03 02:28:36 +12:00
->action(function (Response $response) {
2020-06-30 09:43:34 +12:00
2021-12-15 03:17:55 +13:00
$output = [
'status' => 'pass',
2021-12-15 23:19:29 +13:00
'ping' => 0
2021-12-15 03:17:55 +13:00
];
$response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS);
2020-12-27 04:10:45 +13:00
});
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App::get('/v1/health/version')
->desc('Get Version')
2020-06-26 06:32:12 +12:00
->groups(['api', 'health'])
->label('scope', 'public')
2021-12-15 03:17:55 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_HEALTH_VERSION)
2020-12-27 04:10:45 +13:00
->inject('response')
2022-05-03 02:28:36 +12:00
->action(function (Response $response) {
2020-06-30 09:43:34 +12:00
2021-12-15 03:17:55 +13:00
$response->dynamic(new Document([ 'version' => APP_VERSION_STABLE ]), Response::MODEL_HEALTH_VERSION);
2020-12-27 04:10:45 +13:00
});
2020-06-29 05:31:21 +12:00
App::get('/v1/health/db')
2020-05-17 03:22:30 +12:00
->desc('Get DB')
2020-06-26 06:32:12 +12:00
->groups(['api', 'health'])
2020-05-17 03:34:37 +12:00
->label('scope', 'health.read')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
2019-05-09 18:54:39 +12:00
->label('sdk.namespace', 'health')
->label('sdk.method', 'getDB')
2020-05-01 20:39:45 +12:00
->label('sdk.description', '/docs/references/health/get-db.md')
2021-12-15 03:17:55 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_HEALTH_STATUS)
2020-12-27 04:10:45 +13:00
->inject('response')
->inject('utopia')
2022-05-03 02:28:36 +12:00
->action(function (Response $response, App $utopia) {
2021-12-15 03:17:55 +13:00
$checkStart = \microtime(true);
2021-10-27 22:21:16 +13:00
try {
$db = $utopia->getResource('db'); /* @var $db PDO */
2020-06-30 09:43:34 +12:00
2021-10-27 22:21:16 +13:00
// Run a small test to check the connection
$statement = $db->prepare("SELECT 1;");
2022-05-24 02:54:50 +12:00
2021-10-27 22:21:16 +13:00
$statement->closeCursor();
2022-05-24 02:54:50 +12:00
2021-10-27 22:21:16 +13:00
$statement->execute();
} catch (Exception $_e) {
throw new Exception('Database is not available', 500, Exception::GENERAL_SERVER_ERROR);
2021-10-27 22:21:16 +13:00
}
2021-10-15 22:05:21 +13:00
2021-12-15 03:17:55 +13:00
$output = [
'status' => 'pass',
2021-12-17 01:19:04 +13:00
'ping' => \round((\microtime(true) - $checkStart) / 1000)
2021-12-15 03:17:55 +13:00
];
$response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS);
2020-12-27 04:10:45 +13:00
});
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App::get('/v1/health/cache')
2020-05-17 03:22:30 +12:00
->desc('Get Cache')
2020-06-26 06:32:12 +12:00
->groups(['api', 'health'])
2020-05-17 03:34:37 +12:00
->label('scope', 'health.read')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
2019-05-09 18:54:39 +12:00
->label('sdk.namespace', 'health')
->label('sdk.method', 'getCache')
2020-05-01 20:39:45 +12:00
->label('sdk.description', '/docs/references/health/get-cache.md')
2021-12-15 03:17:55 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_HEALTH_STATUS)
2020-12-27 04:10:45 +13:00
->inject('response')
->inject('utopia')
2022-05-03 02:28:36 +12:00
->action(function (Response $response, App $utopia) {
2021-12-15 03:17:55 +13:00
$checkStart = \microtime(true);
2021-10-19 04:08:50 +13:00
$redis = $utopia->getResource('cache');
2019-05-09 18:54:39 +12:00
2021-12-15 03:17:55 +13:00
if (!$redis->ping(true)) {
throw new Exception('Cache is not available', 500, Exception::GENERAL_SERVER_ERROR);
2021-10-19 04:08:50 +13:00
}
2021-12-15 03:17:55 +13:00
$output = [
'status' => 'pass',
2021-12-17 01:19:04 +13:00
'ping' => \round((\microtime(true) - $checkStart) / 1000)
2021-12-15 03:17:55 +13:00
];
$response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS);
2020-12-27 04:10:45 +13:00
});
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App::get('/v1/health/time')
2020-05-17 03:22:30 +12:00
->desc('Get Time')
2020-06-26 06:32:12 +12:00
->groups(['api', 'health'])
2020-05-17 03:34:37 +12:00
->label('scope', 'health.read')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
2019-05-09 18:54:39 +12:00
->label('sdk.namespace', 'health')
->label('sdk.method', 'getTime')
2020-05-01 20:39:45 +12:00
->label('sdk.description', '/docs/references/health/get-time.md')
2021-12-15 03:17:55 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_HEALTH_TIME)
2020-12-27 04:10:45 +13:00
->inject('response')
2022-05-03 02:28:36 +12:00
->action(function (Response $response) {
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
/*
* Code from: @see https://www.beliefmedia.com.au/query-ntp-time-server
*/
$host = 'time.google.com'; // https://developers.google.com/time/
$gap = 60; // Allow [X] seconds gap
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
/* Create a socket and connect to NTP server */
$sock = \socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
\socket_connect($sock, $host, 123);
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
/* Send request */
2022-05-24 02:54:50 +12:00
$msg = "\010" . \str_repeat("\0", 47);
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
\socket_send($sock, $msg, \strlen($msg), 0);
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
/* Receive response and close socket */
\socket_recv($sock, $recv, 48, MSG_WAITALL);
\socket_close($sock);
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
/* Interpret response */
$data = \unpack('N12', $recv);
$timestamp = \sprintf('%u', $data[9]);
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
/* NTP is number of seconds since 0000 UT on 1 January 1900
Unix time is seconds since 0000 UT on 1 January 1970 */
$timestamp -= 2208988800;
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
$diff = ($timestamp - \time());
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
if ($diff > $gap || $diff < ($gap * -1)) {
throw new Exception('Server time gaps detected', 500, Exception::GENERAL_SERVER_ERROR);
2019-05-09 18:54:39 +12:00
}
2020-06-30 09:43:34 +12:00
2021-12-15 03:17:55 +13:00
$output = [
2021-12-15 23:19:29 +13:00
'remoteTime' => $timestamp,
'localTime' => \time(),
2021-12-15 03:17:55 +13:00
'diff' => $diff
];
$response->dynamic(new Document($output), Response::MODEL_HEALTH_TIME);
2020-12-27 04:10:45 +13:00
});
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App::get('/v1/health/queue/webhooks')
2020-05-17 03:22:30 +12:00
->desc('Get Webhooks Queue')
2020-06-26 06:32:12 +12:00
->groups(['api', 'health'])
2020-05-17 03:34:37 +12:00
->label('scope', 'health.read')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
2019-05-09 18:54:39 +12:00
->label('sdk.namespace', 'health')
2020-05-01 20:39:45 +12:00
->label('sdk.method', 'getQueueWebhooks')
->label('sdk.description', '/docs/references/health/get-queue-webhooks.md')
2021-12-15 03:17:55 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE)
2020-12-27 04:10:45 +13:00
->inject('response')
2022-05-03 02:28:36 +12:00
->action(function (Response $response) {
2020-06-30 09:43:34 +12:00
$response->dynamic(new Document([ 'size' => Resque::size(Event::WEBHOOK_QUEUE_NAME) ]), Response::MODEL_HEALTH_QUEUE);
2020-06-30 09:43:34 +12:00
}, ['response']);
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App::get('/v1/health/queue/logs')
->desc('Get Logs Queue')
2020-06-26 06:32:12 +12:00
->groups(['api', 'health'])
2020-05-17 03:34:37 +12:00
->label('scope', 'health.read')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
2020-05-01 20:39:45 +12:00
->label('sdk.namespace', 'health')
->label('sdk.method', 'getQueueLogs')
->label('sdk.description', '/docs/references/health/get-queue-logs.md')
2021-12-15 03:17:55 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE)
2020-12-27 04:10:45 +13:00
->inject('response')
2022-05-03 02:28:36 +12:00
->action(function (Response $response) {
2020-06-30 09:43:34 +12:00
$response->dynamic(new Document([ 'size' => Resque::size(Event::AUDITS_QUEUE_NAME) ]), Response::MODEL_HEALTH_QUEUE);
2020-06-30 09:43:34 +12:00
}, ['response']);
2020-05-01 20:39:45 +12:00
2020-06-29 05:31:21 +12:00
App::get('/v1/health/queue/certificates')
2021-10-21 04:30:59 +13:00
->desc('Get Certificates Queue')
2020-06-26 06:32:12 +12:00
->groups(['api', 'health'])
2020-05-17 03:34:37 +12:00
->label('scope', 'health.read')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
2020-05-01 20:39:45 +12:00
->label('sdk.namespace', 'health')
->label('sdk.method', 'getQueueCertificates')
->label('sdk.description', '/docs/references/health/get-queue-certificates.md')
2021-12-15 03:17:55 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE)
2020-12-27 04:10:45 +13:00
->inject('response')
2022-05-03 02:28:36 +12:00
->action(function (Response $response) {
2020-06-30 09:43:34 +12:00
$response->dynamic(new Document([ 'size' => Resque::size(Event::CERTIFICATES_QUEUE_NAME) ]), Response::MODEL_HEALTH_QUEUE);
2020-06-30 09:43:34 +12:00
}, ['response']);
2020-05-01 20:39:45 +12:00
2020-06-29 05:31:21 +12:00
App::get('/v1/health/queue/functions')
2020-05-17 03:34:37 +12:00
->desc('Get Functions Queue')
2020-06-26 06:32:12 +12:00
->groups(['api', 'health'])
2020-05-17 03:34:37 +12:00
->label('scope', 'health.read')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
2020-05-17 03:34:37 +12:00
->label('sdk.namespace', 'health')
->label('sdk.method', 'getQueueFunctions')
->label('sdk.description', '/docs/references/health/get-queue-functions.md')
2021-12-15 03:17:55 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE)
2020-12-27 04:10:45 +13:00
->inject('response')
2022-05-03 02:28:36 +12:00
->action(function (Response $response) {
2020-06-30 09:43:34 +12:00
$response->dynamic(new Document([ 'size' => Resque::size(Event::FUNCTIONS_QUEUE_NAME) ]), Response::MODEL_HEALTH_QUEUE);
2020-06-30 09:43:34 +12:00
}, ['response']);
2020-05-17 03:34:37 +12:00
2020-06-29 05:31:21 +12:00
App::get('/v1/health/storage/local')
2020-05-17 03:22:30 +12:00
->desc('Get Local Storage')
2020-06-26 06:32:12 +12:00
->groups(['api', 'health'])
2020-05-17 03:34:37 +12:00
->label('scope', 'health.read')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
2019-05-09 18:54:39 +12:00
->label('sdk.namespace', 'health')
->label('sdk.method', 'getStorageLocal')
2020-05-01 20:39:45 +12:00
->label('sdk.description', '/docs/references/health/get-storage-local.md')
2021-12-15 03:17:55 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_HEALTH_STATUS)
2020-12-27 04:10:45 +13:00
->inject('response')
2022-05-03 02:28:36 +12:00
->action(function (Response $response) {
2020-06-30 09:43:34 +12:00
2021-12-15 03:17:55 +13:00
$checkStart = \microtime(true);
2022-05-24 02:54:50 +12:00
foreach (
[
2020-06-30 09:43:34 +12:00
'Uploads' => APP_STORAGE_UPLOADS,
'Cache' => APP_STORAGE_CACHE,
'Config' => APP_STORAGE_CONFIG,
'Certs' => APP_STORAGE_CERTIFICATES
2022-05-24 02:54:50 +12:00
] as $key => $volume
) {
2020-06-30 09:43:34 +12:00
$device = new Local($volume);
if (!\is_readable($device->getRoot())) {
2022-05-24 02:54:50 +12:00
throw new Exception('Device ' . $key . ' dir is not readable', 500, Exception::GENERAL_SERVER_ERROR);
2019-05-09 18:54:39 +12:00
}
2020-06-30 09:43:34 +12:00
if (!\is_writable($device->getRoot())) {
2022-05-24 02:54:50 +12:00
throw new Exception('Device ' . $key . ' dir is not writable', 500, Exception::GENERAL_SERVER_ERROR);
2020-06-30 09:43:34 +12:00
}
2019-05-09 18:54:39 +12:00
}
2020-06-30 09:43:34 +12:00
2021-12-15 03:17:55 +13:00
$output = [
'status' => 'pass',
2021-12-17 01:19:04 +13:00
'ping' => \round((\microtime(true) - $checkStart) / 1000)
2021-12-15 03:17:55 +13:00
];
$response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS);
2020-12-27 04:10:45 +13:00
});
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App::get('/v1/health/anti-virus')
->desc('Get Antivirus')
2020-06-26 06:32:12 +12:00
->groups(['api', 'health'])
2020-05-17 03:34:37 +12:00
->label('scope', 'health.read')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
2019-05-09 18:54:39 +12:00
->label('sdk.namespace', 'health')
->label('sdk.method', 'getAntivirus')
2020-05-01 20:39:45 +12:00
->label('sdk.description', '/docs/references/health/get-storage-anti-virus.md')
2021-12-15 03:17:55 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_HEALTH_ANTIVIRUS)
2020-12-27 04:10:45 +13:00
->inject('response')
2022-05-03 02:28:36 +12:00
->action(function (Response $response) {
2019-05-09 18:54:39 +12:00
2021-12-15 03:17:55 +13:00
$output = [
'status' => '',
'version' => ''
];
2020-06-30 09:43:34 +12:00
if (App::getEnv('_APP_STORAGE_ANTIVIRUS') === 'disabled') { // Check if scans are enabled
2021-12-15 03:17:55 +13:00
$output['status'] = 'disabled';
$output['version'] = '';
} else {
2022-05-24 02:54:50 +12:00
$antivirus = new Network(
App::getEnv('_APP_STORAGE_ANTIVIRUS_HOST', 'clamav'),
(int) App::getEnv('_APP_STORAGE_ANTIVIRUS_PORT', 3310)
);
2021-12-15 03:17:55 +13:00
try {
$output['version'] = @$antivirus->version();
$output['status'] = (@$antivirus->ping()) ? 'pass' : 'fail';
2022-05-24 02:54:50 +12:00
} catch (\Exception $e) {
throw new Exception('Antivirus is not available', 500, Exception::GENERAL_SERVER_ERROR);
2021-12-15 03:17:55 +13:00
}
2019-05-09 18:54:39 +12:00
}
2020-06-30 09:43:34 +12:00
$response->dynamic(new Document($output), Response::MODEL_HEALTH_ANTIVIRUS);
2020-12-27 04:10:45 +13:00
});
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App::get('/v1/health/stats') // Currently only used internally
2020-05-17 03:22:30 +12:00
->desc('Get System Stats')
2020-06-26 06:32:12 +12:00
->groups(['api', 'health'])
2021-05-13 02:53:25 +12:00
->label('scope', 'root')
2021-04-16 19:22:17 +12:00
// ->label('sdk.auth', [APP_AUTH_TYPE_KEY])
2020-05-01 20:39:45 +12:00
// ->label('sdk.namespace', 'health')
// ->label('sdk.method', 'getStats')
2019-05-09 18:54:39 +12:00
->label('docs', false)
2020-12-27 04:10:45 +13:00
->inject('response')
->inject('register')
2022-02-15 21:43:57 +13:00
->inject('deviceFiles')
2022-05-03 02:28:36 +12:00
->action(function (Response $response, Registry $register, Device $deviceFiles) {
2020-06-30 09:43:34 +12:00
$cache = $register->get('cache');
$cacheStats = $cache->info();
$response
->json([
'storage' => [
2022-05-24 02:54:50 +12:00
'used' => Storage::human($deviceFiles->getDirectorySize($deviceFiles->getRoot() . '/')),
2022-02-15 21:43:57 +13:00
'partitionTotal' => Storage::human($deviceFiles->getPartitionTotalSpace()),
'partitionFree' => Storage::human($deviceFiles->getPartitionFreeSpace()),
2020-06-30 09:43:34 +12:00
],
'cache' => [
2020-10-15 10:34:57 +13:00
'uptime' => $cacheStats['uptime_in_seconds'] ?? 0,
'clients' => $cacheStats['connected_clients'] ?? 0,
'hits' => $cacheStats['keyspace_hits'] ?? 0,
'misses' => $cacheStats['keyspace_misses'] ?? 0,
'memory_used' => $cacheStats['used_memory'] ?? 0,
'memory_used_human' => $cacheStats['used_memory_human'] ?? 0,
'memory_used_peak' => $cacheStats['used_memory_peak'] ?? 0,
'memory_used_peak_human' => $cacheStats['used_memory_peak_human'] ?? 0,
2020-06-30 09:43:34 +12:00
],
]);
2020-12-27 04:10:45 +13:00
});