1
0
Fork 0
mirror of synced 2024-06-29 11:40:45 +12:00

feat(usage): refactored functions usage endpoint

This commit is contained in:
Christy Jacob 2021-08-20 13:54:45 +05:30
parent 2c69fab6cd
commit cfe49b6892
3 changed files with 273 additions and 85 deletions

View file

@ -1,5 +1,6 @@
<?php
use Appwrite\Database\Validator\Authorization;
use Appwrite\Utopia\Response;
use Appwrite\Database\Validator\CustomId;
use Utopia\App;
@ -110,16 +111,14 @@ $attributesCallback = function ($attribute, $response, $dbForExternal, $database
$database
->setParam('type', DATABASE_TYPE_CREATE_ATTRIBUTE)
->setParam('document', $attribute)
;
->setParam('document', $attribute);
$usage->setParam('database.collections.update', 1);
$audits
->setParam('event', 'database.attributes.create')
->setParam('resource', 'database/collection/' . $collection->getId())
->setParam('data', $attribute)
;
->setParam('data', $attribute);
$response->setStatusCode(Response::STATUS_CODE_CREATED);
$response->dynamic($attribute, Response::MODEL_ATTRIBUTE);
@ -168,8 +167,7 @@ App::post('/v1/database/collections')
$audits
->setParam('event', 'database.collections.create')
->setParam('resource', 'database/collection/' . $collection->getId())
->setParam('data', $collection->getArrayCopy())
;
->setParam('data', $collection->getArrayCopy());
$usage->setParam('database.collections.create', 1);
@ -250,6 +248,112 @@ App::get('/v1/database/collections/:collectionId')
$response->dynamic($collection, Response::MODEL_COLLECTION);
});
App::get('/v1/database/usage')
->desc('Get Database Usage')
->groups(['api', 'database'])
->label('scope', 'collections.read')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'database')
->label('sdk.method', 'getUsage')
->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d'], true), 'Date range.', true)
->inject('response')
->inject('dbForConsole')
->inject('dbForInternal')
->inject('register')
->action(function ($range, $response, $dbForConsole, $dbForInternal, $register) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForConsole */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Registry\Registry $register */
$stats = [];
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 = [
'database.collections.create',
'database.collections.read',
'database.collections.update',
'database.collections.delete',
'database.documents.create',
'database.documents.read',
'database.documents.update',
'database.documents.delete'
];
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]);
}
}
$documentsCount = $dbForInternal->findOne('stats', [new Query('metric', Query::TYPE_EQUAL, ['database.documents.count'])], 0, ['time'], [Database::ORDER_DESC]);
$documentsTotal = $documentsCount ? $documentsCount->getAttribute('value', 0) : 0;
$collectionsCount = $dbForInternal->findOne('stats', [new Query('metric', Query::TYPE_EQUAL, ['n
'])], 0, ['time'], [Database::ORDER_DESC]);
$collectionsTotal = $collectionsCount ? $collectionsCount->getAttribute('value', 0) : 0;
Authorization::reset();
$response->json([
'range' => $range,
'stats' => $stats,
'requests' => [
'data' => $stats['requests'] ?? [],
'total' => \array_sum(\array_map(function ($item) {
return $item['value'];
}, $stats['requests'] ?? [])),
],
'documents' => [
'data' => [],
'total' => $documentsTotal,
],
'collections' => [
'data' => [],
'total' => $collectionsTotal,
]
]);
});
// :collectionId/usage
// 'reads',
// 'writes',
// 'updates',
// 'delete'
App::get('/v1/database/collections/:collectionId/logs')
->desc('List Collection Logs')
->groups(['api', 'database'])
@ -398,8 +502,7 @@ App::put('/v1/database/collections/:collectionId')
$audits
->setParam('event', 'database.collections.update')
->setParam('resource', 'database/collection/' . $collection->getId())
->setParam('data', $collection->getArrayCopy())
;
->setParam('data', $collection->getArrayCopy());
$response->dynamic($collection, Response::MODEL_COLLECTION);
});
@ -440,14 +543,12 @@ App::delete('/v1/database/collections/:collectionId')
$usage->setParam('database.collections.delete', 1);
$events
->setParam('eventData', $response->output($collection, Response::MODEL_COLLECTION))
;
->setParam('eventData', $response->output($collection, Response::MODEL_COLLECTION));
$audits
->setParam('event', 'database.collections.delete')
->setParam('resource', 'database/collection/' . $collection->getId())
->setParam('data', $collection->getArrayCopy())
;
->setParam('data', $collection->getArrayCopy());
$response->noContent();
});
@ -890,20 +991,17 @@ App::delete('/v1/database/collections/:collectionId/attributes/:attributeId')
$database
->setParam('type', DATABASE_TYPE_DELETE_ATTRIBUTE)
->setParam('document', $attribute)
;
->setParam('document', $attribute);
$usage->setParam('database.collections.update', 1);
$events
->setParam('payload', $response->output($attribute, Response::MODEL_ATTRIBUTE))
;
->setParam('payload', $response->output($attribute, Response::MODEL_ATTRIBUTE));
$audits
->setParam('event', 'database.attributes.delete')
->setParam('resource', 'database/collection/' . $collection->getId())
->setParam('data', $attribute->getArrayCopy())
;
->setParam('data', $attribute->getArrayCopy());
$response->noContent();
});
@ -984,20 +1082,17 @@ App::post('/v1/database/collections/:collectionId/indexes')
$database
->setParam('type', DATABASE_TYPE_CREATE_INDEX)
->setParam('document', $index)
;
->setParam('document', $index);
$usage->setParam('database.collections.update', 1);
$audits
->setParam('event', 'database.indexes.create')
->setParam('resource', 'database/collection/' . $collection->getId())
->setParam('data', $index->getArrayCopy())
;
->setParam('data', $index->getArrayCopy());
$response->setStatusCode(Response::STATUS_CODE_CREATED);
$response->dynamic($index, Response::MODEL_INDEX);
});
App::get('/v1/database/collections/:collectionId/indexes')
@ -1138,20 +1233,17 @@ App::delete('/v1/database/collections/:collectionId/indexes/:indexId')
$database
->setParam('type', DATABASE_TYPE_DELETE_INDEX)
->setParam('document', $index)
;
->setParam('document', $index);
$usage->setParam('database.collections.update', 1);
$events
->setParam('payload', $response->output($index, Response::MODEL_INDEX))
;
->setParam('payload', $response->output($index, Response::MODEL_INDEX));
$audits
->setParam('event', 'database.indexes.delete')
->setParam('resource', 'database/collection/' . $collection->getId())
->setParam('data', $index->getArrayCopy())
;
->setParam('data', $index->getArrayCopy());
$response->noContent();
});
@ -1208,21 +1300,18 @@ App::post('/v1/database/collections/:collectionId/documents')
try {
$document = $dbForExternal->createDocument($collectionId, new Document($data));
}
catch (StructureException $exception) {
} catch (StructureException $exception) {
throw new Exception($exception->getMessage(), 400);
}
$usage
->setParam('database.documents.create', 1)
->setParam('collectionId', $collectionId)
;
->setParam('collectionId', $collectionId);
$audits
->setParam('event', 'database.documents.create')
->setParam('resource', 'database/document/' . $document->getId())
->setParam('data', $document->getArrayCopy())
;
->setParam('data', $document->getArrayCopy());
$response->setStatusCode(Response::STATUS_CODE_CREATED);
$response->dynamic($document, Response::MODEL_DOCUMENT);
@ -1286,8 +1375,7 @@ App::get('/v1/database/collections/:collectionId/documents')
$usage
->setParam('database.documents.read', 1)
->setParam('collectionId', $collectionId)
;
->setParam('collectionId', $collectionId);
$response->dynamic(new Document([
'sum' => $dbForExternal->count($collectionId, $queries, APP_LIMIT_COUNT),
@ -1329,8 +1417,7 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId')
$usage
->setParam('database.documents.read', 1)
->setParam('collectionId', $collectionId)
;
->setParam('collectionId', $collectionId);
$response->dynamic($document, Response::MODEL_DOCUMENT);
});
@ -1393,24 +1480,20 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId')
try {
$document = $dbForExternal->updateDocument($collection->getId(), $document->getId(), new Document($data));
}
catch (AuthorizationException $exception) {
} catch (AuthorizationException $exception) {
throw new Exception('Unauthorized permissions', 401);
}
catch (StructureException $exception) {
} catch (StructureException $exception) {
throw new Exception('Bad structure. ' . $exception->getMessage(), 400);
}
$usage
->setParam('database.documents.update', 1)
->setParam('collectionId', $collectionId)
;
->setParam('collectionId', $collectionId);
$audits
->setParam('event', 'database.documents.update')
->setParam('resource', 'database/document/' . $document->getId())
->setParam('data', $document->getArrayCopy())
;
->setParam('data', $document->getArrayCopy());
$response->dynamic($document, Response::MODEL_DOCUMENT);
});
@ -1456,12 +1539,10 @@ App::delete('/v1/database/collections/:collectionId/documents/:documentId')
$usage
->setParam('database.documents.delete', 1)
->setParam('collectionId', $collectionId)
;
->setParam('collectionId', $collectionId);
$events
->setParam('eventData', $response->output($document, Response::MODEL_DOCUMENT))
;
->setParam('eventData', $response->output($document, Response::MODEL_DOCUMENT));
$audits
->setParam('event', 'database.documents.delete')
@ -1471,3 +1552,15 @@ App::delete('/v1/database/collections/:collectionId/documents/:documentId')
$response->noContent();
});
// Refactor usage endpoint in Functions API
// Create usage endpoint in the Database API
// Create usage endpoint in the users API
// Create usage endpoint in the Storage API

View file

@ -259,6 +259,101 @@ App::get('/v1/functions/:functionId/usage')
}
});
App::get('/v1/functions/:functionId/usage2')
->desc('Get Function Usage')
->groups(['api', 'functions'])
->label('scope', 'functions.read')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'functions')
->label('sdk.method', 'getUsage')
->param('functionId', '', new UID(), 'Function unique ID.')
->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d']), 'Date range.', true)
->inject('response')
->inject('project')
->inject('dbForInternal')
->inject('register')
->action(function ($functionId, $range, $response, $project, $dbForInternal, $register) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $project */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Registry\Registry $register */
$function = $dbForInternal->getDocument('functions', $functionId);
if ($function->isEmpty()) {
throw new Exception('Function not found', 404);
}
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 = ["functions.$functionId.executions", "functions.$functionId.failures", "functions.$functionId.compute"];
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]);
}
$executions = $stats["functions.$functionId.executions"] ?? [];
$failures = $stats["functions.$functionId.failures"] ?? [];
$compute = $stats["functions.$functionId.compute"] ?? [];
$response->json([
'range' => $range,
'executions' => [
'data' => $executions,
'total' => \array_sum(\array_map(function ($item) {
return $item['value'];
}, $executions)),
],
'failures' => [
'data' => $failures,
'total' => \array_sum(\array_map(function ($item) {
return $item['value'];
}, $failures)),
],
'compute' => [
'data' => $compute,
'total' => \array_sum(\array_map(function ($item) {
return $item['value'];
}, $compute)),
],
]);
} else {
$response->json([]);
}
});
App::put('/v1/functions/:functionId')
->groups(['api', 'functions'])
->desc('Update Function')

View file

@ -217,7 +217,7 @@ App::get('/v1/projects/:projectId')
});
App::get('/v1/projects/:projectId/usage')
->desc('Get Project')
->desc('Get Project Usage')
->groups(['api', 'projects'])
->label('scope', 'projects.read')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])