diff --git a/.env b/.env index 1d46f6cad9..3d131c9197 100644 --- a/.env +++ b/.env @@ -93,7 +93,7 @@ _APP_MAINTENANCE_RETENTION_ABUSE=86400 _APP_MAINTENANCE_RETENTION_AUDIT=1209600 _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE=15778800 _APP_USAGE_AGGREGATION_INTERVAL=30 -_APP_STATS_RESOURCES_INTERVAL=3600 +_APP_STATS_RESOURCES_INTERVAL=30 _APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000 _APP_MAINTENANCE_RETENTION_SCHEDULES=86400 _APP_USAGE_STATS=enabled diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index a991565c5d..4c7b21c0f8 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -149,7 +149,7 @@ App::get('/v1/project/usage') $executionsBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS); + $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) @@ -165,7 +165,7 @@ App::get('/v1/project/usage') $executionsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS); + $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) @@ -181,7 +181,7 @@ App::get('/v1/project/usage') $buildsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS); + $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) @@ -230,13 +230,13 @@ App::get('/v1/project/usage') $functionsStorageBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $deploymentMetric = str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $function->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE); + $deploymentMetric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE); $deploymentValue = $dbForProject->findOne('stats', [ Query::equal('metric', [$deploymentMetric]), Query::equal('period', ['inf']) ]); - $buildMetric = str_replace(['{functionInternalId}'], [$function->getInternalId()], METRIC_FUNCTION_ID_BUILDS_STORAGE); + $buildMetric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE); $buildValue = $dbForProject->findOne('stats', [ Query::equal('metric', [$buildMetric]), Query::equal('period', ['inf']) @@ -254,7 +254,7 @@ App::get('/v1/project/usage') $executionsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS); + $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) @@ -270,7 +270,7 @@ App::get('/v1/project/usage') $buildsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS); + $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) diff --git a/app/controllers/general.php b/app/controllers/general.php index 972fc036f6..5c08918ace 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -585,16 +585,62 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size']; } + if (!empty($apiKey) && !empty($apiKey->getDisabledMetrics())) { + foreach ($apiKey->getDisabledMetrics() as $key) { + $queueForStatsUsage->disableMetric($key); + } + } + + $metricTypeExecutions = str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_EXECUTIONS); + $metricTypeIdExecutions = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS); + $metricTypeExecutionsCompute = str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE); + $metricTypeIdExecutionsCompute = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE); + $metricTypeExecutionsMbSeconds = str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS); + $metricTypeIdExecutionsMBSeconds = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS); + if ($deployment->getAttribute('resourceType') === 'sites') { + $queueForStatsUsage + ->disableMetric(METRIC_NETWORK_REQUESTS) + ->disableMetric(METRIC_NETWORK_INBOUND) + ->disableMetric(METRIC_NETWORK_OUTBOUND); + if ($resource->getAttribute('adapter') !== 'ssr') { + $queueForStatsUsage + ->disableMetric(METRIC_EXECUTIONS) + ->disableMetric(METRIC_EXECUTIONS_COMPUTE) + ->disableMetric(METRIC_EXECUTIONS_MB_SECONDS) + ->disableMetric($metricTypeExecutions) + ->disableMetric($metricTypeIdExecutions) + ->disableMetric($metricTypeExecutionsCompute) + ->disableMetric($metricTypeIdExecutionsCompute) + ->disableMetric($metricTypeExecutionsMbSeconds) + ->disableMetric($metricTypeIdExecutionsMBSeconds); + } + + $queueForStatsUsage + ->addMetric(METRIC_SITES_REQUESTS, 1) + ->addMetric(METRIC_SITES_INBOUND, $request->getSize() + $fileSize) + ->addMetric(METRIC_SITES_OUTBOUND, $response->getSize()) + ->addMetric(str_replace('{siteInternalId}', $resource->getInternalId(), METRIC_SITES_ID_REQUESTS), 1) + ->addMetric(str_replace('{siteInternalId}', $resource->getInternalId(), METRIC_SITES_ID_INBOUND), $request->getSize() + $fileSize) + ->addMetric(str_replace('{siteInternalId}', $resource->getInternalId(), METRIC_SITES_ID_OUTBOUND), $response->getSize()) + ; + } + + + $compute = (int)($execution->getAttribute('duration') * 1000); + $mbSeconds = (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT)); $queueForStatsUsage ->addMetric(METRIC_NETWORK_REQUESTS, 1) ->addMetric(METRIC_NETWORK_INBOUND, $request->getSize() + $fileSize) ->addMetric(METRIC_NETWORK_OUTBOUND, $response->getSize()) ->addMetric(METRIC_EXECUTIONS, 1) - ->addMetric(str_replace('{functionInternalId}', $resource->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), 1) - ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000)) // per project - ->addMetric(str_replace('{functionInternalId}', $resource->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function - ->addMetric(METRIC_EXECUTIONS_MB_SECONDS, (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) - ->addMetric(str_replace('{functionInternalId}', $resource->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) + ->addMetric($metricTypeExecutions, 1) + ->addMetric($metricTypeIdExecutions, 1) + ->addMetric(METRIC_EXECUTIONS_COMPUTE, $compute) // per project + ->addMetric($metricTypeExecutionsCompute, $compute) // per function + ->addMetric($metricTypeIdExecutionsCompute, $compute) // per function + ->addMetric(METRIC_EXECUTIONS_MB_SECONDS, $mbSeconds) + ->addMetric($metricTypeExecutionsMbSeconds, $mbSeconds) + ->addMetric($metricTypeIdExecutionsMBSeconds, $mbSeconds) ->setProject($project) ->trigger(); diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 4b780ce66a..957a7a7d23 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -175,8 +175,10 @@ $usageDatabaseListener = function (string $event, Document $document, StatsUsage $queueForStatsUsage ->addMetric(METRIC_DEPLOYMENTS, $value) // per project ->addMetric(METRIC_DEPLOYMENTS_STORAGE, $document->getAttribute('size') * $value) // per project - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_FUNCTION_ID_DEPLOYMENTS), $value) // per function - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE), $document->getAttribute('size') * $value); + ->addMetric(str_replace(['{resourceType}'], [$document->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_DEPLOYMENTS), $value) // per function + ->addMetric(str_replace(['{resourceType}'], [$document->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_DEPLOYMENTS_STORAGE), $document->getAttribute('size') * $value) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), $value) // per function + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), $document->getAttribute('size') * $value); break; default: break; diff --git a/app/init/constants.php b/app/init/constants.php index e5e7b5900d..4d57c63ef5 100644 --- a/app/init/constants.php +++ b/app/init/constants.php @@ -195,36 +195,35 @@ const METRIC_BUILDS_COMPUTE = 'builds.compute'; const METRIC_BUILDS_COMPUTE_SUCCESS = 'builds.compute.success'; const METRIC_BUILDS_COMPUTE_FAILED = 'builds.compute.failed'; const METRIC_BUILDS_MB_SECONDS = 'builds.mbSeconds'; -const METRIC_FUNCTION_ID_BUILDS = '{functionInternalId}.builds'; -const METRIC_FUNCTION_ID_BUILDS_SUCCESS = '{functionInternalId}.builds.success'; -const METRIC_FUNCTION_ID_BUILDS_FAILED = '{functionInternalId}.builds.failed'; -const METRIC_FUNCTION_ID_BUILDS_STORAGE = '{functionInternalId}.builds.storage'; -const METRIC_FUNCTION_ID_BUILDS_COMPUTE = '{functionInternalId}.builds.compute'; -const METRIC_FUNCTION_ID_BUILDS_COMPUTE_SUCCESS = '{functionInternalId}.builds.compute.success'; -const METRIC_FUNCTION_ID_BUILDS_COMPUTE_FAILED = '{functionInternalId}.builds.compute.failed'; -const METRIC_FUNCTION_ID_BUILDS_MB_SECONDS = '{functionInternalId}.builds.mbSeconds'; -const METRIC_SITES_ID_BUILDS = 'sites.{siteInternalId}.builds'; -const METRIC_SITES_ID_BUILDS_SUCCESS = 'sites.{siteInternalId}.builds.success'; -const METRIC_SITES_ID_BUILDS_FAILED = 'sites.{siteInternalId}.builds.failed'; -const METRIC_SITES_ID_BUILDS_STORAGE = 'sites.{siteInternalId}.builds.storage'; -const METRIC_SITES_ID_BUILDS_COMPUTE = 'sites.{siteInternalId}.builds.compute'; -const METRIC_SITES_ID_BUILDS_COMPUTE_SUCCESS = 'sites.{siteInternalId}.builds.compute.success'; -const METRIC_SITES_ID_BUILDS_COMPUTE_FAILED = 'sites.{siteInternalId}.builds.compute.failed'; -const METRIC_SITES_ID_BUILDS_MB_SECONDS = 'sites.{siteInternalId}.builds.mbSeconds'; -const METRIC_FUNCTION_ID_DEPLOYMENTS = '{resourceType}.{resourceInternalId}.deployments'; -const METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE = '{resourceType}.{resourceInternalId}.deployments.storage'; const METRIC_EXECUTIONS = 'executions'; const METRIC_EXECUTIONS_COMPUTE = 'executions.compute'; const METRIC_EXECUTIONS_MB_SECONDS = 'executions.mbSeconds'; -const METRIC_FUNCTION_ID_EXECUTIONS = '{functionInternalId}.executions'; -const METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE = '{functionInternalId}.executions.compute'; -const METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS = '{functionInternalId}.executions.mbSeconds'; -const METRIC_SITE_ID_DEPLOYMENTS = '{resourceType}.{resourceInternalId}.deployments'; -const METRIC_SITE_ID_DEPLOYMENTS_STORAGE = '{resourceType}.{resourceInternalId}.deployments.storage'; -const METRIC_SITE_ID_BUILDS = '{siteInternalId}.builds'; -const METRIC_SITE_ID_BUILDS_STORAGE = '{siteInternalId}.builds.storage'; -const METRIC_SITE_ID_BUILDS_COMPUTE = '{siteInternalId}.builds.compute'; -const METRIC_SITE_ID_BUILDS_MB_SECONDS = '{siteInternalId}.builds.mbSeconds'; +const METRIC_RESOURCE_TYPE_ID_EXECUTIONS = '{resourceType}.{resourceInternalId}.executions'; +const METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE = '{resourceType}.{resourceInternalId}.executions.compute'; +const METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS = '{resourceType}.{resourceInternalId}.executions.mbSeconds'; +const METRIC_RESOURCE_TYPE_ID_BUILDS_SUCCESS = '{resourceType}.{resourceInternalId}.builds.success'; +const METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED = '{resourceType}.{resourceInternalId}.builds.failed'; +const METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE = '{resourceType}.{resourceInternalId}.builds.compute'; +const METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE_SUCCESS = '{resourceType}.{resourceInternalId}.builds.compute.success'; +const METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE_FAILED = '{resourceType}.{resourceInternalId}.builds.compute.failed'; +const METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS = '{resourceType}.{resourceInternalId}.builds.mbSeconds'; +const METRIC_RESOURCE_TYPE_ID_BUILDS = '{resourceType}.{resourceInternalId}.builds'; +const METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE = '{resourceType}.{resourceInternalId}.builds.storage'; +const METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS = '{resourceType}.{resourceInternalId}.deployments'; +const METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE = '{resourceType}.{resourceInternalId}.deployments.storage'; +const METRIC_RESOURCE_TYPE_EXECUTIONS = '{resourceType}.executions'; +const METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE = '{resourceType}.executions.compute'; +const METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS = '{resourceType}.executions.mbSeconds'; +const METRIC_RESOURCE_TYPE_BUILDS_SUCCESS = '{resourceType}.builds.success'; +const METRIC_RESOURCE_TYPE_BUILDS_FAILED = '{resourceType}.builds.failed'; +const METRIC_RESOURCE_TYPE_BUILDS_COMPUTE = '{resourceType}.builds.compute'; +const METRIC_RESOURCE_TYPE_BUILDS_COMPUTE_SUCCESS = '{resourceType}.builds.compute.success'; +const METRIC_RESOURCE_TYPE_BUILDS_COMPUTE_FAILED = '{resourceType}.builds.compute.failed'; +const METRIC_RESOURCE_TYPE_BUILDS_MB_SECONDS = '{resourceType}.builds.mbSeconds'; +const METRIC_RESOURCE_TYPE_BUILDS = '{resourceType}.builds'; +const METRIC_RESOURCE_TYPE_BUILDS_STORAGE = '{resourceType}.builds.storage'; +const METRIC_RESOURCE_TYPE_DEPLOYMENTS = '{resourceType}.deployments'; +const METRIC_RESOURCE_TYPE_DEPLOYMENTS_STORAGE = '{resourceType}.deployments.storage'; const METRIC_NETWORK_REQUESTS = 'network.requests'; const METRIC_NETWORK_INBOUND = 'network.inbound'; const METRIC_NETWORK_OUTBOUND = 'network.outbound'; @@ -239,10 +238,12 @@ const METRIC_TARGETS = 'targets'; const METRIC_PROVIDER_TYPE_TARGETS = '{providerType}.targets'; const METRIC_KEYS = 'keys'; const METRIC_DOMAINS = 'domains'; -const METRIC_RESOURCE_TYPE_ID_BUILDS = '{resourceType}.{resourceInternalId}.builds'; -const METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE = '{resourceType}.{resourceInternalId}.builds.storage'; -const METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS = '{resourceType}.{resourceInternalId}.deployments'; -const METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE = '{resourceType}.{resourceInternalId}.deployments.storage'; +const METRIC_SITES_REQUESTS = 'sites.requests'; +const METRIC_SITES_INBOUND = 'sites.inbound'; +const METRIC_SITES_OUTBOUND = 'sites.outbound'; +const METRIC_SITES_ID_REQUESTS = 'sites.{siteInternalId}.requests'; +const METRIC_SITES_ID_INBOUND = 'sites.{siteInternalId}.inbound'; +const METRIC_SITES_ID_OUTBOUND = 'sites.{siteInternalId}.outbound'; // Resource types diff --git a/app/worker.php b/app/worker.php index ca58456308..bcd4d8767d 100644 --- a/app/worker.php +++ b/app/worker.php @@ -374,7 +374,7 @@ Server::setResource('certificates', function () { }); Server::setResource('logError', function (Registry $register, Document $project) { - return function (Throwable $error, string $namespace, string $action, ?array $extras) use ($register, $project) { + return function (Throwable $error, string $namespace, string $action, ?array $extras = null) use ($register, $project) { $logger = $register->get('logger'); if ($logger) { diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php index b92e5c2784..1c7e771430 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php @@ -438,11 +438,14 @@ class Create extends Base } finally { $queueForStatsUsage ->addMetric(METRIC_EXECUTIONS, 1) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), 1) + ->addMetric(str_replace(['{resourceType}'], [RESOURCE_TYPE_FUNCTIONS], METRIC_RESOURCE_TYPE_EXECUTIONS), 1) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), 1) ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000)) // per project - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function + ->addMetric(str_replace(['{resourceType}'], [RESOURCE_TYPE_FUNCTIONS], METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function ->addMetric(METRIC_EXECUTIONS_MB_SECONDS, (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) + ->addMetric(str_replace(['{resourceType}'], [RESOURCE_TYPE_FUNCTIONS], METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) ; $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php index cf06282038..7f64fa8d8c 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php @@ -69,15 +69,17 @@ class Get extends Base $stats = $usage = []; $days = $periods[$range]; $metrics = [ - str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $function->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS), - str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $function->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE), - str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS), - str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE), - str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), - str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), - str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), - str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS), - str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS) + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_SUCCESS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED), ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { @@ -124,15 +126,22 @@ class Get extends Base } } + $buildsTimeTotal = $usage[$metrics[4]]['total'] ?? 0; + $buildsTotal = $usage[$metrics[2]]['total'] ?? 0; $response->dynamic(new Document([ 'range' => $range, 'deploymentsTotal' => $usage[$metrics[0]]['total'], 'deploymentsStorageTotal' => $usage[$metrics[1]]['total'], 'buildsTotal' => $usage[$metrics[2]]['total'], + 'buildsSuccessTotal' => $usage[$metrics[9]]['total'], + 'buildsFailedTotal' => $usage[$metrics[10]]['total'], 'buildsStorageTotal' => $usage[$metrics[3]]['total'], 'buildsTimeTotal' => $usage[$metrics[4]]['total'], + 'buildsTimeAverage' => $buildsTotal === 0 ? 0 : (int) ($buildsTimeTotal / $buildsTotal), 'executionsTotal' => $usage[$metrics[5]]['total'], 'executionsTimeTotal' => $usage[$metrics[6]]['total'], + 'buildsMbSecondsTotal' => $usage[$metrics[7]]['total'], + 'executionsMbSecondsTotal' => $usage[$metrics[8]]['total'], 'deployments' => $usage[$metrics[0]]['data'], 'deploymentsStorage' => $usage[$metrics[1]]['data'], 'builds' => $usage[$metrics[2]]['data'], @@ -140,10 +149,10 @@ class Get extends Base 'buildsTime' => $usage[$metrics[4]]['data'], 'executions' => $usage[$metrics[5]]['data'], 'executionsTime' => $usage[$metrics[6]]['data'], - 'buildsMbSecondsTotal' => $usage[$metrics[7]]['total'], 'buildsMbSeconds' => $usage[$metrics[7]]['data'], 'executionsMbSeconds' => $usage[$metrics[8]]['data'], - 'executionsMbSecondsTotal' => $usage[$metrics[8]]['total'] + 'buildsSuccess' => $usage[$metrics[9]]['data'], + 'buildsFailed' => $usage[$metrics[10]]['data'], ]), Response::MODEL_USAGE_FUNCTION); } } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php index ca94b59a96..e4a7c01bdf 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php @@ -61,15 +61,17 @@ class XList extends Base $days = $periods[$range]; $metrics = [ METRIC_FUNCTIONS, - METRIC_DEPLOYMENTS, - METRIC_DEPLOYMENTS_STORAGE, - METRIC_BUILDS, - METRIC_BUILDS_STORAGE, - METRIC_BUILDS_COMPUTE, - METRIC_EXECUTIONS, - METRIC_EXECUTIONS_COMPUTE, - METRIC_BUILDS_MB_SECONDS, - METRIC_EXECUTIONS_MB_SECONDS, + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_DEPLOYMENTS), + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_DEPLOYMENTS_STORAGE), + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS), + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS_STORAGE), + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS_COMPUTE), + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_EXECUTIONS), + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE), + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS_MB_SECONDS), + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS), + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS_SUCCESS), + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS_FAILED), ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { @@ -125,6 +127,10 @@ class XList extends Base 'buildsTimeTotal' => $usage[$metrics[5]]['total'], 'executionsTotal' => $usage[$metrics[6]]['total'], 'executionsTimeTotal' => $usage[$metrics[7]]['total'], + 'buildsMbSecondsTotal' => $usage[$metrics[8]]['total'], + 'executionsMbSecondsTotal' => $usage[$metrics[9]]['total'], + 'buildsSuccessTotal' => $usage[$metrics[10]]['total'], + 'buildsFailedTotal' => $usage[$metrics[11]]['total'], 'functions' => $usage[$metrics[0]]['data'], 'deployments' => $usage[$metrics[1]]['data'], 'deploymentsStorage' => $usage[$metrics[2]]['data'], @@ -133,10 +139,10 @@ class XList extends Base 'buildsTime' => $usage[$metrics[5]]['data'], 'executions' => $usage[$metrics[6]]['data'], 'executionsTime' => $usage[$metrics[7]]['data'], - 'buildsMbSecondsTotal' => $usage[$metrics[8]]['total'], 'buildsMbSeconds' => $usage[$metrics[8]]['data'], 'executionsMbSeconds' => $usage[$metrics[9]]['data'], - 'executionsMbSecondsTotal' => $usage[$metrics[9]]['total'], + 'buildsSuccess' => $usage[$metrics[10]]['data'], + 'buildsFailed' => $usage[$metrics[11]]['data'], ]), Response::MODEL_USAGE_FUNCTIONS); } } diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 7e429defca..5356a746e6 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -854,6 +854,20 @@ class Builds extends Action $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 900, 0); $apiKey = $jwtObj->encode([ 'hostnameOverride' => true, + 'disabledMetrics' => [ + METRIC_EXECUTIONS, + METRIC_EXECUTIONS_COMPUTE, + METRIC_EXECUTIONS_MB_SECONDS, + METRIC_NETWORK_REQUESTS, + METRIC_NETWORK_INBOUND, + METRIC_NETWORK_OUTBOUND, + str_replace(["{resourceType}"], [RESOURCE_TYPE_SITES], METRIC_RESOURCE_TYPE_EXECUTIONS), + str_replace(["{resourceType}"], [RESOURCE_TYPE_SITES], METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE), + str_replace(["{resourceType}"], [RESOURCE_TYPE_SITES], METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS), + str_replace(["{resourceType}", "{resourceInternalId}"], [RESOURCE_TYPE_SITES, $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), + str_replace(["{resourceType}", "{resourceInternalId}"], [RESOURCE_TYPE_SITES, $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), + str_replace(["{resourceType}", "{resourceInternalId}"], [RESOURCE_TYPE_SITES, $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), + ], 'bannerDisabled' => true, 'projectCheckDisabled' => true, 'previewAuthDisabled' => true, @@ -1184,49 +1198,24 @@ class Builds extends Action protected function sendUsage(Document $resource, Document $deployment, Document $project, StatsUsage $queue): void { - $key = match($resource->getCollection()) { - 'functions' => 'functionInternalId', - 'sites' => 'siteInternalId', - default => throw new \Exception('Invalid resource type') - }; - - $metrics = match($resource->getCollection()) { - 'functions' => [ - 'builds' => METRIC_FUNCTION_ID_BUILDS, - 'buildsSuccess' => METRIC_FUNCTION_ID_BUILDS_SUCCESS, - 'buildsFailed' => METRIC_FUNCTION_ID_BUILDS_FAILED, - 'buildsComputeSuccess' => METRIC_FUNCTION_ID_BUILDS_COMPUTE_SUCCESS, - 'buildsComputeFailed' => METRIC_FUNCTION_ID_BUILDS_COMPUTE_FAILED, - 'buildsStorage' => METRIC_FUNCTION_ID_BUILDS_STORAGE, - 'buildsCompute' => METRIC_FUNCTION_ID_BUILDS_COMPUTE, - 'buildsMbSeconds' => METRIC_FUNCTION_ID_BUILDS_MB_SECONDS - ], - 'sites' => [ - 'builds' => METRIC_SITES_ID_BUILDS, - 'buildsSuccess' => METRIC_SITES_ID_BUILDS_SUCCESS, - 'buildsFailed' => METRIC_SITES_ID_BUILDS_FAILED, - 'buildsComputeSuccess' => METRIC_SITES_ID_BUILDS_COMPUTE_SUCCESS, - 'buildsComputeFailed' => METRIC_SITES_ID_BUILDS_COMPUTE_FAILED, - 'buildsStorage' => METRIC_SITES_ID_BUILDS_STORAGE, - 'buildsCompute' => METRIC_SITES_ID_BUILDS_COMPUTE, - 'buildsMbSeconds' => METRIC_SITES_ID_BUILDS_MB_SECONDS - ] - }; - switch ($deployment->getAttribute('status')) { case 'ready': $queue ->addMetric(METRIC_BUILDS_SUCCESS, 1) // per project ->addMetric(METRIC_BUILDS_COMPUTE_SUCCESS, (int)$deployment->getAttribute('buildDuration', 0) * 1000) - ->addMetric(str_replace($key, $resource->getInternalId(), METRIC_FUNCTION_ID_BUILDS_SUCCESS), 1) // per function - ->addMetric(str_replace($key, $resource->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE_SUCCESS), (int)$deployment->getAttribute('buildDuration', 0) * 1000); + ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS_SUCCESS), 1) // per function + ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS_COMPUTE_SUCCESS), (int)$deployment->getAttribute('buildDuration', 0) * 1000) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_SUCCESS), 1) // per function + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE_SUCCESS), (int)$deployment->getAttribute('buildDuration', 0) * 1000); break; case 'failed': $queue ->addMetric(METRIC_BUILDS_FAILED, 1) // per project ->addMetric(METRIC_BUILDS_COMPUTE_FAILED, (int)$deployment->getAttribute('buildDuration', 0) * 1000) - ->addMetric(str_replace($key, $resource->getInternalId(), $metrics['buildsFailed']), 1) // per function - ->addMetric(str_replace($key, $resource->getInternalId(), $metrics['buildsComputeFailed']), (int)$deployment->getAttribute('buildDuration', 0) * 1000); + ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS_FAILED), 1) // per function + ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS_COMPUTE_FAILED), (int)$deployment->getAttribute('buildDuration', 0) * 1000) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED), 1) // per function + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE_FAILED), (int)$deployment->getAttribute('buildDuration', 0) * 1000); break; } @@ -1235,10 +1224,14 @@ class Builds extends Action ->addMetric(METRIC_BUILDS_STORAGE, $deployment->getAttribute('buildSize', 0)) ->addMetric(METRIC_BUILDS_COMPUTE, (int)$deployment->getAttribute('buildDuration', 0) * 1000) ->addMetric(METRIC_BUILDS_MB_SECONDS, (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $deployment->getAttribute('buildDuration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) - ->addMetric(str_replace($key, $resource->getInternalId(), METRIC_FUNCTION_ID_BUILDS), 1) // per function - ->addMetric(str_replace($key, $resource->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE), $deployment->getAttribute('buildSize', 0)) - ->addMetric(str_replace($key, $resource->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), (int)$deployment->getAttribute('buildDuration', 0) * 1000) - ->addMetric(str_replace($key, $resource->getInternalId(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $deployment->getAttribute('buildDuration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) + ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS), 1) // per function + ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS_STORAGE), $deployment->getAttribute('buildSize', 0)) + ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS_COMPUTE), (int)$deployment->getAttribute('buildDuration', 0) * 1000) + ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $deployment->getAttribute('buildDuration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS), 1) // per function + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), $deployment->getAttribute('buildSize', 0)) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE), (int)$deployment->getAttribute('buildDuration', 0) * 1000) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $deployment->getAttribute('buildDuration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) ->setProject($project) ->trigger(); } diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php index 3269062d6d..158674aeba 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php @@ -73,12 +73,21 @@ class Get extends Base $stats = $usage = []; $days = $periods[$range]; $metrics = [ - str_replace(['{resourceType}', '{resourceInternalId}'], ['sites', $site->getInternalId()], METRIC_SITE_ID_DEPLOYMENTS), - str_replace(['{resourceType}', '{resourceInternalId}'], ['sites', $site->getInternalId()], METRIC_SITE_ID_DEPLOYMENTS_STORAGE), - str_replace('{siteInternalId}', $site->getInternalId(), METRIC_SITE_ID_BUILDS), - str_replace('{siteInternalId}', $site->getInternalId(), METRIC_SITE_ID_BUILDS_STORAGE), - str_replace('{siteInternalId}', $site->getInternalId(), METRIC_SITE_ID_BUILDS_COMPUTE), - str_replace('{siteInternalId}', $site->getInternalId(), METRIC_SITE_ID_BUILDS_MB_SECONDS) + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_SUCCESS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED), + str_replace(['{siteInternalId}'], [$site->getInternalId()], METRIC_SITES_ID_REQUESTS), + str_replace(['{siteInternalId}'], [$site->getInternalId()], METRIC_SITES_ID_INBOUND), + str_replace(['{siteInternalId}'], [$site->getInternalId()], METRIC_SITES_ID_OUTBOUND), + ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { @@ -125,21 +134,39 @@ class Get extends Base } } + $buildsTimeTotal = $usage[$metrics[4]]['total'] ?? 0; + $buildsTotal = $usage[$metrics[2]]['total'] ?? 0; $response->dynamic(new Document([ 'range' => $range, 'deploymentsTotal' => $usage[$metrics[0]]['total'], 'deploymentsStorageTotal' => $usage[$metrics[1]]['total'], - 'buildsTotal' => $usage[$metrics[2]]['total'], + 'buildsTotal' => $buildsTotal, 'buildsStorageTotal' => $usage[$metrics[3]]['total'], - 'buildsTimeTotal' => $usage[$metrics[4]]['total'], + 'buildsTimeTotal' => $buildsTimeTotal, + 'buildsTimeAverage' => $buildsTotal === 0 ? 0 : (int) ($buildsTimeTotal / $buildsTotal), + 'executionsTotal' => $usage[$metrics[5]]['total'], + 'executionsTimeTotal' => $usage[$metrics[6]]['total'], + 'buildsMbSecondsTotal' => $usage[$metrics[7]]['total'], + 'executionsMbSecondsTotal' => $usage[$metrics[8]]['total'], + 'buildsSuccessTotal' => $usage[$metrics[9]]['total'], + 'buildsFailedTotal' => $usage[$metrics[10]]['total'], + 'requestsTotal' => $usage[$metrics[11]]['total'], + 'inboundTotal' => $usage[$metrics[12]]['total'], + 'outboundTotal' => $usage[$metrics[13]]['total'], 'deployments' => $usage[$metrics[0]]['data'], 'deploymentsStorage' => $usage[$metrics[1]]['data'], 'builds' => $usage[$metrics[2]]['data'], 'buildsStorage' => $usage[$metrics[3]]['data'], 'buildsTime' => $usage[$metrics[4]]['data'], - 'buildsMbSecondsTotal' => $usage[$metrics[7]]['total'], - 'buildsMbSeconds' => $usage[$metrics[7]]['data'] - // TODO: Add more metrics for requests, bandwidth, etc. + 'executions' => $usage[$metrics[5]]['data'], + 'executionsTime' => $usage[$metrics[6]]['data'], + 'buildsMbSeconds' => $usage[$metrics[7]]['data'], + 'executionsMbSeconds' => $usage[$metrics[8]]['data'], + 'buildsSuccess' => $usage[$metrics[9]]['data'], + 'buildsFailed' => $usage[$metrics[10]]['data'], + 'requests' => $usage[$metrics[11]]['data'], + 'inbound' => $usage[$metrics[12]]['data'], + 'outbound' => $usage[$metrics[13]]['data'], ]), Response::MODEL_USAGE_SITE); } } diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php index ee522114bf..6f830b665e 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php @@ -61,12 +61,20 @@ class XList extends Base $days = $periods[$range]; $metrics = [ METRIC_SITES, - METRIC_DEPLOYMENTS, - METRIC_DEPLOYMENTS_STORAGE, - METRIC_BUILDS, - METRIC_BUILDS_STORAGE, - METRIC_BUILDS_COMPUTE, - METRIC_BUILDS_MB_SECONDS, + str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_DEPLOYMENTS), + str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_DEPLOYMENTS_STORAGE), + str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_BUILDS), + str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_BUILDS_STORAGE), + str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_BUILDS_COMPUTE), + str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_EXECUTIONS), + str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE), + str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_BUILDS_MB_SECONDS), + str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS), + str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_BUILDS_SUCCESS), + str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_BUILDS_FAILED), + METRIC_SITES_REQUESTS, + METRIC_SITES_INBOUND, + METRIC_SITES_OUTBOUND, ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { @@ -120,14 +128,30 @@ class XList extends Base 'buildsTotal' => $usage[$metrics[3]]['total'], 'buildsStorageTotal' => $usage[$metrics[4]]['total'], 'buildsTimeTotal' => $usage[$metrics[5]]['total'], + 'executionsTotal' => $usage[$metrics[6]]['total'], + 'executionsTimeTotal' => $usage[$metrics[7]]['total'], + 'buildsMbSecondsTotal' => $usage[$metrics[8]]['total'], + 'executionsMbSecondsTotal' => $usage[$metrics[9]]['total'], + 'buildsSuccessTotal' => $usage[$metrics[10]]['total'], + 'buildsFailedTotal' => $usage[$metrics[11]]['total'], + 'requestsTotal' => $usage[$metrics[12]]['total'], + 'inboundTotal' => $usage[$metrics[13]]['total'], + 'outboundTotal' => $usage[$metrics[14]]['total'], 'sites' => $usage[$metrics[0]]['data'], 'deployments' => $usage[$metrics[1]]['data'], 'deploymentsStorage' => $usage[$metrics[2]]['data'], 'builds' => $usage[$metrics[3]]['data'], 'buildsStorage' => $usage[$metrics[4]]['data'], 'buildsTime' => $usage[$metrics[5]]['data'], - 'buildsMbSecondsTotal' => $usage[$metrics[8]]['total'], - 'buildsMbSeconds' => $usage[$metrics[8]]['data'] + 'executions' => $usage[$metrics[6]]['data'], + 'executionsTime' => $usage[$metrics[7]]['data'], + 'buildsMbSeconds' => $usage[$metrics[8]]['data'], + 'executionsMbSeconds' => $usage[$metrics[9]]['data'], + 'buildsSuccess' => $usage[$metrics[10]]['data'], + 'buildsFailed' => $usage[$metrics[11]]['data'], + 'requests' => $usage[$metrics[12]]['data'], + 'inbound' => $usage[$metrics[13]]['data'], + 'outbound' => $usage[$metrics[14]]['data'], ]), Response::MODEL_USAGE_SITES); } } diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index e81a180c42..c8c68a58ba 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -571,11 +571,14 @@ class Functions extends Action $queueForStatsUsage ->setProject($project) ->addMetric(METRIC_EXECUTIONS, 1) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), 1) + ->addMetric(str_replace(['{resourceType}'], [RESOURCE_TYPE_FUNCTIONS], METRIC_RESOURCE_TYPE_EXECUTIONS), 1) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), 1) ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000))// per project - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) + ->addMetric(str_replace(['{resourceType}'], [RESOURCE_TYPE_FUNCTIONS], METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) ->addMetric(METRIC_EXECUTIONS_MB_SECONDS, (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) + ->addMetric(str_replace(['{resourceType}'], [RESOURCE_TYPE_FUNCTIONS], METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) ->trigger() ; } diff --git a/src/Appwrite/Platform/Workers/StatsResources.php b/src/Appwrite/Platform/Workers/StatsResources.php index dae2967264..8b7c6df1ca 100644 --- a/src/Appwrite/Platform/Workers/StatsResources.php +++ b/src/Appwrite/Platform/Workers/StatsResources.php @@ -199,7 +199,7 @@ class StatsResources extends Action } try { - $this->countForFunctions($dbForProject, $dbForLogs, $region); + $this->countForSitesAndFunctions($dbForProject, $region); } catch (Throwable $th) { call_user_func_array($this->logError, [$th, "StatsResources", "count_for_functions_{$project->getId()}"]); } @@ -303,9 +303,9 @@ class StatsResources extends Action return [$databaseDocuments, $databaseStorage]; } - protected function countForFunctions(Database $dbForProject, Database $dbForLogs, string $region) + protected function countForSitesAndFunctions(Database $dbForProject, string $region): void { - $deploymentsStorage = $dbForProject->sum('deployments', 'size'); + $deploymentsStorage = $dbForProject->sum('deployments', 'sourceSize'); $buildsStorage = $dbForProject->sum('deployments', 'buildSize'); $this->createStatsDocuments($region, METRIC_DEPLOYMENTS_STORAGE, $deploymentsStorage); $this->createStatsDocuments($region, METRIC_BUILDS_STORAGE, $buildsStorage); @@ -314,8 +314,30 @@ class StatsResources extends Action $this->createStatsDocuments($region, METRIC_DEPLOYMENTS, $deployments); $this->createStatsDocuments($region, METRIC_BUILDS, $deployments); - $this->foreachDocument($dbForProject, 'functions', [], function (Document $function) use ($dbForProject, $dbForLogs, $region) { - $functionDeploymentsStorage = $dbForProject->sum('deployments', 'size', [ + $this->countForFunctions($dbForProject, $region); + $this->countForSites($dbForProject, $region); + } + + protected function countForFunctions(Database $dbForProject, string $region) + { + + $deploymentsStorage = $dbForProject->sum('deployments', 'sourceSize', [ + Query::equal('resourceType', [RESOURCE_TYPE_FUNCTIONS]) + ]); + $buildsStorage = $dbForProject->sum('deployments', 'buildSize', [ + Query::equal('resourceType', [RESOURCE_TYPE_FUNCTIONS]) + ]); + $this->createStatsDocuments($region, str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_DEPLOYMENTS_STORAGE), $deploymentsStorage); + $this->createStatsDocuments($region, str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS_STORAGE), $buildsStorage); + + $deployments = $dbForProject->count('deployments', [ + Query::equal('resourceType', [RESOURCE_TYPE_FUNCTIONS]) + ]); + $this->createStatsDocuments($region, str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_DEPLOYMENTS), $deployments); + $this->createStatsDocuments($region, str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS), $deployments); + + $this->foreachDocument($dbForProject, 'functions', [], function (Document $function) use ($dbForProject, $region) { + $functionDeploymentsStorage = $dbForProject->sum('deployments', 'sourceSize', [ Query::equal('resourceInternalId', [$function->getInternalId()]), Query::equal('resourceType', [RESOURCE_TYPE_FUNCTIONS]), ]); @@ -346,6 +368,52 @@ class StatsResources extends Action }); } + protected function countForSites(Database $dbForProject, string $region) + { + + $deploymentsStorage = $dbForProject->sum('deployments', 'sourceSize', [ + Query::equal('resourceType', [RESOURCE_TYPE_SITES]) + ]); + $buildsStorage = $dbForProject->sum('deployments', 'buildSize', [ + Query::equal('resourceType', [RESOURCE_TYPE_SITES]) + ]); + $this->createStatsDocuments($region, str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_DEPLOYMENTS_STORAGE), $deploymentsStorage); + $this->createStatsDocuments($region, str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_BUILDS_STORAGE), $buildsStorage); + + $deployments = $dbForProject->count('deployments', [ + Query::equal('resourceType', [RESOURCE_TYPE_SITES]) + ]); + $this->createStatsDocuments($region, str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_DEPLOYMENTS), $deployments); + $this->createStatsDocuments($region, str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_BUILDS), $deployments); + + $this->foreachDocument($dbForProject, 'sites', [], function (Document $site) use ($dbForProject, $region) { + $siteDeploymentsStorage = $dbForProject->sum('deployments', 'sourceSize', [ + Query::equal('resourceInternalId', [$site->getInternalId()]), + Query::equal('resourceType', [RESOURCE_TYPE_SITES]), + ]); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_SITES,$site->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), $siteDeploymentsStorage); + + $siteDeployments = $dbForProject->count('deployments', [ + Query::equal('resourceInternalId', [$site->getInternalId()]), + Query::equal('resourceType', [RESOURCE_TYPE_SITES]), + ]); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_SITES,$site->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), $siteDeployments); + + /** + * As deployments and builds have 1-1 relationship, + * the count for one should match the other + */ + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_SITES,$site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS), $siteDeployments); + + $siteBuildsStorage = $dbForProject->sum('deployments', 'buildSize', [ + Query::equal('resourceInternalId', [$site->getInternalId()]), + Query::equal('resourceType', [RESOURCE_TYPE_SITES]), + ]); + + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_SITES,$site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), $siteBuildsStorage); + }); + } + protected function createStatsDocuments(string $region, string $metric, int $value) { foreach ($this->periods as $period => $format) { diff --git a/src/Appwrite/Platform/Workers/StatsUsage.php b/src/Appwrite/Platform/Workers/StatsUsage.php index 1d270fcd04..b4f54db285 100644 --- a/src/Appwrite/Platform/Workers/StatsUsage.php +++ b/src/Appwrite/Platform/Workers/StatsUsage.php @@ -189,20 +189,24 @@ class StatsUsage extends Action } break; - case $document->getCollection() === 'functions': - $deployments = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS))); - $deploymentsStorage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE))); - $builds = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS))); - $buildsStorage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE))); - $buildsCompute = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE))); - $executions = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS))); - $executionsCompute = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE))); + case $document->getCollection() === 'functions' || $document->getCollection() === 'sites': + $deployments = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS))); + $deploymentsStorage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE))); + $builds = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS))); + $buildsStorage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE))); + $buildsCompute = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE))); + $executions = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS))); + $executionsCompute = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE))); if (!empty($deployments['value'])) { $metrics[] = [ 'key' => METRIC_DEPLOYMENTS, 'value' => ($deployments['value'] * -1), ]; + $metrics[] = [ + 'key' => str_replace("{resourceType}", $document->getCollection(), METRIC_RESOURCE_TYPE_DEPLOYMENTS), + 'value' => ($deployments['value'] * -1), + ]; } if (!empty($deploymentsStorage['value'])) { @@ -210,6 +214,10 @@ class StatsUsage extends Action 'key' => METRIC_DEPLOYMENTS_STORAGE, 'value' => ($deploymentsStorage['value'] * -1), ]; + $metrics[] = [ + 'key' => str_replace("{resourceType}", $document->getCollection(), METRIC_RESOURCE_TYPE_DEPLOYMENTS_STORAGE), + 'value' => ($deploymentsStorage['value'] * -1), + ]; } if (!empty($builds['value'])) { @@ -217,6 +225,10 @@ class StatsUsage extends Action 'key' => METRIC_BUILDS, 'value' => ($builds['value'] * -1), ]; + $metrics[] = [ + 'key' => str_replace("{resourceType}", $document->getCollection(), METRIC_RESOURCE_TYPE_BUILDS), + 'value' => ($builds['value'] * -1), + ]; } if (!empty($buildsStorage['value'])) { @@ -224,6 +236,10 @@ class StatsUsage extends Action 'key' => METRIC_BUILDS_STORAGE, 'value' => ($buildsStorage['value'] * -1), ]; + $metrics[] = [ + 'key' => str_replace("{resourceType}", $document->getCollection(), METRIC_RESOURCE_TYPE_BUILDS_STORAGE), + 'value' => ($buildsStorage['value'] * -1), + ]; } if (!empty($buildsCompute['value'])) { @@ -231,6 +247,10 @@ class StatsUsage extends Action 'key' => METRIC_BUILDS_COMPUTE, 'value' => ($buildsCompute['value'] * -1), ]; + $metrics[] = [ + 'key' => str_replace("{resourceType}", $document->getCollection(), METRIC_RESOURCE_TYPE_BUILDS_COMPUTE), + 'value' => ($buildsCompute['value'] * -1), + ]; } if (!empty($executions['value'])) { @@ -238,6 +258,10 @@ class StatsUsage extends Action 'key' => METRIC_EXECUTIONS, 'value' => ($executions['value'] * -1), ]; + $metrics[] = [ + 'key' => str_replace("{resourceType}", $document->getCollection(), METRIC_RESOURCE_TYPE_EXECUTIONS), + 'value' => ($executions['value'] * -1), + ]; } if (!empty($executionsCompute['value'])) { @@ -245,6 +269,10 @@ class StatsUsage extends Action 'key' => METRIC_EXECUTIONS_COMPUTE, 'value' => ($executionsCompute['value'] * -1), ]; + $metrics[] = [ + 'key' => str_replace("{resourceType}", $document->getCollection(), METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE), + 'value' => ($executionsCompute['value'] * -1), + ]; } break; default: diff --git a/src/Appwrite/Utopia/Response/Model/UsageFunction.php b/src/Appwrite/Utopia/Response/Model/UsageFunction.php index ac21c5ae0d..32a23250d4 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageFunction.php +++ b/src/Appwrite/Utopia/Response/Model/UsageFunction.php @@ -34,6 +34,18 @@ class UsageFunction extends Model 'default' => 0, 'example' => 0, ]) + ->addRule('buildsSuccessTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of successful function builds.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('buildsFailedTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of failed function builds.', + 'default' => 0, + 'example' => 0, + ]) ->addRule('buildsStorageTotal', [ 'type' => self::TYPE_INTEGER, 'description' => 'total aggregated sum of function builds storage.', @@ -46,6 +58,12 @@ class UsageFunction extends Model 'default' => 0, 'example' => 0, ]) + ->addRule('buildsTimeAverage', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Average builds compute time.', + 'default' => 0, + 'example' => 0, + ]) ->addRule('buildsMbSecondsTotal', [ 'type' => self::TYPE_INTEGER, 'description' => 'Total aggregated sum of function builds mbSeconds.', @@ -133,6 +151,20 @@ class UsageFunction extends Model 'example' => [], 'array' => true ]) + ->addRule('buildsSuccess', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of successful builds per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ->addRule('buildsFailed', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of failed builds per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) ; } diff --git a/src/Appwrite/Utopia/Response/Model/UsageFunctions.php b/src/Appwrite/Utopia/Response/Model/UsageFunctions.php index 90327a7e8a..6dc03c6293 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageFunctions.php +++ b/src/Appwrite/Utopia/Response/Model/UsageFunctions.php @@ -97,6 +97,18 @@ class UsageFunctions extends Model 'example' => [], 'array' => true ]) + ->addRule('buildsSuccessTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of successful function builds.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('buildsFailedTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of failed function builds.', + 'default' => 0, + 'example' => 0, + ]) ->addRule('builds', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated number of functions build per period.', @@ -146,6 +158,20 @@ class UsageFunctions extends Model 'example' => [], 'array' => true ]) + ->addRule('buildsSuccess', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of successful function builds per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ->addRule('buildsFailed', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of failed function builds per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) ; } diff --git a/src/Appwrite/Utopia/Response/Model/UsageSite.php b/src/Appwrite/Utopia/Response/Model/UsageSite.php index 266cc4cade..c45dc831cd 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageSite.php +++ b/src/Appwrite/Utopia/Response/Model/UsageSite.php @@ -3,93 +3,48 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; -use Appwrite\Utopia\Response\Model; -class UsageSite extends Model +class UsageSite extends UsageFunction { public function __construct() { + parent::__construct(); $this - ->addRule('range', [ - 'type' => self::TYPE_STRING, - 'description' => 'The time range of the usage stats.', - 'default' => '', - 'example' => '30d', - ]) - ->addRule('deploymentsTotal', [ + ->addRule('requestsTotal', [ 'type' => self::TYPE_INTEGER, - 'description' => 'Total aggregated number of site deployments.', + 'description' => 'Total aggregated number of requests.', 'default' => 0, 'example' => 0, ]) - ->addRule('deploymentsStorageTotal', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'Total aggregated sum of site deployments storage.', - 'default' => 0, - 'example' => 0, - ]) - ->addRule('buildsTotal', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'Total aggregated number of site builds.', - 'default' => 0, - 'example' => 0, - ]) - ->addRule('buildsStorageTotal', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'total aggregated sum of site builds storage.', - 'default' => 0, - 'example' => 0, - ]) - ->addRule('buildsTimeTotal', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'Total aggregated sum of site builds compute time.', - 'default' => 0, - 'example' => 0, - ]) - ->addRule('buildsMbSecondsTotal', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'Total aggregated sum of site builds mbSeconds.', - 'default' => 0, - 'example' => 0, - ]) - ->addRule('deployments', [ + ->addRule('requests', [ 'type' => Response::MODEL_METRIC, - 'description' => 'Aggregated number of site deployments per period.', + 'description' => 'Aggregated number of requests per period.', 'default' => [], 'example' => [], 'array' => true ]) - ->addRule('deploymentsStorage', [ + ->addRule('inboundTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated inbound bandwidth.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('inbound', [ 'type' => Response::MODEL_METRIC, - 'description' => 'Aggregated number of site deployments storage per period.', + 'description' => 'Aggregated number of inbound bandwidth per period.', 'default' => [], 'example' => [], 'array' => true ]) - ->addRule('builds', [ - 'type' => Response::MODEL_METRIC, - 'description' => 'Aggregated number of site builds per period.', - 'default' => [], - 'example' => [], - 'array' => true + ->addRule('outboundTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated outbound bandwidth.', + 'default' => 0, + 'example' => 0, ]) - ->addRule('buildsStorage', [ + ->addRule('outbound', [ 'type' => Response::MODEL_METRIC, - 'description' => 'Aggregated sum of site builds storage per period.', - 'default' => [], - 'example' => [], - 'array' => true - ]) - ->addRule('buildsTime', [ - 'type' => Response::MODEL_METRIC, - 'description' => 'Aggregated sum of site builds compute time per period.', - 'default' => [], - 'example' => [], - 'array' => true - ]) - ->addRule('buildsMbSeconds', [ - 'type' => Response::MODEL_METRIC, - 'description' => 'Aggregated number of site builds mbSeconds per period.', + 'description' => 'Aggregated number of outbound bandwidth per period.', 'default' => [], 'example' => [], 'array' => true diff --git a/src/Appwrite/Utopia/Response/Model/UsageSites.php b/src/Appwrite/Utopia/Response/Model/UsageSites.php index 8425b8cb74..74435b332c 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageSites.php +++ b/src/Appwrite/Utopia/Response/Model/UsageSites.php @@ -3,106 +3,63 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; -use Appwrite\Utopia\Response\Model; -class UsageSites extends Model +class UsageSites extends UsageFunctions { public function __construct() { + parent::__construct(); $this - ->addRule('range', [ - 'type' => self::TYPE_STRING, - 'description' => 'Time range of the usage stats.', - 'default' => '', - 'example' => '30d', - ]) + ->removeRule('functionsTotal') + ->removeRule('functions') ->addRule('sitesTotal', [ 'type' => self::TYPE_INTEGER, 'description' => 'Total aggregated number of sites.', 'default' => 0, 'example' => 0, ]) - ->addRule('deploymentsTotal', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'Total aggregated number of sites deployments.', - 'default' => 0, - 'example' => 0, - ]) - ->addRule('deploymentsStorageTotal', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'Total aggregated sum of sites deployment storage.', - 'default' => 0, - 'example' => 0, - ]) - ->addRule('buildsTotal', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'Total aggregated number of sites build.', - 'default' => 0, - 'example' => 0, - ]) - ->addRule('buildsStorageTotal', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'total aggregated sum of sites build storage.', - 'default' => 0, - 'example' => 0, - ]) - ->addRule('buildsTimeTotal', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'Total aggregated sum of sites build compute time.', - 'default' => 0, - 'example' => 0, - ]) - ->addRule('buildsMbSecondsTotal', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'Total aggregated sum of sites build mbSeconds.', - 'default' => 0, - 'example' => 0, - ]) ->addRule('sites', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated number of sites per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ->addRule('requestsTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of requests.', 'default' => 0, 'example' => 0, - 'array' => true ]) - ->addRule('deployments', [ + ->addRule('requests', [ 'type' => Response::MODEL_METRIC, - 'description' => 'Aggregated number of sites deployment per period.', + 'description' => 'Aggregated number of requests per period.', 'default' => [], 'example' => [], 'array' => true ]) - ->addRule('deploymentsStorage', [ + ->addRule('inboundTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated inbound bandwidth.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('inbound', [ 'type' => Response::MODEL_METRIC, - 'description' => 'Aggregated number of sites deployment storage per period.', + 'description' => 'Aggregated number of inbound bandwidth per period.', 'default' => [], 'example' => [], 'array' => true ]) - ->addRule('builds', [ - 'type' => Response::MODEL_METRIC, - 'description' => 'Aggregated number of sites build per period.', - 'default' => [], - 'example' => [], - 'array' => true + ->addRule('outboundTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated outbound bandwidth.', + 'default' => 0, + 'example' => 0, ]) - ->addRule('buildsStorage', [ + ->addRule('outbound', [ 'type' => Response::MODEL_METRIC, - 'description' => 'Aggregated sum of sites build storage per period.', - 'default' => [], - 'example' => [], - 'array' => true - ]) - ->addRule('buildsTime', [ - 'type' => Response::MODEL_METRIC, - 'description' => 'Aggregated sum of sites build compute time per period.', - 'default' => [], - 'example' => [], - 'array' => true - ]) - ->addRule('buildsMbSeconds', [ - 'type' => Response::MODEL_METRIC, - 'description' => 'Aggregated sum of sites build mbSeconds per period.', + 'description' => 'Aggregated number of outbound bandwidth per period.', 'default' => [], 'example' => [], 'array' => true diff --git a/tests/e2e/General/UsageTest.php b/tests/e2e/General/UsageTest.php index a58209e746..72bf747576 100644 --- a/tests/e2e/General/UsageTest.php +++ b/tests/e2e/General/UsageTest.php @@ -12,6 +12,7 @@ use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; use Tests\E2E\Services\Functions\FunctionsBase; +use Tests\E2E\Services\Sites\SitesBase; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -24,6 +25,57 @@ class UsageTest extends Scope use ProjectCustom; use SideServer; use FunctionsBase; + use SitesBase { + FunctionsBase::createDeployment insteadof SitesBase; + FunctionsBase::setupDeployment insteadof SitesBase; + FunctionsBase::createVariable insteadof SitesBase; + FunctionsBase::getVariable insteadof SitesBase; + FunctionsBase::listVariables insteadof SitesBase; + FunctionsBase::updateVariable insteadof SitesBase; + FunctionsBase::deleteVariable insteadof SitesBase; + FunctionsBase::getDeployment insteadof SitesBase; + FunctionsBase::listDeployments insteadof SitesBase; + FunctionsBase::deleteDeployment insteadof SitesBase; + FunctionsBase::setupDuplicateDeployment insteadof SitesBase; + FunctionsBase::createDuplicateDeployment insteadof SitesBase; + FunctionsBase::createTemplateDeployment insteadof SitesBase; + FunctionsBase::getUsage insteadof SitesBase; + FunctionsBase::getTemplate insteadof SitesBase; + FunctionsBase::getDeploymentDownload insteadof SitesBase; + FunctionsBase::cancelDeployment insteadof SitesBase; + FunctionsBase::listSpecifications insteadof SitesBase; + SitesBase::createDeployment as createDeploymentSite; + SitesBase::setupDeployment as setupDeploymentSite; + SitesBase::createVariable as createVariableSite; + SitesBase::getVariable as getVariableSite; + SitesBase::listVariables as listVariablesSite; + SitesBase::listVariables as listVariablesSite; + SitesBase::updateVariable as updateVariableSite; + SitesBase::updateVariable as updateVariableSite; + SitesBase::deleteVariable as deleteVariableSite; + SitesBase::deleteVariable as deleteVariableSite; + SitesBase::getDeployment as getDeploymentSite; + SitesBase::getDeployment as getDeploymentSite; + SitesBase::listDeployments as listDeploymentsSite; + SitesBase::listDeployments as listDeploymentsSite; + SitesBase::deleteDeployment as deleteDeploymentSite; + SitesBase::deleteDeployment as deleteDeploymentSite; + SitesBase::setupDuplicateDeployment as setupDuplicateDeploymentSite; + SitesBase::setupDuplicateDeployment as setupDuplicateDeploymentSite; + SitesBase::createDuplicateDeployment as createDuplicateDeploymentSite; + SitesBase::createDuplicateDeployment as createDuplicateDeploymentSite; + SitesBase::createTemplateDeployment as createTemplateDeploymentSite; + SitesBase::createTemplateDeployment as createTemplateDeploymentSite; + SitesBase::getUsage as getUsageSite; + SitesBase::getUsage as getUsageSite; + SitesBase::getTemplate as getTemplateSite; + SitesBase::getTemplate as getTemplateSite; + SitesBase::getDeploymentDownload as getDeploymentDownloadSite; + SitesBase::getDeploymentDownload as getDeploymentDownloadSite; + SitesBase::cancelDeployment as cancelDeploymentSite; + SitesBase::cancelDeployment as cancelDeploymentSite; + SitesBase::listSpecifications as listSpecificationsSite; + } private const WAIT = 5; private const CREATE = 20; @@ -1012,7 +1064,7 @@ class UsageTest extends Scope ); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(19, count($response['body'])); + $this->assertEquals(24, count($response['body'])); $this->assertEquals('30d', $response['body']['range']); $this->assertIsArray($response['body']['deployments']); $this->assertIsArray($response['body']['deploymentsStorage']); @@ -1037,7 +1089,7 @@ class UsageTest extends Scope ); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(21, count($response['body'])); + $this->assertEquals(25, count($response['body'])); $this->assertEquals($response['body']['range'], '30d'); $this->assertIsArray($response['body']['functions']); $this->assertIsArray($response['body']['deployments']); @@ -1058,6 +1110,145 @@ class UsageTest extends Scope return $data; } + + public function testPrepareSitesStats(): array + { + $siteId = $this->setupSite([ + 'buildRuntime' => 'node-22', + 'fallbackFile' => '', + 'framework' => 'other', + 'name' => 'Test Site', + 'outputDirectory' => './', + 'providerBranch' => 'main', + 'providerRootDirectory' => './', + 'siteId' => ID::unique() + ]); + + $this->assertNotNull($siteId); + + $deployment = $this->createDeploymentSite($siteId, [ + 'siteId' => $siteId, + 'code' => $this->packageSite('static'), + 'activate' => true, + ]); + + $this->assertEquals(202, $deployment['headers']['status-code']); + $this->assertNotEmpty($deployment['body']['$id']); + $this->assertEquals('waiting', $deployment['body']['status']); + $this->assertEquals(true, (new DatetimeValidator())->isValid($deployment['body']['$createdAt'])); + + $deploymentIdActive = $deployment['body']['$id'] ?? ''; + + $this->assertEventually(function () use ($siteId, $deploymentIdActive) { + $deployment = $this->getDeploymentSite($siteId, $deploymentIdActive); + + $this->assertEquals('ready', $deployment['body']['status']); + }, 50000, 500); + + $deployment = $this->createDeploymentSite($siteId, [ + 'code' => $this->packageSite('static'), + 'activate' => 'false' + ]); + + $this->assertEquals(202, $deployment['headers']['status-code']); + $this->assertNotEmpty($deployment['body']['$id']); + + $deploymentIdInactive = $deployment['body']['$id'] ?? ''; + + $this->assertEventually(function () use ($siteId, $deploymentIdInactive) { + $deployment = $this->getDeploymentSite($siteId, $deploymentIdInactive); + + $this->assertEquals('ready', $deployment['body']['status']); + }, 50000, 500); + + $site = $this->getSite($siteId); + + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertEquals($deploymentIdActive, $site['body']['deploymentId']); + $this->assertNotEquals($deploymentIdInactive, $site['body']['deploymentId']); + + $data = [ + 'siteId' => $siteId, + 'deployments' => 2, + 'deploymentsSuccess' => 2, + 'deploymentsFailed' => 0 + ]; + + return $data; + } + + /** @depends testPrepareSitesStats */ + #[Retry(count: 1)] + public function testSitesStats(array $data) + { + $siteId = $data['siteId']; + $executionTime = $data['executionTime'] ?? 0; + $executions = $data['executions'] ?? 0; + $deploymentsSuccess = $data['deploymentsSuccess']; + $deploymentsFailed = $data['deploymentsFailed']; + $response = $this->client->call( + Client::METHOD_GET, + '/sites/' . $siteId . '/usage?range=30d', + $this->getConsoleHeaders() + ); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(30, count($response['body'])); + $this->assertEquals('30d', $response['body']['range']); + $this->assertIsArray($response['body']['deployments']); + $this->assertEquals($deploymentsSuccess, $response['body']['buildsSuccessTotal']); + $this->assertEquals($deploymentsFailed, $response['body']['buildsFailedTotal']); + $this->assertIsArray($response['body']['deploymentsStorage']); + $this->assertIsNumeric($response['body']['deploymentsStorageTotal']); + $this->assertIsNumeric($response['body']['buildsMbSecondsTotal']); + $this->assertIsNumeric($response['body']['executionsMbSecondsTotal']); + $this->assertIsArray($response['body']['builds']); + $this->assertIsArray($response['body']['buildsTime']); + $this->assertIsArray($response['body']['buildsMbSeconds']); + $this->assertIsArray($response['body']['executions']); + $this->assertIsArray($response['body']['executionsTime']); + $this->assertIsArray($response['body']['executionsMbSeconds']); + $this->assertIsArray($response['body']['buildsSuccess']); + $this->assertIsArray($response['body']['buildsFailed']); + $this->assertIsArray($response['body']['requests']); + $this->assertIsArray($response['body']['inbound']); + $this->assertIsArray($response['body']['outbound']); + $this->assertEquals($executions, $response['body']['executions'][array_key_last($response['body']['executions'])]['value']); + $this->validateDates($response['body']['executions']); + $this->assertEquals($executionTime, $response['body']['executionsTime'][array_key_last($response['body']['executionsTime'])]['value']); + $this->validateDates($response['body']['executionsTime']); + + $response = $this->client->call( + Client::METHOD_GET, + '/sites/usage?range=30d', + $this->getConsoleHeaders() + ); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(31, count($response['body'])); + $this->assertEquals($response['body']['range'], '30d'); + $this->assertIsArray($response['body']['sites']); + $this->assertIsArray($response['body']['deployments']); + $this->assertIsArray($response['body']['deploymentsStorage']); + $this->assertIsArray($response['body']['builds']); + $this->assertIsArray($response['body']['buildsTime']); + $this->assertIsArray($response['body']['buildsMbSeconds']); + $this->assertIsArray($response['body']['executions']); + $this->assertIsArray($response['body']['executionsTime']); + $this->assertIsArray($response['body']['executionsMbSeconds']); + $this->assertIsArray($response['body']['buildsSuccess']); + $this->assertIsArray($response['body']['buildsFailed']); + $this->assertIsArray($response['body']['requests']); + $this->assertIsArray($response['body']['inbound']); + $this->assertIsArray($response['body']['outbound']); + $this->assertEquals($executions, $response['body']['executions'][array_key_last($response['body']['executions'])]['value']); + $this->validateDates($response['body']['executions']); + $this->assertEquals($executionTime, $response['body']['executionsTime'][array_key_last($response['body']['executionsTime'])]['value']); + $this->validateDates($response['body']['executionsTime']); + $this->assertGreaterThan(0, $response['body']['buildsTime'][array_key_last($response['body']['buildsTime'])]['value']); + $this->validateDates($response['body']['buildsTime']); + } + /** @depends testFunctionsStats */ public function testCustomDomainsFunctionStats(array $data): void { @@ -1099,7 +1290,7 @@ class UsageTest extends Scope ); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(19, count($response['body'])); + $this->assertEquals(24, count($response['body'])); $this->assertEquals('30d', $response['body']['range']); $functionsMetrics = $response['body']; @@ -1141,7 +1332,7 @@ class UsageTest extends Scope ); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(19, count($response['body'])); + $this->assertEquals(24, count($response['body'])); $this->assertEquals('30d', $response['body']['range']); // Check if the new values are greater than the old values diff --git a/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php b/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php index 5e2310f2d7..24215f5352 100644 --- a/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php @@ -62,7 +62,7 @@ class FunctionsConsoleClientTest extends Scope 'range' => '24h' ]); $this->assertEquals(200, $usage['headers']['status-code']); - $this->assertEquals(19, count($usage['body'])); + $this->assertEquals(24, count($usage['body'])); $this->assertEquals('24h', $usage['body']['range']); $this->assertIsNumeric($usage['body']['deploymentsTotal']); $this->assertIsNumeric($usage['body']['deploymentsStorageTotal']); diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index caa5bc6d9a..bee774be08 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -1736,7 +1736,7 @@ class FunctionsCustomServerTest extends Scope ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(19, count($response['body'])); + $this->assertEquals(24, count($response['body'])); $this->assertEquals('24h', $response['body']['range']); $this->assertEquals(1, $response['body']['executionsTotal']); }, 25000, 1000);