From 6d6b0ee02418fe6ea7d70eb8b562ef46d256f023 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Fri, 27 Aug 2021 00:14:32 +0530 Subject: [PATCH] feat(usage): added response models for storage API --- app/controllers/api/storage.php | 212 ++++++++---------- src/Appwrite/Utopia/Response.php | 6 + .../Utopia/Response/Model/BucketsUsage.php | 70 ++++++ .../Utopia/Response/Model/CollectionUsage.php | 8 +- .../Utopia/Response/Model/DatabaseUsage.php | 8 +- .../Utopia/Response/Model/StorageUsage.php | 56 +++++ 6 files changed, 230 insertions(+), 130 deletions(-) create mode 100644 src/Appwrite/Utopia/Response/Model/BucketsUsage.php create mode 100644 src/Appwrite/Utopia/Response/Model/StorageUsage.php diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 5589dbe95..69a7c1870 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -651,6 +651,9 @@ App::get('/v1/storage/usage') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'storage') ->label('sdk.method', 'getUsage') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_STORAGE_USAGE) ->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForInternal') @@ -658,71 +661,11 @@ App::get('/v1/storage/usage') /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ + $usage = []; if (App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') { $period = [ '24h' => [ - 'period' => '30m', - 'limit' => 48, - ], - '7d' => [ - 'period' => '1d', - 'limit' => 7, - ], - '30d' => [ - 'period' => '1d', - 'limit' => 30, - ], - '90d' => [ - 'period' => '1d', - 'limit' => 90, - ], - ]; - - Authorization::disable(); - - $storageTotal = $dbForInternal->findOne('stats', [new Query('metric', Query::TYPE_EQUAL, ['storage.total'])], 0, ['time'], [Database::ORDER_DESC]); - $storage = $storageTotal ? $storageTotal->getAttribute('value', 0) : 0; - - $filesCount = $dbForInternal->findOne('stats', [new Query('metric', Query::TYPE_EQUAL, ['storage.files.count'])], 0, ['time'], [Database::ORDER_DESC]); - $filesTotal = $filesCount ? $filesCount->getAttribute('value', 0) : 0; - - Authorization::reset(); - - $response->json([ - 'range' => $range, - 'storage' => [ - 'total' => $storage, - ], - 'files' => [ - 'total' => $filesTotal, - ], - ]); - } else { - $response->json([]); - } - }); - -App::get('/v1/storage/:bucketId/usage') - ->desc('Get usage stats for a storage bucket') - ->groups(['api', 'storage']) - ->label('scope', 'files.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'getUsage') - ->param('bucketId', '', new UID(), 'Bucket unique ID.') - ->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d'], true), 'Date range.', true) - ->inject('response') - ->inject('dbForInternal') - ->action(function ($bucketId, $range, $response, $dbForInternal) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForInternal */ - - // TODO: Check if the storage bucket exists else throw 404 - $stats = []; - if (App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') { - $period = [ - '24h' => [ - 'period' => '30m', + 'period' => '15m', 'limit' => 48, ], '7d' => [ @@ -742,12 +685,11 @@ App::get('/v1/storage/:bucketId/usage') Authorization::disable(); $metrics = [ - "storage.buckets.$bucketId.files.create", - "storage.buckets.$bucketId.files.read", - "storage.buckets.$bucketId.files.update", - "storage.buckets.$bucketId.files.delete" + "storage.total", + "storage.files.count" ]; + $stats = []; foreach ($metrics as $metric) { $requestDocs = $dbForInternal->find('stats', [ new Query('period', Query::TYPE_EQUAL, [$period[$range]['period']]), @@ -761,68 +703,94 @@ App::get('/v1/storage/:bucketId/usage') 'date' => $requestDoc->getAttribute('time'), ]; } - $stats[$metric] = array_reverse($stats[$metric]); } + $usage = new Document([ + 'range' => $range, + 'storage' => $stats['storage.total'], + 'files' => $stats['storage.files.count'] + ]); + } + + $response->dynamic($usage, Response::MODEL_STORAGE_USAGE); + }); + +App::get('/v1/storage/:bucketId/usage') + ->desc('Get usage stats for a storage bucket') + ->groups(['api', 'storage']) + ->label('scope', 'files.read') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'storage') + ->label('sdk.method', 'getUsage') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_BUCKETS_USAGE) + ->param('bucketId', '', new UID(), 'Bucket unique ID.') + ->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d'], true), 'Date range.', true) + ->inject('response') + ->inject('dbForInternal') + ->action(function ($bucketId, $range, $response, $dbForInternal) { + /** @var Appwrite\Utopia\Response $response */ + /** @var Utopia\Database\Database $dbForInternal */ + + // TODO: Check if the storage bucket exists else throw 404 + + $usage = []; + if (App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') { + $period = [ + '24h' => [ + 'period' => '30m', + 'limit' => 48, + ], + '7d' => [ + 'period' => '1d', + 'limit' => 7, + ], + '30d' => [ + 'period' => '1d', + 'limit' => 30, + ], + '90d' => [ + 'period' => '1d', + 'limit' => 90, + ], + ]; + + Authorization::disable(); + $metrics = [ + "storage.buckets.$bucketId.files.create", + "storage.buckets.$bucketId.files.read", + "storage.buckets.$bucketId.files.update", + "storage.buckets.$bucketId.files.delete" + ]; + + $stats = []; + foreach ($metrics as $metric) { + $requestDocs = $dbForInternal->find('stats', [ + new Query('period', Query::TYPE_EQUAL, [$period[$range]['period']]), + new Query('metric', Query::TYPE_EQUAL, [$metric]), + ], $period[$range]['limit'], 0, ['time'], [Database::ORDER_DESC]); + + $stats[$metric] = []; + foreach ($requestDocs as $requestDoc) { + $stats[$metric][] = [ + 'value' => $requestDoc->getAttribute('value'), + 'date' => $requestDoc->getAttribute('time'), + ]; + } + $stats[$metric] = array_reverse($stats[$metric]); + } Authorization::reset(); - $create = $stats["storage.buckets.$bucketId.files.create"] ?? []; - $read = $stats["storage.buckets.$bucketId.files.read"] ?? []; - $update = $stats["storage.buckets.$bucketId.files.update"] ?? []; - $delete = $stats["storage.buckets.$bucketId.files.delete"] ?? []; - - - // 'name' => [ - // [ - // [ - // 'value' => '', - // 'date' => 'unix timestamp' - // ] - // ] - // ] - - // $res = [ - // 'range' => '', - // 'name' => [ - // [ - // 'value' => , - // 'date' => - // ] - // ], - // 'nameTotal' => [ - - // ] - // ]; - - $response->json([ + $usage = new Document([ 'range' => $range, - 'create' => [ - 'data' => $create, - 'total' => \array_sum(\array_map(function ($item) { - return $item['value']; - }, $create)), - ], - 'read' => [ - 'data' => $read, - 'total' => \array_sum(\array_map(function ($item) { - return $item['value']; - }, $read)), - ], - 'update' => [ - 'data' => $update, - 'total' => \array_sum(\array_map(function ($item) { - return $item['value']; - }, $update)), - ], - 'delete' => [ - 'data' => $delete, - 'total' => \array_sum(\array_map(function ($item) { - return $item['value']; - }, $delete)), - ], + 'files.create' => $stats["storage.buckets.$bucketId.files.create"], + 'files.read' => $stats["storage.buckets.$bucketId.files.read"], + 'files.update' => $stats["storage.buckets.$bucketId.files.update"], + 'files.delete' => $stats["storage.buckets.$bucketId.files.delete"] ]); - } else { - $response->json([]); } + + $response->dynamic($usage, Response::MODEL_BUCKETS_USAGE); }); \ No newline at end of file diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 44799fdaa..811f07cb5 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -12,6 +12,7 @@ use Appwrite\Utopia\Response\Model\None; use Appwrite\Utopia\Response\Model\Any; use Appwrite\Utopia\Response\Model\Attribute; use Appwrite\Utopia\Response\Model\BaseList; +use Appwrite\Utopia\Response\Model\BucketsUsage; use Appwrite\Utopia\Response\Model\Collection; use Appwrite\Utopia\Response\Model\CollectionUsage; use Appwrite\Utopia\Response\Model\Continent; @@ -45,6 +46,7 @@ use Appwrite\Utopia\Response\Model\Token; use Appwrite\Utopia\Response\Model\Webhook; use Appwrite\Utopia\Response\Model\Preferences; use Appwrite\Utopia\Response\Model\Mock; // Keep last +use Appwrite\Utopia\Response\Model\StorageUsage; use stdClass; /** @@ -88,6 +90,8 @@ class Response extends SwooleResponse const MODEL_FILE = 'file'; const MODEL_FILE_LIST = 'fileList'; const MODEL_BUCKET = 'bucket'; // - Missing + const MODEL_BUCKETS_USAGE = 'bucketsUsage'; + const MODEL_STORAGE_USAGE = 'storageUsage'; // Locale const MODEL_LOCALE = 'locale'; @@ -198,6 +202,8 @@ class Response extends SwooleResponse ->setModel(new JWT()) ->setModel(new Locale()) ->setModel(new File()) + ->setModel(new StorageUsage()) + ->setModel(new BucketsUsage()) ->setModel(new Team()) ->setModel(new Membership()) ->setModel(new Func()) diff --git a/src/Appwrite/Utopia/Response/Model/BucketsUsage.php b/src/Appwrite/Utopia/Response/Model/BucketsUsage.php new file mode 100644 index 000000000..0fb923e14 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/BucketsUsage.php @@ -0,0 +1,70 @@ +addRule('range', [ + 'type' => self::TYPE_STRING, + 'description' => 'The time range of the usage stats.', + 'default' => '', + 'example' => '30d', + ]) + ->addRule('files.create', [ + 'type' => Response::MODEL_METRIC_LIST, + 'description' => 'Aggregated stats for files created.', + 'default' => [], + 'example' => new stdClass, + 'array' => true + ]) + ->addRule('files.read', [ + 'type' => Response::MODEL_METRIC_LIST, + 'description' => 'Aggregated stats for files read.', + 'default' => [], + 'example' => new stdClass, + 'array' => true + ]) + ->addRule('files.update', [ + 'type' => Response::MODEL_METRIC_LIST, + 'description' => 'Aggregated stats for files updated.', + 'default' => [], + 'example' => new stdClass, + 'array' => true + ]) + ->addRule('files.delete', [ + 'type' => Response::MODEL_METRIC_LIST, + 'description' => 'Aggregated stats for files deleted.', + 'default' => [], + 'example' => new stdClass, + 'array' => true + ]) + ; + } + + /** + * Get Name + * + * @return string + */ + public function getName():string + { + return 'BucketsUsage'; + } + + /** + * Get Collection + * + * @return string + */ + public function getType():string + { + return Response::MODEL_BUCKETS_USAGE; + } +} \ No newline at end of file diff --git a/src/Appwrite/Utopia/Response/Model/CollectionUsage.php b/src/Appwrite/Utopia/Response/Model/CollectionUsage.php index 2281b3d03..a0b0a51c9 100644 --- a/src/Appwrite/Utopia/Response/Model/CollectionUsage.php +++ b/src/Appwrite/Utopia/Response/Model/CollectionUsage.php @@ -12,10 +12,10 @@ class CollectionUsage extends Model { $this ->addRule('range', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'The value of this metric at a timestamp.', - 'default' => 0, - 'example' => 1, + 'type' => self::TYPE_STRING, + 'description' => 'The time range of the usage stats.', + 'default' => '', + 'example' => '30d', ]) ->addRule('documents.count', [ 'type' => Response::MODEL_METRIC_LIST, diff --git a/src/Appwrite/Utopia/Response/Model/DatabaseUsage.php b/src/Appwrite/Utopia/Response/Model/DatabaseUsage.php index 58d9575d7..1c2462500 100644 --- a/src/Appwrite/Utopia/Response/Model/DatabaseUsage.php +++ b/src/Appwrite/Utopia/Response/Model/DatabaseUsage.php @@ -12,10 +12,10 @@ class DatabaseUsage extends Model { $this ->addRule('range', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'The value of this metric at a timestamp.', - 'default' => 0, - 'example' => 1, + 'type' => self::TYPE_STRING, + 'description' => 'The time range of the usage stats.', + 'default' => '', + 'example' => '30d', ]) ->addRule('documents.count', [ 'type' => Response::MODEL_METRIC_LIST, diff --git a/src/Appwrite/Utopia/Response/Model/StorageUsage.php b/src/Appwrite/Utopia/Response/Model/StorageUsage.php new file mode 100644 index 000000000..e26e0d4b3 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/StorageUsage.php @@ -0,0 +1,56 @@ +addRule('range', [ + 'type' => self::TYPE_STRING, + 'description' => 'The time range of the usage stats.', + 'default' => '', + 'example' => '30d', + ]) + ->addRule('storage', [ + 'type' => Response::MODEL_METRIC_LIST, + 'description' => 'Aggregated stats for the occupied storage size.', + 'default' => [], + 'example' => new stdClass, + 'array' => true + ]) + ->addRule('files', [ + 'type' => Response::MODEL_METRIC_LIST, + 'description' => 'Aggregated stats for total number of files.', + 'default' => [], + 'example' => new stdClass, + 'array' => true + ]) + ; + } + + /** + * Get Name + * + * @return string + */ + public function getName():string + { + return 'StorageUsage'; + } + + /** + * Get Collection + * + * @return string + */ + public function getType():string + { + return Response::MODEL_STORAGE_USAGE; + } +} \ No newline at end of file