diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 8ed21875f..ea385fc91 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -51,6 +51,7 @@ App::get('/v1/project/usage') METRIC_NETWORK_REQUESTS, METRIC_NETWORK_INBOUND, METRIC_NETWORK_OUTBOUND, + METRIC_USERS, ] ]; @@ -60,8 +61,8 @@ App::get('/v1/project/usage') }; $limit = match ($period) { - '1h' => (new DateTime($endDate))->diff(new DateTime($startDate))->h, - '1d' => (new DateTime($endDate))->diff(new DateTime($startDate))->days + '1h' => (new DateTime($startDate))->diff(new DateTime($endDate))->days * 24, + '1d' => (new DateTime($startDate))->diff(new DateTime($endDate))->days }; $format = match ($period) { @@ -110,15 +111,50 @@ App::get('/v1/project/usage') } } + $executionsBreakdown = array_map(function($function) use ($dbForProject) { + $id = $function->getId(); + $name = $function->getAttribute('name'); + $metric = str_replace('{bucketInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS); + $value = $dbForProject->findOne('stats', [ + Query::equal('metric', [$metric]), + Query::equal('period', ['inf']) + ]); + + return [ + 'resourceId' => $id, + 'name' => $name, + 'value' => $value['value'] ?? 0, + ]; + }, $dbForProject->find('functions')); + + $bucketsBreakdown = array_map(function($bucket) use ($dbForProject) { + $id = $bucket->getId(); + $name = $bucket->getAttribute('name'); + $metric = str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE); + $value = $dbForProject->findOne('stats', [ + Query::equal('metric', [$metric]), + Query::equal('period', ['inf']) + ]); + + return [ + 'resourceId' => $id, + 'name' => $name, + 'value' => $value['value'] ?? 0, + ]; + }, $dbForProject->find('buckets')); + $response->dynamic(new Document([ 'requests' => ($usage[METRIC_NETWORK_REQUESTS]), 'network' => ($usage[METRIC_NETWORK_INBOUND] + $usage[METRIC_NETWORK_OUTBOUND]), + 'users' => ($usage[METRIC_USERS]), 'executionsTotal' => $total[METRIC_EXECUTIONS], 'documentsTotal' => $total[METRIC_DOCUMENTS], 'databasesTotal' => $total[METRIC_DATABASES], 'usersTotal' => $total[METRIC_USERS], 'bucketsTotal' => $total[METRIC_BUCKETS], 'filesStorageTotal' => $total[METRIC_FILES_STORAGE], + 'executionsBreakdown' => $executionsBreakdown, + 'bucketsBreakdown' => $bucketsBreakdown ]), Response::MODEL_USAGE_PROJECT); }); diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 7e52536ee..8643f3be8 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -3,7 +3,6 @@ namespace Appwrite\Utopia; use Exception; -use Swoole\Http\Request as SwooleRequest; use Utopia\Swoole\Response as SwooleResponse; use Swoole\Http\Response as SwooleHTTPResponse; use Utopia\Database\Document; @@ -39,7 +38,6 @@ use Appwrite\Utopia\Response\Model\Continent; use Appwrite\Utopia\Response\Model\Country; use Appwrite\Utopia\Response\Model\Currency; use Appwrite\Utopia\Response\Model\Document as ModelDocument; -use Appwrite\Utopia\Response\Model\Domain; use Appwrite\Utopia\Response\Model\Error; use Appwrite\Utopia\Response\Model\ErrorDev; use Appwrite\Utopia\Response\Model\Execution; @@ -60,7 +58,6 @@ use Appwrite\Utopia\Response\Model\Locale; use Appwrite\Utopia\Response\Model\Log; use Appwrite\Utopia\Response\Model\Membership; use Appwrite\Utopia\Response\Model\Metric; -use Appwrite\Utopia\Response\Model\Permissions; use Appwrite\Utopia\Response\Model\Phone; use Appwrite\Utopia\Response\Model\Platform; use Appwrite\Utopia\Response\Model\Project; @@ -79,6 +76,7 @@ use Appwrite\Utopia\Response\Model\HealthTime; use Appwrite\Utopia\Response\Model\HealthVersion; use Appwrite\Utopia\Response\Model\Installation; use Appwrite\Utopia\Response\Model\LocaleCode; +use Appwrite\Utopia\Response\Model\MetricBreakdown; use Appwrite\Utopia\Response\Model\Provider; use Appwrite\Utopia\Response\Model\ProviderRepository; use Appwrite\Utopia\Response\Model\Runtime; @@ -113,6 +111,7 @@ class Response extends SwooleResponse public const MODEL_ERROR = 'error'; public const MODEL_METRIC = 'metric'; public const MODEL_METRIC_LIST = 'metricList'; + public const MODEL_METRIC_BREAKDOWN = 'metricBreakdown'; public const MODEL_ERROR_DEV = 'errorDev'; public const MODEL_BASE_LIST = 'baseList'; public const MODEL_USAGE_DATABASES = 'usageDatabases'; @@ -394,6 +393,7 @@ class Response extends SwooleResponse ->setModel(new HealthTime()) ->setModel(new HealthVersion()) ->setModel(new Metric()) + ->setModel(new MetricBreakdown()) ->setModel(new UsageDatabases()) ->setModel(new UsageDatabase()) ->setModel(new UsageCollection()) diff --git a/src/Appwrite/Utopia/Response/Model/MetricBreakdown.php b/src/Appwrite/Utopia/Response/Model/MetricBreakdown.php new file mode 100644 index 000000000..29d562153 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/MetricBreakdown.php @@ -0,0 +1,52 @@ +addRule('resourceId', [ + 'type' => self::TYPE_STRING, + 'description' => 'Resource ID.', + 'default' => '', + 'example' => '5e5ea5c16897e', + ]) + ->addRule('name', [ + 'type' => self::TYPE_STRING, + 'description' => 'Resource name.', + 'default' => '', + 'example' => 'Documents', + ]) + ->addRule('value', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'The value of this metric at the timestamp.', + 'default' => 0, + 'example' => 1, + ]); + } + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'Metric Breakdown'; + } + + /** + * Get Collection + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_METRIC_BREAKDOWN; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/UsageProject.php b/src/Appwrite/Utopia/Response/Model/UsageProject.php index 35c9296a0..cc56920a9 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageProject.php +++ b/src/Appwrite/Utopia/Response/Model/UsageProject.php @@ -47,19 +47,40 @@ class UsageProject extends Model 'example' => 0, ]) ->addRule('requests', [ - 'type' => self::TYPE_INTEGER, + 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated number of requests per period.', 'default' => [], 'example' => [], 'array' => true ]) ->addRule('network', [ - 'type' => self::TYPE_INTEGER, + 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated number of consumed bandwidth per period.', 'default' => [], 'example' => [], 'array' => true ]) + ->addRule('users', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of users per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ->addRule('executionsBreakdown', [ + 'type' => Response::MODEL_METRIC_BREAKDOWN, + 'description' => 'Aggregated breakdown in totals of executions by functions.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ->addRule('bucketsBreakdown', [ + 'type' => Response::MODEL_METRIC_BREAKDOWN, + 'description' => 'Aggregated breakdown in totals of usage by buckets.', + 'default' => [], + 'example' => [], + 'array' => true + ]) ; } diff --git a/tests/e2e/General/UsageTest.php b/tests/e2e/General/UsageTest.php index 694f0a61b..7f78dc527 100644 --- a/tests/e2e/General/UsageTest.php +++ b/tests/e2e/General/UsageTest.php @@ -130,14 +130,12 @@ class UsageTest extends Scope ); $res = $res['body']; - $this->assertEquals('24h', $res['range']); - $this->assertEquals(9, count($res)); - $this->assertEquals(24, count($res['requestsTotal'])); - $this->assertEquals(24, count($res['usersTotal'])); - $this->assertEquals($usersTotal, $res['usersTotal'][array_key_last($res['usersTotal'])]['value']); - $this->validateDates($res['usersTotal']); - $this->assertEquals($requestsTotal, $res['requestsTotal'][array_key_last($res['requestsTotal'])]['value']); - $this->validateDates($res['requestsTotal']); + $this->assertEquals(11, count($res)); + $this->validateDates($res['network']); + $this->validateDates($res['requests']); + $this->validateDates($res['users']); + $this->assertArrayHasKey('executionsBreakdown', $res); + $this->assertArrayHasKey('bucketsBreakdown', $res); $res = $this->client->call( Client::METHOD_GET, diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 8a24b220e..18a568da7 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -1663,7 +1663,6 @@ class ProjectsConsoleClientTest extends Scope foreach ($response['body'] as $key => $value) { if (\preg_match($pattern, $key)) { - \var_dump('Matched key: ' . $key); $matches[$key] = $value; } }