diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index ef11b4146..f5e974da0 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -39,7 +39,6 @@ use Appwrite\Detector\Detector; use Appwrite\Event\Audit as EventAudit; use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; -use Appwrite\Usage\Stats; use Utopia\Config\Config; use MaxMind\Db\Reader; @@ -50,7 +49,7 @@ use MaxMind\Db\Reader; * @return Document Newly created attribute document * @throws Exception */ -function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $database, Event $events, Stats $usage): Document +function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $database, Event $events): Document { $key = $attribute->getAttribute('key'); $type = $attribute->getAttribute('type', ''); @@ -122,10 +121,6 @@ function createAttribute(string $databaseId, string $collectionId, Document $att $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId); $dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); - $usage - ->setParam('databaseId', $databaseId) - ->setParam('collections.requests.update', 1); - $database ->setType(DATABASE_TYPE_CREATE_ATTRIBUTE) ->setDatabase($db) @@ -152,6 +147,7 @@ App::post('/v1/databases') ->label('event', 'databases.[databaseId].create') ->label('scope', 'databases.write') ->label('audits.resource', 'database/{response.$id}') + ->label('usage.metric', 'databases.{scope}.requests.create') ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'create') @@ -163,9 +159,8 @@ App::post('/v1/databases') ->param('name', '', new Text(128), 'Collection name. Max length: 128 chars.') ->inject('response') ->inject('dbForProject') - ->inject('usage') ->inject('events') - ->action(function (string $databaseId, string $name, Response $response, Database $dbForProject, Stats $usage, Event $events) { + ->action(function (string $databaseId, string $name, Response $response, Database $dbForProject, Event $events) { $databaseId = $databaseId == 'unique()' ? $dbForProject->getId() : $databaseId; @@ -214,7 +209,6 @@ App::post('/v1/databases') } $events->setParam('databaseId', $database->getId()); - $usage->setParam('databases.requests.create', 1); $response->setStatusCode(Response::STATUS_CODE_CREATED); $response->dynamic($database, Response::MODEL_DATABASE); @@ -224,6 +218,7 @@ App::get('/v1/databases') ->desc('List Databases') ->groups(['api', 'database']) ->label('scope', 'databases.read') + ->label('usage.metric', 'databases.{scope}.requests.read') ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'list') @@ -239,8 +234,7 @@ App::get('/v1/databases') ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForProject') - ->inject('usage') - ->action(function (string $search, int $limit, int $offset, string $cursor, string $cursorDirection, string $orderType, Response $response, Database $dbForProject, Stats $usage) { + ->action(function (string $search, int $limit, int $offset, string $cursor, string $cursorDirection, string $orderType, Response $response, Database $dbForProject) { if (!empty($cursor)) { $cursorDocument = $dbForProject->getDocument('databases', $cursor); @@ -256,8 +250,6 @@ App::get('/v1/databases') $queries[] = new Query('search', Query::TYPE_SEARCH, [$search]); } - $usage->setParam('databases.requests.read', 1); - $response->dynamic(new Document([ 'databases' => $dbForProject->find('databases', $queries, $limit, $offset, [], [$orderType], $cursorDocument ?? null, $cursorDirection), 'total' => $dbForProject->count('databases', $queries, APP_LIMIT_COUNT), @@ -268,6 +260,7 @@ App::get('/v1/databases/:databaseId') ->desc('Get Database') ->groups(['api', 'database']) ->label('scope', 'databases.read') + ->label('usage.metric', 'databases.{scope}.requests.read') ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'get') @@ -278,8 +271,7 @@ App::get('/v1/databases/:databaseId') ->param('databaseId', '', new UID(), 'Database ID.') ->inject('response') ->inject('dbForProject') - ->inject('usage') - ->action(function (string $databaseId, Response $response, Database $dbForProject, Stats $usage) { + ->action(function (string $databaseId, Response $response, Database $dbForProject) { $database = $dbForProject->getDocument('databases', $databaseId); @@ -287,8 +279,6 @@ App::get('/v1/databases/:databaseId') throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND); } - $usage->setParam('databases.requests.read', 1); - $response->dynamic($database, Response::MODEL_DATABASE); }); @@ -377,6 +367,7 @@ App::put('/v1/databases/:databaseId') ->label('scope', 'databases.write') ->label('event', 'databases.[databaseId].update') ->label('audits.resource', 'database/{response.$id}') + ->label('usage.metric', 'databases.{scope}.requests.update') ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'update') @@ -388,9 +379,8 @@ App::put('/v1/databases/:databaseId') ->param('name', null, new Text(128), 'Collection name. Max length: 128 chars.') ->inject('response') ->inject('dbForProject') - ->inject('usage') ->inject('events') - ->action(function (string $databaseId, string $name, Response $response, Database $dbForProject, Stats $usage, Event $events) { + ->action(function (string $databaseId, string $name, Response $response, Database $dbForProject, Event $events) { $database = $dbForProject->getDocument('databases', $databaseId); @@ -408,7 +398,6 @@ App::put('/v1/databases/:databaseId') throw new Exception('Bad structure. ' . $exception->getMessage(), 400, Exception::DOCUMENT_INVALID_STRUCTURE); } - $usage->setParam('databases.requests.update', 1); $events->setParam('databaseId', $database->getId()); $response->dynamic($database, Response::MODEL_DATABASE); @@ -420,6 +409,7 @@ App::delete('/v1/databases/:databaseId') ->label('scope', 'databases.write') ->label('event', 'databases.[databaseId].delete') ->label('audits.resource', 'database/{request.databaseId}') + ->label('usage.metric', 'databases.{scope}.requests.delete') ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'delete') @@ -432,8 +422,7 @@ App::delete('/v1/databases/:databaseId') ->inject('events') ->inject('audits') ->inject('deletes') - ->inject('usage') - ->action(function (string $databaseId, Response $response, Database $dbForProject, Event $events, EventAudit $audits, Delete $deletes, Stats $usage) { + ->action(function (string $databaseId, Response $response, Database $dbForProject, Event $events, EventAudit $audits, Delete $deletes) { $database = $dbForProject->getDocument('databases', $databaseId); @@ -459,8 +448,6 @@ App::delete('/v1/databases/:databaseId') $audits->setPayload($database->getArrayCopy()); - $usage->setParam('databases.requests.delete', 1); - $response->noContent(); }); @@ -471,6 +458,8 @@ App::post('/v1/databases/:databaseId/collections') ->label('event', 'databases.[databaseId].collections.[collectionId].create') ->label('scope', 'collections.write') ->label('audits.resource', 'database/{request.databaseId}/collection/{response.$id}') + ->label('usage.metric', 'collections.{scope}.requests.create') + ->label('usage.params', ['databaseId:request.databaseId']) ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'createCollection') @@ -486,9 +475,8 @@ App::post('/v1/databases/:databaseId/collections') ->param('write', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.') ->inject('response') ->inject('dbForProject') - ->inject('usage') ->inject('events') - ->action(function (string $databaseId, string $collectionId, string $name, ?string $permission, ?array $read, ?array $write, Response $response, Database $dbForProject, Stats $usage, Event $events) { + ->action(function (string $databaseId, string $collectionId, string $name, ?string $permission, ?array $read, ?array $write, Response $response, Database $dbForProject, Event $events) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -524,10 +512,6 @@ App::post('/v1/databases/:databaseId/collections') ->setParam('databaseId', $databaseId) ->setParam('collectionId', $collection->getId()); - $usage - ->setParam('databaseId', $databaseId) - ->setParam('collections.requests.create', 1); - $response->setStatusCode(Response::STATUS_CODE_CREATED); $response->dynamic($collection, Response::MODEL_COLLECTION); }); @@ -537,6 +521,8 @@ App::get('/v1/databases/:databaseId/collections') ->desc('List Collections') ->groups(['api', 'database']) ->label('scope', 'collections.read') + ->label('usage.metric', 'collections.{scope}.requests.read') + ->label('usage.params', ['databaseId:request.databaseId']) ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'listCollections') @@ -553,8 +539,7 @@ App::get('/v1/databases/:databaseId/collections') ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForProject') - ->inject('usage') - ->action(function (string $databaseId, string $search, int $limit, int $offset, string $cursor, string $cursorDirection, string $orderType, Response $response, Database $dbForProject, Stats $usage) { + ->action(function (string $databaseId, string $search, int $limit, int $offset, string $cursor, string $cursorDirection, string $orderType, Response $response, Database $dbForProject) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -576,10 +561,6 @@ App::get('/v1/databases/:databaseId/collections') $queries[] = new Query('search', Query::TYPE_SEARCH, [$search]); } - $usage - ->setParam('databaseId', $databaseId) - ->setParam('collections.requests.read', 1); - $response->dynamic(new Document([ 'collections' => $dbForProject->find('database_' . $database->getInternalId(), $queries, $limit, $offset, [], [$orderType], $cursorCollection ?? null, $cursorDirection), 'total' => $dbForProject->count('database_' . $database->getInternalId(), $queries, APP_LIMIT_COUNT), @@ -591,6 +572,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId') ->desc('Get Collection') ->groups(['api', 'database']) ->label('scope', 'collections.read') + ->label('usage.metric', 'collections.{scope}.requests.create') + ->label('usage.params', ['databaseId:request.databaseId']) ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'getCollection') @@ -602,8 +585,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId') ->param('collectionId', '', new UID(), 'Collection ID.') ->inject('response') ->inject('dbForProject') - ->inject('usage') - ->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject, Stats $usage) { + ->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -616,10 +598,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId') throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } - $usage - ->setParam('databaseId', $databaseId) - ->setParam('collections.requests.read', 1); - $response->dynamic($collection, Response::MODEL_COLLECTION); }); @@ -721,6 +699,8 @@ App::put('/v1/databases/:databaseId/collections/:collectionId') ->label('event', 'databases.[databaseId].collections.[collectionId].update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('audits-payload', true) + ->label('usage.metric', 'collections.{scope}.requests.update') + ->label('usage.params', ['databaseId:request.databaseId']) ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'updateCollection') @@ -737,9 +717,8 @@ App::put('/v1/databases/:databaseId/collections/:collectionId') ->param('enabled', true, new Boolean(), 'Is collection enabled?', true) ->inject('response') ->inject('dbForProject') - ->inject('usage') ->inject('events') - ->action(function (string $databaseId, string $collectionId, string $name, string $permission, ?array $read, ?array $write, bool $enabled, Response $response, Database $dbForProject, Stats $usage, Event $events) { + ->action(function (string $databaseId, string $collectionId, string $name, string $permission, ?array $read, ?array $write, bool $enabled, Response $response, Database $dbForProject, Event $events) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -770,10 +749,6 @@ App::put('/v1/databases/:databaseId/collections/:collectionId') throw new Exception('Bad structure. ' . $exception->getMessage(), 400, Exception::DOCUMENT_INVALID_STRUCTURE); } - $usage - ->setParam('databaseId', $databaseId) - ->setParam('collections.requests.update', 1); - $events ->setContext('database', $database) ->setParam('databaseId', $databaseId) @@ -789,6 +764,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId') ->label('scope', 'collections.write') ->label('event', 'databases.[databaseId].collections.[collectionId].delete') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('usage.metric', 'collections.{scope}.requests.delete') + ->label('usage.params', ['databaseId:request.databaseId']) ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'deleteCollection') @@ -802,8 +779,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId') ->inject('events') ->inject('audits') ->inject('deletes') - ->inject('usage') - ->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject, Event $events, EventAudit $audits, Delete $deletes, Stats $usage) { + ->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject, Event $events, EventAudit $audits, Delete $deletes) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -837,10 +813,6 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId') $audits->setPayload($collection->getArrayCopy()); - $usage - ->setParam('databaseId', $databaseId) - ->setParam('collections.collections.delete', 1); - $response->noContent(); }); @@ -851,6 +823,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') ->label('scope', 'collections.write') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('usage.metric', 'collections.{scope}.requests.update') + ->label('usage.params', ['databaseId:request.databaseId']) ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'createStringAttribute') @@ -868,9 +842,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string ->inject('response') ->inject('dbForProject') ->inject('database') - ->inject('usage') ->inject('events') - ->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Stats $usage, Event $events) { + ->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { // Ensure attribute default is within required size $validator = new Text($size); @@ -885,7 +858,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string 'required' => $required, 'default' => $default, 'array' => $array, - ]), $response, $dbForProject, $database, $events, $usage); + ]), $response, $dbForProject, $database, $events); $response->dynamic($attribute, Response::MODEL_ATTRIBUTE_STRING); }); @@ -897,6 +870,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email' ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') ->label('scope', 'collections.write') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('usage.metric', 'collections.{scope}.requests.update') + ->label('usage.params', ['databaseId:request.databaseId']) ->label('sdk.namespace', 'databases') ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.method', 'createEmailAttribute') @@ -913,9 +888,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email' ->inject('response') ->inject('dbForProject') ->inject('database') - ->inject('usage') ->inject('events') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Stats $usage, Event $events) { + ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { $attribute = createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, @@ -925,7 +899,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email' 'default' => $default, 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_EMAIL, - ]), $response, $dbForProject, $database, $events, $usage); + ]), $response, $dbForProject, $database, $events); $response->dynamic($attribute, Response::MODEL_ATTRIBUTE_EMAIL); }); @@ -937,6 +911,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum') ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') ->label('scope', 'collections.write') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('usage.metric', 'collections.{scope}.requests.update') + ->label('usage.params', ['databaseId:request.databaseId']) ->label('sdk.namespace', 'databases') ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.method', 'createEnumAttribute') @@ -954,9 +930,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum') ->inject('response') ->inject('dbForProject') ->inject('database') - ->inject('usage') ->inject('events') - ->action(function (string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Stats $usage, Event $events) { + ->action(function (string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { // use length of longest string as attribute size $size = 0; @@ -981,7 +956,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum') 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_ENUM, 'formatOptions' => ['elements' => $elements], - ]), $response, $dbForProject, $database, $events, $usage); + ]), $response, $dbForProject, $database, $events); $response->dynamic($attribute, Response::MODEL_ATTRIBUTE_ENUM); }); @@ -993,6 +968,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/ip') ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') ->label('scope', 'collections.write') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('usage.metric', 'collections.{scope}.requests.update') + ->label('usage.params', ['databaseId:request.databaseId']) ->label('sdk.namespace', 'databases') ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.method', 'createIpAttribute') @@ -1009,9 +986,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/ip') ->inject('response') ->inject('dbForProject') ->inject('database') - ->inject('usage') ->inject('events') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Stats $usage, Event $events) { + ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { $attribute = createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, @@ -1021,7 +997,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/ip') 'default' => $default, 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_IP, - ]), $response, $dbForProject, $database, $events, $usage); + ]), $response, $dbForProject, $database, $events); $response->dynamic($attribute, Response::MODEL_ATTRIBUTE_IP); }); @@ -1033,6 +1009,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/url') ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') ->label('scope', 'collections.write') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('usage.metric', 'collections.{scope}.requests.update') + ->label('usage.params', ['databaseId:request.databaseId']) ->label('sdk.namespace', 'databases') ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.method', 'createUrlAttribute') @@ -1049,9 +1027,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/url') ->inject('response') ->inject('dbForProject') ->inject('database') - ->inject('usage') ->inject('events') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Stats $usage, Event $events) { + ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { $attribute = createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, @@ -1061,7 +1038,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/url') 'default' => $default, 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_URL, - ]), $response, $dbForProject, $database, $events, $usage); + ]), $response, $dbForProject, $database, $events); $response->dynamic($attribute, Response::MODEL_ATTRIBUTE_URL); }); @@ -1073,6 +1050,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') ->label('scope', 'collections.write') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('usage.metric', 'collections.{scope}.requests.update') + ->label('usage.params', ['databaseId:request.databaseId']) ->label('sdk.namespace', 'databases') ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.method', 'createIntegerAttribute') @@ -1091,9 +1070,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege ->inject('response') ->inject('dbForProject') ->inject('database') - ->inject('usage') ->inject('events') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Stats $usage, Event $events) { + ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { // Ensure attribute default is within range $min = (is_null($min)) ? PHP_INT_MIN : \intval($min); @@ -1123,7 +1101,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege 'min' => $min, 'max' => $max, ], - ]), $response, $dbForProject, $database, $events, $usage); + ]), $response, $dbForProject, $database, $events); $formatOptions = $attribute->getAttribute('formatOptions', []); @@ -1142,6 +1120,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float' ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') ->label('scope', 'collections.write') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('usage.metric', 'collections.{scope}.requests.update') + ->label('usage.params', ['databaseId:request.databaseId']) ->label('sdk.namespace', 'databases') ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.method', 'createFloatAttribute') @@ -1161,8 +1141,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float' ->inject('dbForProject') ->inject('database') ->inject('events') - ->inject('usage') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events, Stats $usage) { + ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { // Ensure attribute default is within range $min = (is_null($min)) ? -PHP_FLOAT_MAX : \floatval($min); @@ -1195,7 +1174,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float' 'min' => $min, 'max' => $max, ], - ]), $response, $dbForProject, $database, $events, $usage); + ]), $response, $dbForProject, $database, $events); $formatOptions = $attribute->getAttribute('formatOptions', []); @@ -1214,6 +1193,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/boolea ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') ->label('scope', 'collections.write') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('usage.metric', 'collections.{scope}.requests.update') + ->label('usage.params', ['databaseId:request.databaseId']) ->label('sdk.namespace', 'databases') ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.method', 'createBooleanAttribute') @@ -1230,9 +1211,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/boolea ->inject('response') ->inject('dbForProject') ->inject('database') - ->inject('usage') ->inject('events') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Stats $usage, Event $events) { + ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { $attribute = createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, @@ -1241,7 +1221,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/boolea 'required' => $required, 'default' => $default, 'array' => $array, - ]), $response, $dbForProject, $database, $events, $usage); + ]), $response, $dbForProject, $database, $events); $response->dynamic($attribute, Response::MODEL_ATTRIBUTE_BOOLEAN); }); @@ -1251,6 +1231,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') ->desc('List Attributes') ->groups(['api', 'database']) ->label('scope', 'collections.read') + ->label('usage.metric', 'collections.{scope}.requests.read') + ->label('usage.params', ['databaseId:request.databaseId']) ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'listAttributes') @@ -1262,8 +1244,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->inject('response') ->inject('dbForProject') - ->inject('usage') - ->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject, Stats $usage) { + ->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -1278,10 +1259,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') $attributes = $collection->getAttribute('attributes'); - $usage - ->setParam('databaseId', $databaseId) - ->setParam('collections.requests.read', 1); - $response->dynamic(new Document([ 'total' => \count($attributes), 'attributes' => $attributes @@ -1293,6 +1270,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') ->desc('Get Attribute') ->groups(['api', 'database']) ->label('scope', 'collections.read') + ->label('usage.metric', 'collections.{scope}.requests.read') + ->label('usage.params', ['databaseId:request.databaseId']) ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'getAttribute') @@ -1313,8 +1292,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') ->param('key', '', new Key(), 'Attribute Key.') ->inject('response') ->inject('dbForProject') - ->inject('usage') - ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, Stats $usage) { + ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -1352,10 +1330,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') default => Response::MODEL_ATTRIBUTE, }; - $usage - ->setParam('databaseId', $databaseId) - ->setParam('collections.requests.read', 1); - $response->dynamic($attribute, $model); }); @@ -1366,6 +1340,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key ->label('scope', 'collections.write') ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].delete') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('usage.metric', 'collections.{scope}.requests.update') + ->label('usage.params', ['databaseId:request.databaseId']) ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'deleteAttribute') @@ -1380,8 +1356,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key ->inject('database') ->inject('events') ->inject('audits') - ->inject('usage') - ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $database, Event $events, EventAudit $audits, Stats $usage) { + ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $database, Event $events, EventAudit $audits) { $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -1415,10 +1390,6 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key ->setDocument($attribute) ; - $usage - ->setParam('databaseId', $databaseId) - ->setParam('collections.requests.update', 1); - // Select response model based on type and format $type = $attribute->getAttribute('type'); $format = $attribute->getAttribute('format'); @@ -1458,6 +1429,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') ->label('event', 'databases.[databaseId].collections.[collectionId].indexes.[indexId].create') ->label('scope', 'collections.write') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('usage.metric', 'collections.{scope}.requests.update') + ->label('usage.params', ['databaseId:request.databaseId']) ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'createIndex') @@ -1474,9 +1447,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') ->inject('response') ->inject('dbForProject') ->inject('database') - ->inject('usage') ->inject('events') - ->action(function (string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, Response $response, Database $dbForProject, EventDatabase $database, Stats $usage, Event $events) { + ->action(function (string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -1586,10 +1558,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') ->setDocument($index) ; - $usage - ->setParam('databaseId', $databaseId) - ->setParam('collections.requests.update', 1); - $events ->setParam('databaseId', $databaseId) ->setParam('collectionId', $collection->getId()) @@ -1607,6 +1575,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') ->desc('List Indexes') ->groups(['api', 'database']) ->label('scope', 'collections.read') + ->label('usage.metric', 'collections.{scope}.requests.read') + ->label('usage.params', ['databaseId:request.databaseId']) ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'listIndexes') @@ -1618,8 +1588,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->inject('response') ->inject('dbForProject') - ->inject('usage') - ->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject, Stats $usage) { + ->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -1634,10 +1603,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') $indexes = $collection->getAttribute('indexes'); - $usage - ->setParam('databaseId', $databaseId) - ->setParam('collections.requests.read', 1); - $response->dynamic(new Document([ 'total' => \count($indexes), 'indexes' => $indexes, @@ -1649,6 +1614,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') ->desc('Get Index') ->groups(['api', 'database']) ->label('scope', 'collections.read') + ->label('usage.metric', 'collections.{scope}.requests.read') + ->label('usage.params', ['databaseId:request.databaseId']) ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'getIndex') @@ -1661,8 +1628,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') ->param('key', null, new Key(), 'Index Key.') ->inject('response') ->inject('dbForProject') - ->inject('usage') - ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, Stats $usage) { + ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -1688,10 +1654,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') 'collectionId' => $database->getInternalId() . '_' . $collectionId, ])]); - $usage - ->setParam('databaseId', $databaseId) - ->setParam('collections.requests.read', 1); - $response->dynamic($index, Response::MODEL_INDEX); }); @@ -1702,6 +1664,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') ->label('scope', 'collections.write') ->label('event', 'databases.[databaseId].collections.[collectionId].indexes.[indexId].delete') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('usage.metric', 'collections.{scope}.requests.update') + ->label('usage.params', ['databaseId:request.databaseId']) ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'deleteIndex') @@ -1716,8 +1680,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') ->inject('database') ->inject('events') ->inject('audits') - ->inject('usage') - ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $database, Event $events, EventAudit $audits, Stats $usage) { + ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $database, Event $events, EventAudit $audits) { $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -1750,10 +1713,6 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') ->setDocument($index) ; - $usage - ->setParam('databaseId', $databaseId) - ->setParam('collections.requests.update', 1); - $events ->setParam('databaseId', $databaseId) ->setParam('collectionId', $collection->getId()) @@ -1775,6 +1734,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].create') ->label('scope', 'documents.write') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('usage.metric', 'documents.{scope}.requests.create') + ->label('usage.params', ['databaseId:request.databaseId', 'collectionId:request.collectionId']) ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'createDocument') @@ -1791,10 +1752,9 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') ->inject('response') ->inject('dbForProject') ->inject('user') - ->inject('usage') ->inject('events') ->inject('mode') - ->action(function (string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $read, ?array $write, Response $response, Database $dbForProject, Document $user, Stats $usage, Event $events, string $mode) { + ->action(function (string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $read, ?array $write, Response $response, Database $dbForProject, Document $user, Event $events, string $mode) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -1876,12 +1836,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') ->setContext('database', $database) ; - $usage - ->setParam('documents.requests.create', 1) - ->setParam('databaseId', $databaseId) - ->setParam('collectionId', $collectionId) - ; - $response->setStatusCode(Response::STATUS_CODE_CREATED); $response->dynamic($document, Response::MODEL_DOCUMENT); }); @@ -1891,6 +1845,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') ->desc('List Documents') ->groups(['api', 'database']) ->label('scope', 'documents.read') + ->label('usage.metric', 'documents.{scope}.requests.read') + ->label('usage.params', ['databaseId:request.databaseId', 'collectionId:request.collectionId']) ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'listDocuments') @@ -1909,9 +1865,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') ->param('orderTypes', [], new ArrayList(new WhiteList(['DESC', 'ASC'], true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of order directions for sorting attribtues. Possible values are DESC for descending order, or ASC for ascending order. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' order types are allowed.', true) ->inject('response') ->inject('dbForProject') - ->inject('usage') ->inject('mode') - ->action(function (string $databaseId, string $collectionId, array $queries, int $limit, int $offset, string $cursor, string $cursorDirection, array $orderAttributes, array $orderTypes, Response $response, Database $dbForProject, Stats $usage, string $mode) { + ->action(function (string $databaseId, string $collectionId, array $queries, int $limit, int $offset, string $cursor, string $cursorDirection, array $orderAttributes, array $orderTypes, Response $response, Database $dbForProject, string $mode) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -1988,12 +1943,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') */ $documents = array_map(fn(Document $document) => $document->setAttribute('$collection', $collectionId), $documents); - $usage - ->setParam('documents.requests.read', 1) - ->setParam('databaseId', $databaseId) - ->setParam('collectionId', $collectionId) - ; - $response->dynamic(new Document([ 'total' => $total, 'documents' => $documents, @@ -2005,6 +1954,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->desc('Get Document') ->groups(['api', 'database']) ->label('scope', 'documents.read') + ->label('usage.metric', 'documents.{scope}.requests.read') + ->label('usage.params', ['databaseId:request.databaseId', 'collectionId:request.collectionId']) ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'getDocument') @@ -2017,9 +1968,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->param('documentId', null, new UID(), 'Document ID.') ->inject('response') ->inject('dbForProject') - ->inject('usage') ->inject('mode') - ->action(function (string $databaseId, string $collectionId, string $documentId, Response $response, Database $dbForProject, Stats $usage, string $mode) { + ->action(function (string $databaseId, string $collectionId, string $documentId, Response $response, Database $dbForProject, string $mode) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -2061,12 +2011,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception('No document found', 404, Exception::DOCUMENT_NOT_FOUND); } - $usage - ->setParam('documents.requests.read', 1) - ->setParam('databaseId', $databaseId) - ->setParam('collectionId', $collectionId) - ; - $response->dynamic($document, Response::MODEL_DOCUMENT); }); @@ -2171,6 +2115,8 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].update') ->label('scope', 'documents.write') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}/document/{response.$id}') + ->label('usage.metric', 'documents.{scope}.requests.update') + ->label('usage.params', ['databaseId:request.databaseId', 'collectionId:request.collectionId']) ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'updateDocument') @@ -2186,10 +2132,9 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum ->param('write', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with write permissions. By default inherits the existing write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) ->inject('response') ->inject('dbForProject') - ->inject('usage') ->inject('events') ->inject('mode') - ->action(function (string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $read, ?array $write, Response $response, Database $dbForProject, Stats $usage, Event $events, string $mode) { + ->action(function (string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $read, ?array $write, Response $response, Database $dbForProject, Event $events, string $mode) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -2289,12 +2234,6 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum ->setContext('database', $database) ; - $usage - ->setParam('documents.requests.update', 1) - ->setParam('databaseId', $databaseId) - ->setParam('collectionId', $collectionId) - ; - $response->dynamic($document, Response::MODEL_DOCUMENT); }); @@ -2305,6 +2244,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu ->label('scope', 'documents.write') ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].delete') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}/document/{request.documentId}') + ->label('usage.metric', 'documents.{scope}.requests.delete') + ->label('usage.params', ['databaseId:request.databaseId', 'collectionId:request.collectionId']) ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'deleteDocument') @@ -2319,9 +2260,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu ->inject('events') ->inject('audits') ->inject('deletes') - ->inject('usage') ->inject('mode') - ->action(function (string $databaseId, string $collectionId, string $documentId, Response $response, Database $dbForProject, Event $events, EventAudit $audits, Delete $deletes, Stats $usage, string $mode) { + ->action(function (string $databaseId, string $collectionId, string $documentId, Response $response, Database $dbForProject, Event $events, EventAudit $audits, Delete $deletes, string $mode) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -2376,12 +2316,6 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu ->setDocument($document) ; - $usage - ->setParam('documents.requests.delete', 1) - ->setParam('databaseId', $databaseId) - ->setParam('collectionId', $collectionId) - ; - $events ->setParam('databaseId', $databaseId) ->setParam('collectionId', $collection->getId())