Merge pull request #3422 from appwrite/feat-database-layer-alias

Add alias to Database Layer
This commit is contained in:
Torsten Dittmann 2022-06-23 11:00:32 +02:00 committed by GitHub
commit 3f1b906de0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -482,6 +482,7 @@ App::delete('/v1/databases/:databaseId')
});
App::post('/v1/databases/:databaseId/collections')
->alias('/v1/database/collections', ['databaseId' => 'default'])
->desc('Create Collection')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].create')
@ -554,6 +555,7 @@ App::post('/v1/databases/:databaseId/collections')
});
App::get('/v1/databases/:databaseId/collections')
->alias('/v1/database/collections', ['databaseId' => 'default'])
->desc('List Collections')
->groups(['api', 'database'])
->label('scope', 'collections.read')
@ -607,6 +609,7 @@ App::get('/v1/databases/:databaseId/collections')
});
App::get('/v1/databases/:databaseId/collections/:collectionId')
->alias('/v1/database/collections/:collectionId', ['databaseId' => 'default'])
->desc('Get Collection')
->groups(['api', 'database'])
->label('scope', 'collections.read')
@ -643,6 +646,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId')
});
App::get('/v1/databases/:databaseId/collections/:collectionId/logs')
->alias('/v1/database/collections/:collectionId/logs', ['databaseId' => 'default'])
->desc('List Collection Logs')
->groups(['api', 'database'])
->label('scope', 'collections.read')
@ -732,6 +736,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs')
App::put('/v1/databases/:databaseId/collections/:collectionId')
->alias('/v1/database/collections/:collectionId', ['databaseId' => 'default'])
->desc('Update Collection')
->groups(['api', 'database'])
->label('scope', 'collections.write')
@ -804,6 +809,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId')
});
App::delete('/v1/databases/:databaseId/collections/:collectionId')
->alias('/v1/database/collections/:collectionId', ['databaseId' => 'default'])
->desc('Delete Collection')
->groups(['api', 'database'])
->label('scope', 'collections.write')
@ -867,6 +873,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId')
});
App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string')
->alias('/v1/database/collections/:collectionId/attributes/string', ['databaseId' => 'default'])
->desc('Create String Attribute')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create')
@ -912,6 +919,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string
});
App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email')
->alias('/v1/database/collections/:collectionId/attributes/email', ['databaseId' => 'default'])
->desc('Create Email Attribute')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create')
@ -951,6 +959,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email'
});
App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum')
->alias('/v1/database/collections/:collectionId/attributes/enum', ['databaseId' => 'default'])
->desc('Create Enum Attribute')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create')
@ -1006,6 +1015,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum')
});
App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/ip')
->alias('/v1/database/collections/:collectionId/attributes/ip', ['databaseId' => 'default'])
->desc('Create IP Address Attribute')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create')
@ -1045,6 +1055,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/ip')
});
App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/url')
->alias('/v1/database/collections/:collectionId/attributes/url', ['databaseId' => 'default'])
->desc('Create URL Attribute')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create')
@ -1084,6 +1095,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/url')
});
App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/integer')
->alias('/v1/database/collections/:collectionId/attributes/integer', ['databaseId' => 'default'])
->desc('Create Integer Attribute')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create')
@ -1152,6 +1164,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege
});
App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float')
->alias('/v1/database/collections/:collectionId/attributes/float', ['databaseId' => 'default'])
->desc('Create Float Attribute')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create')
@ -1223,6 +1236,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float'
});
App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/boolean')
->alias('/v1/database/collections/:collectionId/attributes/boolean', ['databaseId' => 'default'])
->desc('Create Boolean Attribute')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create')
@ -1261,6 +1275,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/boolea
});
App::get('/v1/databases/:databaseId/collections/:collectionId/attributes')
->alias('/v1/database/collections/:collectionId/attributes', ['databaseId' => 'default'])
->desc('List Attributes')
->groups(['api', 'database'])
->label('scope', 'collections.read')
@ -1302,6 +1317,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes')
});
App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key')
->alias('/v1/database/collections/:collectionId/attributes/:key', ['databaseId' => 'default'])
->desc('Get Attribute')
->groups(['api', 'database'])
->label('scope', 'collections.read')
@ -1372,6 +1388,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key')
});
App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key')
->alias('/v1/database/collections/:collectionId/attributes/:key', ['databaseId' => 'default'])
->desc('Delete Attribute')
->groups(['api', 'database'])
->label('scope', 'collections.write')
@ -1465,6 +1482,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key
});
App::post('/v1/databases/:databaseId/collections/:collectionId/indexes')
->alias('/v1/database/collections/:collectionId/indexes', ['databaseId' => 'default'])
->desc('Create Index')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].indexes.[indexId].create')
@ -1588,6 +1606,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes')
});
App::get('/v1/databases/:databaseId/collections/:collectionId/indexes')
->alias('/v1/database/collections/:collectionId/indexes', ['databaseId' => 'default'])
->desc('List Indexes')
->groups(['api', 'database'])
->label('scope', 'collections.read')
@ -1629,6 +1648,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes')
});
App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key')
->alias('/v1/database/collections/:collectionId/indexes/:key', ['databaseId' => 'default'])
->desc('Get Index')
->groups(['api', 'database'])
->label('scope', 'collections.read')
@ -1679,6 +1699,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key')
});
App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key')
->alias('/v1/database/collections/:collectionId/indexes/:key', ['databaseId' => 'default'])
->desc('Delete Index')
->groups(['api', 'database'])
->label('scope', 'collections.write')
@ -1753,6 +1774,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key')
});
App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
->alias('/v1/database/collections/:collectionId/documents', ['databaseId' => 'default'])
->desc('Create Document')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].create')
@ -1875,6 +1897,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
});
App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
->alias('/v1/database/collections/:collectionId/documents', ['databaseId' => 'default'])
->desc('List Documents')
->groups(['api', 'database'])
->label('scope', 'documents.read')
@ -1988,6 +2011,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
});
App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId')
->alias('/v1/database/collections/:collectionId/documents/:documentId', ['databaseId' => 'default'])
->desc('Get Document')
->groups(['api', 'database'])
->label('scope', 'documents.read')
@ -2057,6 +2081,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
});
App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId/logs')
->alias('/v1/database/collections/:collectionId/documents/:documentId/logs', ['databaseId' => 'default'])
->desc('List Document Logs')
->groups(['api', 'database'])
->label('scope', 'documents.read')
@ -2150,6 +2175,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
});
App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId')
->alias('/v1/database/collections/:collectionId/documents/:documentId', ['databaseId' => 'default'])
->desc('Update Document')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].update')
@ -2287,6 +2313,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
});
App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId')
->alias('/v1/database/collections/:collectionId/documents/:documentId', ['databaseId' => 'default'])
->desc('Delete Document')
->groups(['api', 'database'])
->label('scope', 'documents.write')
@ -2386,330 +2413,331 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu
});
App::get('/v1/databases/usage')
->desc('Get usage stats for the database')
->groups(['api', 'database'])
->label('scope', 'collections.read')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'databases')
->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_USAGE_DATABASES)
->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d'], true), '`Date range.', true)
->inject('response')
->inject('dbForProject')
->action(function (string $range, Response $response, Database $dbForProject) {
->desc('Get usage stats for the database')
->groups(['api', 'database'])
->label('scope', 'collections.read')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'databases')
->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_USAGE_DATABASES)
->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d'], true), '`Date range.', true)
->inject('response')
->inject('dbForProject')
->action(function (string $range, Response $response, Database $dbForProject) {
$usage = [];
if (App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') {
$periods = [
'24h' => [
'period' => '30m',
'limit' => 48,
],
'7d' => [
'period' => '1d',
'limit' => 7,
],
'30d' => [
'period' => '1d',
'limit' => 30,
],
'90d' => [
'period' => '1d',
'limit' => 90,
],
];
$usage = [];
if (App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') {
$periods = [
'24h' => [
'period' => '30m',
'limit' => 48,
],
'7d' => [
'period' => '1d',
'limit' => 7,
],
'30d' => [
'period' => '1d',
'limit' => 30,
],
'90d' => [
'period' => '1d',
'limit' => 90,
],
];
$metrics = [
'databases.count',
'databases.documents.count',
'databases.collections.count',
'databases.create',
'databases.read',
'databases.update',
'databases.delete',
'databases.collections.create',
'databases.collections.read',
'databases.collections.update',
'databases.collections.delete',
'databases.documents.create',
'databases.documents.read',
'databases.documents.update',
'databases.documents.delete'
];
$metrics = [
'databases.count',
'databases.documents.count',
'databases.collections.count',
'databases.create',
'databases.read',
'databases.update',
'databases.delete',
'databases.collections.create',
'databases.collections.read',
'databases.collections.update',
'databases.collections.delete',
'databases.documents.create',
'databases.documents.read',
'databases.documents.update',
'databases.documents.delete'
];
$stats = [];
$stats = [];
Authorization::skip(function () use ($dbForProject, $periods, $range, $metrics, &$stats) {
foreach ($metrics as $metric) {
$limit = $periods[$range]['limit'];
$period = $periods[$range]['period'];
Authorization::skip(function () use ($dbForProject, $periods, $range, $metrics, &$stats) {
foreach ($metrics as $metric) {
$limit = $periods[$range]['limit'];
$period = $periods[$range]['period'];
$requestDocs = $dbForProject->find('stats', [
new Query('period', Query::TYPE_EQUAL, [$period]),
new Query('metric', Query::TYPE_EQUAL, [$metric]),
], $limit, 0, ['time'], [Database::ORDER_DESC]);
$requestDocs = $dbForProject->find('stats', [
new Query('period', Query::TYPE_EQUAL, [$period]),
new Query('metric', Query::TYPE_EQUAL, [$metric]),
], $limit, 0, ['time'], [Database::ORDER_DESC]);
$stats[$metric] = [];
foreach ($requestDocs as $requestDoc) {
$stats[$metric][] = [
'value' => $requestDoc->getAttribute('value'),
'date' => $requestDoc->getAttribute('time'),
];
$stats[$metric] = [];
foreach ($requestDocs as $requestDoc) {
$stats[$metric][] = [
'value' => $requestDoc->getAttribute('value'),
'date' => $requestDoc->getAttribute('time'),
];
}
// backfill metrics with empty values for graphs
$backfill = $limit - \count($requestDocs);
while ($backfill > 0) {
$last = $limit - $backfill - 1; // array index of last added metric
$diff = match ($period) { // convert period to seconds for unix timestamp math
'30m' => 1800,
'1d' => 86400,
};
$stats[$metric][] = [
'value' => 0,
'date' => ($stats[$metric][$last]['date'] ?? \time()) - $diff, // time of last metric minus period
];
$backfill--;
}
// TODO@kodumbeats explore performance if query is ordered by time ASC
$stats[$metric] = array_reverse($stats[$metric]);
}
});
// backfill metrics with empty values for graphs
$backfill = $limit - \count($requestDocs);
while ($backfill > 0) {
$last = $limit - $backfill - 1; // array index of last added metric
$diff = match ($period) { // convert period to seconds for unix timestamp math
'30m' => 1800,
'1d' => 86400,
};
$stats[$metric][] = [
'value' => 0,
'date' => ($stats[$metric][$last]['date'] ?? \time()) - $diff, // time of last metric minus period
];
$backfill--;
}
// TODO@kodumbeats explore performance if query is ordered by time ASC
$stats[$metric] = array_reverse($stats[$metric]);
}
});
$usage = new Document([
'range' => $range,
'databasesCount' => $stats["databases.count"],
'documentsCount' => $stats["databases.documents.count"],
'collectionsCount' => $stats["databases.collections.count"],
'documentsCreate' => $stats["databases.documents.create"],
'documentsRead' => $stats["databases.documents.read"],
'documentsUpdate' => $stats["databases.documents.update"],
'documentsDelete' => $stats["databases.documents.delete"],
'collectionsCreate' => $stats["databases.collections.create"],
'collectionsRead' => $stats["databases.collections.read"],
'collectionsUpdate' => $stats["databases.collections.update"],
'collectionsDelete' => $stats["databases.collections.delete"],
'databasesCreate' => $stats["databases.create"],
'databasesRead' => $stats["databases.read"],
'databasesUpdate' => $stats["databases.update"],
'databasesDelete' => $stats["databases.delete"],
]);
}
$usage = new Document([
'range' => $range,
'databasesCount' => $stats["databases.count"],
'documentsCount' => $stats["databases.documents.count"],
'collectionsCount' => $stats["databases.collections.count"],
'documentsCreate' => $stats["databases.documents.create"],
'documentsRead' => $stats["databases.documents.read"],
'documentsUpdate' => $stats["databases.documents.update"],
'documentsDelete' => $stats["databases.documents.delete"],
'collectionsCreate' => $stats["databases.collections.create"],
'collectionsRead' => $stats["databases.collections.read"],
'collectionsUpdate' => $stats["databases.collections.update"],
'collectionsDelete' => $stats["databases.collections.delete"],
'databasesCreate' => $stats["databases.create"],
'databasesRead' => $stats["databases.read"],
'databasesUpdate' => $stats["databases.update"],
'databasesDelete' => $stats["databases.delete"],
]);
}
$response->dynamic($usage, Response::MODEL_USAGE_DATABASES);
});
$response->dynamic($usage, Response::MODEL_USAGE_DATABASES);
});
App::get('/v1/databases/:databaseId/usage')
->desc('Get usage stats for the database')
->groups(['api', 'database'])
->label('scope', 'collections.read')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'getDatabaseUsage')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_USAGE_DATABASE)
->param('databaseId', '', new UID(), 'Database ID.')
->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d'], true), '`Date range.', true)
->inject('response')
->inject('dbForProject')
->action(function (string $databaseId, string $range, Response $response, Database $dbForProject) {
->desc('Get usage stats for the database')
->groups(['api', 'database'])
->label('scope', 'collections.read')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'getDatabaseUsage')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_USAGE_DATABASE)
->param('databaseId', '', new UID(), 'Database ID.')
->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d'], true), '`Date range.', true)
->inject('response')
->inject('dbForProject')
->action(function (string $databaseId, string $range, Response $response, Database $dbForProject) {
$usage = [];
if (App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') {
$periods = [
'24h' => [
'period' => '30m',
'limit' => 48,
],
'7d' => [
'period' => '1d',
'limit' => 7,
],
'30d' => [
'period' => '1d',
'limit' => 30,
],
'90d' => [
'period' => '1d',
'limit' => 90,
],
];
$usage = [];
if (App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') {
$periods = [
'24h' => [
'period' => '30m',
'limit' => 48,
],
'7d' => [
'period' => '1d',
'limit' => 7,
],
'30d' => [
'period' => '1d',
'limit' => 30,
],
'90d' => [
'period' => '1d',
'limit' => 90,
],
];
$metrics = [
'databases.' . $databaseId . '.documents.count',
'databases.' . $databaseId . '.collections.count',
'databases.' . $databaseId . '.collections.create',
'databases.' . $databaseId . '.collections.read',
'databases.' . $databaseId . '.collections.update',
'databases.' . $databaseId . '.collections.delete',
'databases.' . $databaseId . '.documents.create',
'databases.' . $databaseId . '.documents.read',
'databases.' . $databaseId . '.documents.update',
'databases.' . $databaseId . '.documents.delete'
];
$metrics = [
'databases.' . $databaseId . '.documents.count',
'databases.' . $databaseId . '.collections.count',
'databases.' . $databaseId . '.collections.create',
'databases.' . $databaseId . '.collections.read',
'databases.' . $databaseId . '.collections.update',
'databases.' . $databaseId . '.collections.delete',
'databases.' . $databaseId . '.documents.create',
'databases.' . $databaseId . '.documents.read',
'databases.' . $databaseId . '.documents.update',
'databases.' . $databaseId . '.documents.delete'
];
$stats = [];
$stats = [];
Authorization::skip(function () use ($dbForProject, $periods, $range, $metrics, &$stats) {
foreach ($metrics as $metric) {
$limit = $periods[$range]['limit'];
$period = $periods[$range]['period'];
Authorization::skip(function () use ($dbForProject, $periods, $range, $metrics, &$stats) {
foreach ($metrics as $metric) {
$limit = $periods[$range]['limit'];
$period = $periods[$range]['period'];
$requestDocs = $dbForProject->find('stats', [
new Query('period', Query::TYPE_EQUAL, [$period]),
new Query('metric', Query::TYPE_EQUAL, [$metric]),
], $limit, 0, ['time'], [Database::ORDER_DESC]);
$requestDocs = $dbForProject->find('stats', [
new Query('period', Query::TYPE_EQUAL, [$period]),
new Query('metric', Query::TYPE_EQUAL, [$metric]),
], $limit, 0, ['time'], [Database::ORDER_DESC]);
$stats[$metric] = [];
foreach ($requestDocs as $requestDoc) {
$stats[$metric][] = [
'value' => $requestDoc->getAttribute('value'),
'date' => $requestDoc->getAttribute('time'),
];
$stats[$metric] = [];
foreach ($requestDocs as $requestDoc) {
$stats[$metric][] = [
'value' => $requestDoc->getAttribute('value'),
'date' => $requestDoc->getAttribute('time'),
];
}
// backfill metrics with empty values for graphs
$backfill = $limit - \count($requestDocs);
while ($backfill > 0) {
$last = $limit - $backfill - 1; // array index of last added metric
$diff = match ($period) { // convert period to seconds for unix timestamp math
'30m' => 1800,
'1d' => 86400,
};
$stats[$metric][] = [
'value' => 0,
'date' => ($stats[$metric][$last]['date'] ?? \time()) - $diff, // time of last metric minus period
];
$backfill--;
}
// TODO@kodumbeats explore performance if query is ordered by time ASC
$stats[$metric] = array_reverse($stats[$metric]);
}
});
// backfill metrics with empty values for graphs
$backfill = $limit - \count($requestDocs);
while ($backfill > 0) {
$last = $limit - $backfill - 1; // array index of last added metric
$diff = match ($period) { // convert period to seconds for unix timestamp math
'30m' => 1800,
'1d' => 86400,
};
$stats[$metric][] = [
'value' => 0,
'date' => ($stats[$metric][$last]['date'] ?? \time()) - $diff, // time of last metric minus period
];
$backfill--;
}
// TODO@kodumbeats explore performance if query is ordered by time ASC
$stats[$metric] = array_reverse($stats[$metric]);
}
});
$usage = new Document([
'range' => $range,
'documentsCount' => $stats["databases.{$databaseId}.documents.count"],
'collectionsCount' => $stats["databases.{$databaseId}.collections.count"],
'documentsCreate' => $stats["databases.{$databaseId}.documents.create"],
'documentsRead' => $stats["databases.{$databaseId}.documents.read"],
'documentsUpdate' => $stats["databases.{$databaseId}.documents.update"],
'documentsDelete' => $stats["databases.{$databaseId}.documents.delete"],
'collectionsCreate' => $stats["databases.{$databaseId}.collections.create"],
'collectionsRead' => $stats["databases.{$databaseId}.collections.read"],
'collectionsUpdate' => $stats["databases.{$databaseId}.collections.update"],
'collectionsDelete' => $stats["databases.{$databaseId}.collections.delete"],
]);
}
$usage = new Document([
'range' => $range,
'documentsCount' => $stats["databases.{$databaseId}.documents.count"],
'collectionsCount' => $stats["databases.{$databaseId}.collections.count"],
'documentsCreate' => $stats["databases.{$databaseId}.documents.create"],
'documentsRead' => $stats["databases.{$databaseId}.documents.read"],
'documentsUpdate' => $stats["databases.{$databaseId}.documents.update"],
'documentsDelete' => $stats["databases.{$databaseId}.documents.delete"],
'collectionsCreate' => $stats["databases.{$databaseId}.collections.create"],
'collectionsRead' => $stats["databases.{$databaseId}.collections.read"],
'collectionsUpdate' => $stats["databases.{$databaseId}.collections.update"],
'collectionsDelete' => $stats["databases.{$databaseId}.collections.delete"],
]);
}
$response->dynamic($usage, Response::MODEL_USAGE_DATABASE);
});
$response->dynamic($usage, Response::MODEL_USAGE_DATABASE);
});
App::get('/v1/databases/:databaseId/collections/:collectionId/usage')
->desc('Get usage stats for a collection')
->groups(['api', 'database'])
->label('scope', 'collections.read')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'getCollectionUsage')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_USAGE_COLLECTION)
->param('databaseId', '', new UID(), 'Database ID.')
->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d'], true), 'Date range.', true)
->param('collectionId', '', new UID(), 'Collection ID.')
->inject('response')
->inject('dbForProject')
->action(function (string $databaseId, string $range, string $collectionId, Response $response, Database $dbForProject) {
->alias('/v1/database/collections/:collectionId/documents', ['databaseId' => 'default'])
->desc('Get usage stats for a collection')
->groups(['api', 'database'])
->label('scope', 'collections.read')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'getCollectionUsage')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_USAGE_COLLECTION)
->param('databaseId', '', new UID(), 'Database ID.')
->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d'], true), 'Date range.', true)
->param('collectionId', '', new UID(), 'Collection ID.')
->inject('response')
->inject('dbForProject')
->action(function (string $databaseId, string $range, string $collectionId, Response $response, Database $dbForProject) {
$database = $dbForProject->getDocument('databases', $databaseId);
$database = $dbForProject->getDocument('databases', $databaseId);
$collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId);
$collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId());
$collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId);
$collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId());
if ($collection->isEmpty()) {
throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND);
}
if ($collection->isEmpty()) {
throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND);
}
$usage = [];
if (App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') {
$periods = [
'24h' => [
'period' => '30m',
'limit' => 48,
],
'7d' => [
'period' => '1d',
'limit' => 7,
],
'30d' => [
'period' => '1d',
'limit' => 30,
],
'90d' => [
'period' => '1d',
'limit' => 90,
],
];
$usage = [];
if (App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') {
$periods = [
'24h' => [
'period' => '30m',
'limit' => 48,
],
'7d' => [
'period' => '1d',
'limit' => 7,
],
'30d' => [
'period' => '1d',
'limit' => 30,
],
'90d' => [
'period' => '1d',
'limit' => 90,
],
];
$metrics = [
"databases.{$databaseId}.collections.{$collectionId}.documents.count",
"databases.{$databaseId}.collections.{$collectionId}.documents.create",
"databases.{$databaseId}.collections.{$collectionId}.documents.read",
"databases.{$databaseId}.collections.{$collectionId}.documents.update",
"databases.{$databaseId}.collections.{$collectionId}.documents.delete",
];
$metrics = [
"databases.{$databaseId}.collections.{$collectionId}.documents.count",
"databases.{$databaseId}.collections.{$collectionId}.documents.create",
"databases.{$databaseId}.collections.{$collectionId}.documents.read",
"databases.{$databaseId}.collections.{$collectionId}.documents.update",
"databases.{$databaseId}.collections.{$collectionId}.documents.delete",
];
$stats = [];
$stats = [];
Authorization::skip(function () use ($dbForProject, $periods, $range, $metrics, &$stats) {
foreach ($metrics as $metric) {
$limit = $periods[$range]['limit'];
$period = $periods[$range]['period'];
Authorization::skip(function () use ($dbForProject, $periods, $range, $metrics, &$stats) {
foreach ($metrics as $metric) {
$limit = $periods[$range]['limit'];
$period = $periods[$range]['period'];
$requestDocs = $dbForProject->find('stats', [
new Query('period', Query::TYPE_EQUAL, [$period]),
new Query('metric', Query::TYPE_EQUAL, [$metric]),
], $limit, 0, ['time'], [Database::ORDER_DESC]);
$requestDocs = $dbForProject->find('stats', [
new Query('period', Query::TYPE_EQUAL, [$period]),
new Query('metric', Query::TYPE_EQUAL, [$metric]),
], $limit, 0, ['time'], [Database::ORDER_DESC]);
$stats[$metric] = [];
foreach ($requestDocs as $requestDoc) {
$stats[$metric][] = [
'value' => $requestDoc->getAttribute('value'),
'date' => $requestDoc->getAttribute('time'),
];
$stats[$metric] = [];
foreach ($requestDocs as $requestDoc) {
$stats[$metric][] = [
'value' => $requestDoc->getAttribute('value'),
'date' => $requestDoc->getAttribute('time'),
];
}
// backfill metrics with empty values for graphs
$backfill = $limit - \count($requestDocs);
while ($backfill > 0) {
$last = $limit - $backfill - 1; // array index of last added metric
$diff = match ($period) { // convert period to seconds for unix timestamp math
'30m' => 1800,
'1d' => 86400,
};
$stats[$metric][] = [
'value' => 0,
'date' => ($stats[$metric][$last]['date'] ?? \time()) - $diff, // time of last metric minus period
];
$backfill--;
}
$stats[$metric] = array_reverse($stats[$metric]);
}
});
// backfill metrics with empty values for graphs
$backfill = $limit - \count($requestDocs);
while ($backfill > 0) {
$last = $limit - $backfill - 1; // array index of last added metric
$diff = match ($period) { // convert period to seconds for unix timestamp math
'30m' => 1800,
'1d' => 86400,
};
$stats[$metric][] = [
'value' => 0,
'date' => ($stats[$metric][$last]['date'] ?? \time()) - $diff, // time of last metric minus period
];
$backfill--;
}
$stats[$metric] = array_reverse($stats[$metric]);
}
});
$usage = new Document([
'range' => $range,
'documentsCount' => $stats["databases.{$databaseId}.collections.{$collectionId}.documents.count"],
'documentsCreate' => $stats["databases.{$databaseId}.collections.{$collectionId}.documents.create"],
'documentsRead' => $stats["databases.{$databaseId}.collections.{$collectionId}.documents.read"],
'documentsUpdate' => $stats["databases.{$databaseId}.collections.{$collectionId}.documents.update"],
'documentsDelete' => $stats["databases.{$databaseId}.collections.{$collectionId}.documents.delete"]
]);
}
$usage = new Document([
'range' => $range,
'documentsCount' => $stats["databases.{$databaseId}.collections.{$collectionId}.documents.count"],
'documentsCreate' => $stats["databases.{$databaseId}.collections.{$collectionId}.documents.create"],
'documentsRead' => $stats["databases.{$databaseId}.collections.{$collectionId}.documents.read"],
'documentsUpdate' => $stats["databases.{$databaseId}.collections.{$collectionId}.documents.update"],
'documentsDelete' => $stats["databases.{$databaseId}.collections.{$collectionId}.documents.delete"]
]);
}
$response->dynamic($usage, Response::MODEL_USAGE_COLLECTION);
});
$response->dynamic($usage, Response::MODEL_USAGE_COLLECTION);
});