Merge branch 'master' of github.com:appwrite/appwrite into feat-add-console

This commit is contained in:
Christy Jacob
2022-11-17 20:26:10 +05:30
2425 changed files with 34637 additions and 54261 deletions
+3 -3
View File
@@ -352,19 +352,19 @@ class Auth
*
* @param array $sessions
* @param string $secret
* @param string $expires
*
* @return bool|string
*/
public static function sessionVerify(array $sessions, string $secret)
public static function sessionVerify(array $sessions, string $secret, int $expires)
{
foreach ($sessions as $session) {
/** @var Document $session */
if (
$session->isSet('secret') &&
$session->isSet('expire') &&
$session->isSet('provider') &&
$session->getAttribute('secret') === self::hash($secret) &&
DateTime::formatTz($session->getAttribute('expire')) >= DateTime::formatTz(DateTime::now())
DateTime::formatTz(DateTime::addSeconds(new \DateTime($session->getCreatedAt()), $expires)) >= DateTime::formatTz(DateTime::now())
) {
return $session->getId();
}
+5 -19
View File
@@ -11,8 +11,7 @@ class Delete extends Event
protected ?Document $document = null;
protected ?string $resource = null;
protected ?string $datetime = null;
protected ?string $dateTime30m = null;
protected ?string $dateTime1d = null;
protected ?string $hourlyUsageRetentionDatetime = null;
public function __construct()
@@ -56,26 +55,14 @@ class Delete extends Event
}
/**
* Set datetime for 1 day interval.
* Sets datetime for 1h interval.
*
* @param string $datetime
* @return self
*/
public function setDateTime1d(string $datetime): self
public function setUsageRetentionHourlyDateTime(string $datetime): self
{
$this->dateTime1d = $datetime;
return $this;
}
/**
* Sets datetime for 30m interval.
*
* @param string $datetime
* @return self
*/
public function setDateTime30m(string $datetime): self
{
$this->dateTime30m = $datetime;
$this->hourlyUsageRetentionDatetime = $datetime;
return $this;
}
@@ -140,8 +127,7 @@ class Delete extends Event
'document' => $this->document,
'resource' => $this->resource,
'datetime' => $this->datetime,
'dateTime1d' => $this->dateTime1d,
'dateTime30m' => $this->dateTime30m,
'hourlyUsageRetentionDatetime' => $this->hourlyUsageRetentionDatetime,
]);
}
}
+2 -1
View File
@@ -44,7 +44,8 @@ abstract class Migration
'1.0.0-RC1' => 'V15',
'1.0.0' => 'V15',
'1.0.1' => 'V15',
'1.0.3' => 'V15'
'1.0.3' => 'V15',
'1.1.0' => 'V16',
];
/**
+142
View File
@@ -0,0 +1,142 @@
<?php
namespace Appwrite\Migration\Version;
use Appwrite\Auth\Auth;
use Appwrite\Migration\Migration;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Database\Database;
use Utopia\Database\Document;
class V16 extends Migration
{
public function execute(): void
{
/**
* Disable SubQueries for Performance.
*/
foreach (['subQueryIndexes', 'subQueryPlatforms', 'subQueryDomains', 'subQueryKeys', 'subQueryWebhooks', 'subQuerySessions', 'subQueryTokens', 'subQueryMemberships', 'subqueryVariables'] as $name) {
Database::addFilter(
$name,
fn () => null,
fn () => []
);
}
Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')');
Console::info('Migrating Collections');
$this->migrateCollections();
Console::info('Migrating Documents');
$this->forEachDocument([$this, 'fixDocument']);
}
/**
* Migrate all Collections.
*
* @return void
*/
protected function migrateCollections(): void
{
foreach ($this->collections as $collection) {
$id = $collection['$id'];
Console::log("Migrating Collection \"{$id}\"");
$this->projectDB->setNamespace("_{$this->project->getInternalId()}");
switch ($id) {
case 'sessions':
try {
/**
* Create 'expire' attribute
*/
$this->projectDB->deleteAttribute($id, 'expire');
} catch (\Throwable $th) {
Console::warning("'expire' from {$id}: {$th->getMessage()}");
}
break;
case 'projects':
try {
/**
* Create 'region' attribute
*/
$this->createAttributeFromCollection($this->projectDB, $id, 'region');
} catch (\Throwable $th) {
Console::warning("'region' from {$id}: {$th->getMessage()}");
}
try {
/**
* Create '_key_team' index
*/
$this->createIndexFromCollection($this->projectDB, $id, '_key_team');
} catch (\Throwable $th) {
Console::warning("'_key_team' from {$id}: {$th->getMessage()}");
}
break;
case 'stats':
try {
/**
* Create 'region' attribute
*/
$this->createAttributeFromCollection($this->projectDB, $id, 'region');
} catch (\Throwable $th) {
Console::warning("'region' from {$id}: {$th->getMessage()}");
}
break;
default:
break;
}
usleep(50000);
}
}
/**
* Fix run on each document
*
* @param \Utopia\Database\Document $document
* @return \Utopia\Database\Document
*/
protected function fixDocument(Document $document)
{
switch ($document->getCollection()) {
case 'projects':
/**
* Bump version number.
*/
$document->setAttribute('version', '1.1.0');
/**
* Set default authDuration
*/
$document->setAttribute('auths', array_merge($document->getAttribute('auths', []), [
'duration' => Auth::TOKEN_EXPIRATION_LOGIN_LONG
]));
$authProviders = $document->getAttribute('authProviders', []);
foreach (Config::getParam('providers') as $provider => $value) {
if (!$value['enabled']) {
continue;
}
if (($authProviders[$provider . 'Appid'] ?? false) && ($authProviders[$provider . 'Secret'] ?? false)) {
$authProviders[$provider . 'Enabled'] = true;
}
}
break;
}
return $document;
}
}
+7 -8
View File
@@ -57,12 +57,11 @@ class Maintenance extends Action
->trigger();
}
function notifyDeleteUsageStats(int $interval30m, int $interval1d)
function notifyDeleteUsageStats(int $usageStatsRetentionHourly)
{
(new Delete())
->setType(DELETE_TYPE_USAGE)
->setDateTime1d(DateTime::addSeconds(new \DateTime(), -1 * $interval1d))
->setDateTime30m(DateTime::addSeconds(new \DateTime(), -1 * $interval30m))
->setUsageRetentionHourlyDateTime(DateTime::addSeconds(new \DateTime(), -1 * $usageStatsRetentionHourly))
->trigger();
}
@@ -78,7 +77,7 @@ class Maintenance extends Action
{
(new Delete())
->setType(DELETE_TYPE_SESSIONS)
->setDatetime(DateTime::addSeconds(new \DateTime(), -1 * Auth::TOKEN_EXPIRATION_LOGIN_LONG))
->setDatetime(DateTime::addSeconds(new \DateTime(), -1 * Auth::TOKEN_EXPIRATION_LOGIN_LONG)) //TODO: Update to use project session expiration instead of default.
->trigger();
}
@@ -132,19 +131,19 @@ class Maintenance extends Action
$executionLogsRetention = (int) App::getEnv('_APP_MAINTENANCE_RETENTION_EXECUTION', '1209600');
$auditLogRetention = (int) App::getEnv('_APP_MAINTENANCE_RETENTION_AUDIT', '1209600');
$abuseLogsRetention = (int) App::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', '86400');
$usageStatsRetention30m = (int) App::getEnv('_APP_MAINTENANCE_RETENTION_USAGE_30M', '129600'); //36 hours
$usageStatsRetention1d = (int) App::getEnv('_APP_MAINTENANCE_RETENTION_USAGE_1D', '8640000'); // 100 days
$usageStatsRetentionHourly = (int) App::getEnv('_APP_MAINTENANCE_RETENTION_USAGE_HOURLY', '8640000'); //100 days
$cacheRetention = (int) App::getEnv('_APP_MAINTENANCE_RETENTION_CACHE', '2592000'); // 30 days
$schedulesDeletionRetention = (int) App::getEnv('_APP_MAINTENANCE_RETENTION_SCHEDULES', '86400'); // 1 Day
Console::loop(function () use ($interval, $executionLogsRetention, $abuseLogsRetention, $auditLogRetention, $usageStatsRetention30m, $usageStatsRetention1d, $cacheRetention, $schedulesDeletionRetention, $dbForConsole) {
Console::loop(function () use ($interval, $executionLogsRetention, $abuseLogsRetention, $auditLogRetention, $usageStatsRetentionHourly, $cacheRetention, $schedulesDeletionRetention, $dbForConsole) {
$time = DateTime::now();
Console::info("[{$time}] Notifying workers with maintenance tasks every {$interval} seconds");
notifyDeleteExecutionLogs($executionLogsRetention);
notifyDeleteAbuseLogs($abuseLogsRetention);
notifyDeleteAuditLogs($auditLogRetention);
notifyDeleteUsageStats($usageStatsRetention30m, $usageStatsRetention1d);
notifyDeleteUsageStats($usageStatsRetentionHourly);
notifyDeleteConnections();
notifyDeleteExpiredSessions();
renewCertificates($dbForConsole);
+16 -2
View File
@@ -8,6 +8,7 @@ use Appwrite\Migration\Migration;
use Utopia\App;
use Utopia\Cache\Cache;
use Utopia\Cache\Adapter\Redis as RedisCache;
use Utopia\Database\Document;
use Utopia\Database\Validator\Authorization;
use Utopia\Registry\Registry;
use Utopia\Validator\Text;
@@ -23,11 +24,21 @@ class Migrate extends Action
{
$this
->desc('Migrate Appwrite to new version')
/** @TODO APP_VERSION_STABLE needs to be defined */
->param('version', APP_VERSION_STABLE, new Text(8), 'Version to migrate to.', true)
->inject('register')
->callback(fn ($version, $register) => $this->action($version, $register));
}
private function clearProjectsCache(Redis $redis, Document $project)
{
try {
$redis->del($redis->keys("cache-_{$project->getInternalId()}:*"));
} catch (\Throwable $th) {
Console::error('Failed to clear project ("' . $project->getId() . '") cache with error: ' . $th->getMessage());
}
}
public function action(string $version, Registry $register)
{
Authorization::disable();
@@ -43,7 +54,7 @@ class Migrate extends Action
$dbPool = $register->get('dbPool', true);
$redis = $register->get('cache', true);
$redis->flushAll();
$cache = new Cache(new RedisCache($redis));
$dbForConsole = $dbPool->getDB('console', $cache);
@@ -79,6 +90,8 @@ class Migrate extends Action
continue;
}
$this->clearProjectsCache($redis, $project);
try {
// TODO: Iterate through all project DBs
$projectDB = $dbPool->getDB($project->getId(), $cache);
@@ -89,6 +102,8 @@ class Migrate extends Action
throw $th;
Console::error('Failed to update project ("' . $project->getId() . '") version with error: ' . $th->getMessage());
}
$this->clearProjectsCache($redis, $project);
}
$sum = \count($projects);
@@ -101,7 +116,6 @@ class Migrate extends Action
}
Swoole\Event::wait(); // Wait for Coroutines to finish
$redis->flushAll();
Console::success('Data Migration Completed');
}
}
+1 -1
View File
@@ -48,7 +48,7 @@ class SDKs extends Action
$production = ($git) ? (Console::confirm('Type "Appwrite" to push code to production git repos') == 'Appwrite') : false;
$message = ($git) ? Console::confirm('Please enter your commit message:') : '';
if (!in_array($version, ['0.6.x', '0.7.x', '0.8.x', '0.9.x', '0.10.x', '0.11.x', '0.12.x', '0.13.x', '0.14.x', '0.15.x', '1.0.x', 'latest'])) {
if (!in_array($version, ['0.6.x', '0.7.x', '0.8.x', '0.9.x', '0.10.x', '0.11.x', '0.12.x', '0.13.x', '0.14.x', '0.15.x', '1.0.x', '1.1.x', 'latest'])) {
throw new Exception('Unknown version given');
}
-75
View File
@@ -1,75 +0,0 @@
<?php
namespace Appwrite\SMS;
abstract class Adapter
{
/**
* @var string
*/
protected string $user;
/**
* @var string
*/
protected string $secret;
/**
* @param string $key
*/
public function __construct(string $user, string $secret)
{
$this->user = $user;
$this->secret = $secret;
}
/**
* Send Message to phone.
* @param string $from
* @param string $to
* @param string $message
* @return void
*/
abstract public function send(string $from, string $to, string $message): void;
/**
* @param string $method
* @param string $url
* @param array $headers
* @param string $payload
*
* @return string
*/
protected function request(string $method, string $url, array $headers = [], ?string $payload = null, ?string $userpwd = null): string
{
$ch = \curl_init($url);
\curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
\curl_setopt($ch, CURLOPT_HEADER, 0);
\curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
\curl_setopt($ch, CURLOPT_USERAGENT, 'Appwrite Phone Authentication');
if (!is_null($payload)) {
\curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
}
if (!is_null($userpwd)) {
\curl_setopt($ch, CURLOPT_USERPWD, $userpwd);
}
$headers[] = 'Content-length: ' . \strlen($payload);
\curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = (string) \curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
\curl_close($ch);
if ($code >= 400) {
throw new \Exception($response);
}
return $response;
}
}
-38
View File
@@ -1,38 +0,0 @@
<?php
namespace Appwrite\SMS\Adapter;
use Appwrite\SMS\Adapter;
// Mock adapter used to E2E test worker
class Mock extends Adapter
{
/**
* @var string
*/
private string $endpoint = 'http://request-catcher:5000/mock-sms';
/**
* @param string $from
* @param string $to
* @param string $message
* @return void
*/
public function send(string $from, string $to, string $message): void
{
$this->request(
method: 'POST',
url: $this->endpoint,
payload: \json_encode([
'message' => $message,
'from' => $from,
'to' => $to
]),
headers: [
"content-type: application/json",
"x-username: {$this->user}",
"x-key: {$this->secret}",
]
);
}
}
-46
View File
@@ -1,46 +0,0 @@
<?php
namespace Appwrite\SMS\Adapter;
use Appwrite\SMS\Adapter;
// Reference Material
// https://docs.msg91.com/p/tf9GTextN/e/Irz7-x1PK/MSG91
class Msg91 extends Adapter
{
/**
* @var string
*/
private string $endpoint = 'https://api.msg91.com/api/v5/flow/';
/**
* For Flow based sending SMS sender ID should not be set in flow
* In environment _APP_SMS_PROVIDER format is 'sms://[senderID]:[authKey]@msg91'.
* _APP_SMS_FROM value is flow ID created in Msg91
* Eg. _APP_SMS_PROVIDER = sms://DINESH:5e1e93cad6fc054d8e759a5b@msg91
* _APP_SMS_FROM = 3968636f704b303135323339
* @param string $from-> utilized from for flow id
* @param string $to
* @param string $message
* @return void
*/
public function send(string $from, string $to, string $message): void
{
$to = ltrim($to, '+');
$this->request(
method: 'POST',
url: $this->endpoint,
payload: json_encode([
'sender' => $this->user,
'otp' => $message,
'flow_id' => $from,
'mobiles' => $to
]),
headers: [
"content-type: application/JSON",
"authkey: {$this->secret}",
]
);
}
}
-39
View File
@@ -1,39 +0,0 @@
<?php
namespace Appwrite\SMS\Adapter;
use Appwrite\SMS\Adapter;
// Reference Material
// https://developer.telesign.com/enterprise/docs/sms-api-send-an-sms
class Telesign extends Adapter
{
/**
* @var string
*/
private string $endpoint = 'https://rest-api.telesign.com/v1/messaging';
/**
* @param string $from
* @param string $to
* @param string $message
* @return void
* @throws \Appwrite\Extend\Exception
*/
public function send(string $from, string $to, string $message): void
{
$to = ltrim($to, '+');
$this->request(
method: 'POST',
url: $this->endpoint,
payload: \http_build_query([
'message' => $message,
'message_type' => 'otp',
'phone_number' => $to
]),
userpwd: "{$this->user}:{$this->secret}"
);
}
}
-42
View File
@@ -1,42 +0,0 @@
<?php
namespace Appwrite\SMS\Adapter;
use Appwrite\SMS\Adapter;
// Reference Material
// https://www.textmagic.com/docs/api/start/
class TextMagic extends Adapter
{
/**
* @var string
*/
private string $endpoint = 'https://rest.textmagic.com/api/v2';
/**
* @param string $from
* @param string $to
* @param string $message
* @return void
*/
public function send(string $from, string $to, string $message): void
{
$to = ltrim($to, '+');
$from = ltrim($from, '+');
$this->request(
method: 'POST',
url: $this->endpoint . '/messages',
payload: \http_build_query([
'text' => $message,
'from' => $from,
'phones' => $to
]),
headers: [
"X-TM-Username: {$this->user}",
"X-TM-Key: {$this->secret}",
]
);
}
}
-36
View File
@@ -1,36 +0,0 @@
<?php
namespace Appwrite\SMS\Adapter;
use Appwrite\SMS\Adapter;
// Reference Material
// https://www.twilio.com/docs/sms/api
class Twilio extends Adapter
{
/**
* @var string
*/
private string $endpoint = 'https://api.twilio.com/2010-04-01';
/**
* @param string $from
* @param string $to
* @param string $message
* @return void
*/
public function send(string $from, string $to, string $message): void
{
$this->request(
method: 'POST',
url: "{$this->endpoint}/Accounts/{$this->user}/Messages.json",
payload: \http_build_query([
'Body' => $message,
'From' => $from,
'To' => $to
]),
userpwd: "{$this->user}:{$this->secret}"
);
}
}
-41
View File
@@ -1,41 +0,0 @@
<?php
namespace Appwrite\SMS\Adapter;
use Appwrite\SMS\Adapter;
// Reference Material
// https://developer.vonage.com/api/sms
class Vonage extends Adapter
{
/**
* @var string
*/
private string $endpoint = 'https://rest.nexmo.com/sms/json';
/**
* @param string $from
* @param string $to
* @param string $message
* @return void
*/
public function send(string $from, string $to, string $message): void
{
$to = ltrim($to, '+');
$headers = ['Content-Type: application/x-www-form-urlencoded'];
$this->request(
method: 'POST',
url: $this->endpoint,
headers: $headers,
payload: \http_build_query([
'text' => $message,
'from' => $from,
'to' => $to,
'api_key' => $this->user,
'api_secret' => $this->secret
])
);
}
}
+7
View File
@@ -4,5 +4,12 @@ namespace Appwrite\Usage;
abstract class Calculator
{
protected string $region;
public function __construct(string $region)
{
$this->region = $region;
}
abstract public function collect(): void;
}
@@ -1,231 +0,0 @@
<?php
namespace Appwrite\Usage\Calculators;
use DateTime;
use Utopia\Database\Database as UtopiaDatabase;
use Utopia\Database\Document;
use Utopia\Database\Query;
class Aggregator extends Database
{
protected function aggregateDatabaseMetrics(string $projectId): void
{
$this->database->setNamespace('_' . $projectId);
$databasesGeneralMetrics = [
'databases.$all.requests.create',
'databases.$all.requests.read',
'databases.$all.requests.update',
'databases.$all.requests.delete',
'collections.$all.requests.create',
'collections.$all.requests.read',
'collections.$all.requests.update',
'collections.$all.requests.delete',
'documents.$all.requests.create',
'documents.$all.requests.read',
'documents.$all.requests.update',
'documents.$all.requests.delete'
];
foreach ($databasesGeneralMetrics as $metric) {
$this->aggregateDailyMetric($projectId, $metric);
$this->aggregateMonthlyMetric($projectId, $metric);
}
$databasesDatabaseMetrics = [
'collections.databaseId.requests.create',
'collections.databaseId.requests.read',
'collections.databaseId.requests.update',
'collections.databaseId.requests.delete',
'documents.databaseId.requests.create',
'documents.databaseId.requests.read',
'documents.databaseId.requests.update',
'documents.databaseId.requests.delete',
];
$this->foreachDocument($projectId, 'databases', [], function (Document $database) use ($databasesDatabaseMetrics, $projectId) {
$databaseId = $database->getId();
foreach ($databasesDatabaseMetrics as $metric) {
$metric = str_replace('databaseId', $databaseId, $metric);
$this->aggregateDailyMetric($projectId, $metric);
$this->aggregateMonthlyMetric($projectId, $metric);
}
$databasesCollectionMetrics = [
'documents.' . $databaseId . '/collectionId.requests.create',
'documents.' . $databaseId . '/collectionId.requests.read',
'documents.' . $databaseId . '/collectionId.requests.update',
'documents.' . $databaseId . '/collectionId.requests.delete',
];
$this->foreachDocument($projectId, 'database_' . $database->getInternalId(), [], function (Document $collection) use ($databasesCollectionMetrics, $projectId) {
$collectionId = $collection->getId();
foreach ($databasesCollectionMetrics as $metric) {
$metric = str_replace('collectionId', $collectionId, $metric);
$this->aggregateDailyMetric($projectId, $metric);
$this->aggregateMonthlyMetric($projectId, $metric);
}
});
});
}
protected function aggregateStorageMetrics(string $projectId): void
{
$this->database->setNamespace('_' . $projectId);
$storageGeneralMetrics = [
'buckets.$all.requests.create',
'buckets.$all.requests.read',
'buckets.$all.requests.update',
'buckets.$all.requests.delete',
'files.$all.requests.create',
'files.$all.requests.read',
'files.$all.requests.update',
'files.$all.requests.delete',
];
foreach ($storageGeneralMetrics as $metric) {
$this->aggregateDailyMetric($projectId, $metric);
$this->aggregateMonthlyMetric($projectId, $metric);
}
$storageBucketMetrics = [
'files.bucketId.requests.create',
'files.bucketId.requests.read',
'files.bucketId.requests.update',
'files.bucketId.requests.delete',
];
$this->foreachDocument($projectId, 'buckets', [], function (Document $bucket) use ($storageBucketMetrics, $projectId) {
$bucketId = $bucket->getId();
foreach ($storageBucketMetrics as $metric) {
$metric = str_replace('bucketId', $bucketId, $metric);
$this->aggregateDailyMetric($projectId, $metric);
$this->aggregateMonthlyMetric($projectId, $metric);
}
});
}
protected function aggregateFunctionMetrics(string $projectId): void
{
$this->database->setNamespace('_' . $projectId);
$functionsGeneralMetrics = [
'project.$all.compute.total',
'project.$all.compute.time',
'executions.$all.compute.total',
'executions.$all.compute.success',
'executions.$all.compute.failure',
'executions.$all.compute.time',
'builds.$all.compute.total',
'builds.$all.compute.success',
'builds.$all.compute.failure',
'builds.$all.compute.time',
];
foreach ($functionsGeneralMetrics as $metric) {
$this->aggregateDailyMetric($projectId, $metric);
$this->aggregateMonthlyMetric($projectId, $metric);
}
$functionMetrics = [
'executions.functionId.compute.total',
'executions.functionId.compute.success',
'executions.functionId.compute.failure',
'executions.functionId.compute.time',
'builds.functionId.compute.total',
'builds.functionId.compute.success',
'builds.functionId.compute.failure',
'builds.functionId.compute.time',
];
$this->foreachDocument($projectId, 'functions', [], function (Document $function) use ($functionMetrics, $projectId) {
$functionId = $function->getId();
foreach ($functionMetrics as $metric) {
$metric = str_replace('functionId', $functionId, $metric);
$this->aggregateDailyMetric($projectId, $metric);
$this->aggregateMonthlyMetric($projectId, $metric);
}
});
}
protected function aggregateUsersMetrics(string $projectId): void
{
$metrics = [
'users.$all.requests.create',
'users.$all.requests.read',
'users.$all.requests.update',
'users.$all.requests.delete',
'sessions.$all.requests.create',
'sessions.$all.requests.delete'
];
foreach ($metrics as $metric) {
$this->aggregateDailyMetric($projectId, $metric);
$this->aggregateMonthlyMetric($projectId, $metric);
}
}
protected function aggregateGeneralMetrics(string $projectId): void
{
$this->aggregateDailyMetric($projectId, 'project.$all.network.requests');
$this->aggregateDailyMetric($projectId, 'project.$all.network.bandwidth');
$this->aggregateDailyMetric($projectId, 'project.$all.network.inbound');
$this->aggregateDailyMetric($projectId, 'project.$all.network.outbound');
$this->aggregateMonthlyMetric($projectId, 'project.$all.network.requests');
$this->aggregateMonthlyMetric($projectId, 'project.$all.network.bandwidth');
$this->aggregateMonthlyMetric($projectId, 'project.$all.network.inbound');
$this->aggregateMonthlyMetric($projectId, 'project.$all.network.outbound');
}
protected function aggregateDailyMetric(string $projectId, string $metric): void
{
$beginOfDay = DateTime::createFromFormat('Y-m-d\TH:i:s.v', \date('Y-m-d\T00:00:00.000'))->format(DateTime::RFC3339);
$endOfDay = DateTime::createFromFormat('Y-m-d\TH:i:s.v', \date('Y-m-d\T23:59:59.999'))->format(DateTime::RFC3339);
$this->database->setNamespace('_' . $projectId);
$value = (int) $this->database->sum('stats', 'value', [
Query::equal('metric', [$metric]),
Query::equal('period', ['30m']),
Query::greaterThanEqual('time', $beginOfDay),
Query::lessThanEqual('time', $endOfDay),
]);
$this->createOrUpdateMetric($projectId, $metric, '1d', $beginOfDay, $value);
}
protected function aggregateMonthlyMetric(string $projectId, string $metric): void
{
$beginOfMonth = DateTime::createFromFormat('Y-m-d\TH:i:s.v', \date('Y-m-01\T00:00:00.000'))->format(DateTime::RFC3339);
$endOfMonth = DateTime::createFromFormat('Y-m-d\TH:i:s.v', \date('Y-m-t\T23:59:59.999'))->format(DateTime::RFC3339);
$this->database->setNamespace('_' . $projectId);
$value = (int) $this->database->sum('stats', 'value', [
Query::equal('metric', [$metric]),
Query::equal('period', ['1d']),
Query::greaterThanEqual('time', $beginOfMonth),
Query::lessThanEqual('time', $endOfMonth),
]);
$this->createOrUpdateMetric($projectId, $metric, '1mo', $beginOfMonth, $value);
}
/**
* Collect Stats
* Collect all database related stats
*
* @return void
*/
public function collect(): void
{
$this->foreachDocument('console', 'projects', [], function (Document $project) {
$projectId = $project->getInternalId();
// Aggregate new metrics from already collected usage metrics
// for lower time period (1day and 1 month metric from 30 minute metrics)
$this->aggregateGeneralMetrics($projectId);
$this->aggregateFunctionMetrics($projectId);
$this->aggregateDatabaseMetrics($projectId);
$this->aggregateStorageMetrics($projectId);
$this->aggregateUsersMetrics($projectId);
});
}
}
-360
View File
@@ -1,360 +0,0 @@
<?php
namespace Appwrite\Usage\Calculators;
use Exception;
use Appwrite\Usage\Calculator;
use DateTime;
use Utopia\Database\Database as UtopiaDatabase;
use Utopia\Database\Document;
use Utopia\Database\Exception\Authorization;
use Utopia\Database\Exception\Structure;
use Utopia\Database\Query;
class Database extends Calculator
{
protected array $periods = [
[
'key' => '30m',
'multiplier' => 1800,
],
[
'key' => '1d',
'multiplier' => 86400,
],
];
public function __construct(UtopiaDatabase $database, callable $errorHandler = null)
{
$this->database = $database;
$this->errorHandler = $errorHandler;
}
/**
* Create Per Period Metric
*
* Create given metric for each defined period
*
* @param string $projectId
* @param string $metric
* @param int $value
* @param bool $monthly
* @return void
* @throws Authorization
* @throws Structure
*/
protected function createPerPeriodMetric(string $projectId, string $metric, int $value, bool $monthly = false): void
{
foreach ($this->periods as $options) {
$period = $options['key'];
$date = new \DateTime();
if ($period === '30m') {
$minutes = $date->format('i') >= '30' ? "30" : "00";
$time = $date->format('Y-m-d H:' . $minutes . ':00');
} elseif ($period === '1d') {
$time = $date->format('Y-m-d 00:00:00');
} else {
throw new Exception("Period type not found", 500);
}
$this->createOrUpdateMetric($projectId, $metric, $period, $time, $value);
}
// Required for billing
if ($monthly) {
$time = DateTime::createFromFormat('Y-m-d\TH:i:s.v', \date('Y-m-01\T00:00:00.000'))->format(DateTime::RFC3339);
$this->createOrUpdateMetric($projectId, $metric, '1mo', $time, $value);
}
}
/**
* Create or Update Metric
*
* Create or update each metric in the stats collection for the given project
*
* @param string $projectId
* @param string $metric
* @param string $period
* @param string $time
* @param int $value
*
* @return void
* @throws Authorization
* @throws Structure
*/
protected function createOrUpdateMetric(string $projectId, string $metric, string $period, string $time, int $value): void
{
$id = \md5("{$time}_{$period}_{$metric}");
$this->database->setNamespace('_' . $projectId);
try {
$document = $this->database->getDocument('stats', $id);
if ($document->isEmpty()) {
$this->database->createDocument('stats', new Document([
'$id' => $id,
'period' => $period,
'time' => $time,
'metric' => $metric,
'value' => $value,
'type' => 2, // these are cumulative metrics
]));
} else {
$this->database->updateDocument(
'stats',
$document->getId(),
$document->setAttribute('value', $value)
);
}
} catch (\Exception$e) { // if projects are deleted this might fail
if (is_callable($this->errorHandler)) {
call_user_func($this->errorHandler, $e, "sync_project_{$projectId}_metric_{$metric}");
} else {
throw $e;
}
}
}
/**
* Foreach Document
*
* Call provided callback for each document in the collection
*
* @param string $projectId
* @param string $collection
* @param array $queries
* @param callable $callback
*
* @return void
* @throws Exception
*/
protected function foreachDocument(string $projectId, string $collection, array $queries, callable $callback): void
{
$limit = 50;
$results = [];
$sum = $limit;
$latestDocument = null;
$this->database->setNamespace('_' . $projectId);
while ($sum === $limit) {
try {
$paginationQueries = [Query::limit($limit)];
if ($latestDocument !== null) {
$paginationQueries[] = Query::cursorAfter($latestDocument);
}
$results = $this->database->find($collection, \array_merge($paginationQueries, $queries));
} catch (\Exception $e) {
if (is_callable($this->errorHandler)) {
call_user_func($this->errorHandler, $e, "fetch_documents_project_{$projectId}_collection_{$collection}");
return;
} else {
throw $e;
}
}
if (empty($results)) {
return;
}
$sum = count($results);
foreach ($results as $document) {
if (is_callable($callback)) {
$callback($document);
}
}
$latestDocument = $results[array_key_last($results)];
}
}
/**
* Sum
*
* Calculate sum of an attribute of documents in collection
*
* @param string $projectId
* @param string $collection
* @param string $attribute
* @param string|null $metric
* @param int $multiplier
* @return int
* @throws Exception
*/
private function sum(string $projectId, string $collection, string $attribute, string $metric = null, int $multiplier = 1): int
{
$this->database->setNamespace('_' . $projectId);
try {
$sum = $this->database->sum($collection, $attribute);
$sum = (int) ($sum * $multiplier);
if (!is_null($metric)) {
$this->createPerPeriodMetric($projectId, $metric, $sum);
}
return $sum;
} catch (Exception $e) {
if (is_callable($this->errorHandler)) {
call_user_func($this->errorHandler, $e, "fetch_sum_project_{$projectId}_collection_{$collection}");
} else {
throw $e;
}
}
return 0;
}
/**
* Count
*
* Count number of documents in collection
*
* @param string $projectId
* @param string $collection
* @param ?string $metric
*
* @return int
* @throws Exception
*/
private function count(string $projectId, string $collection, ?string $metric = null): int
{
$this->database->setNamespace('_' . $projectId);
try {
$count = $this->database->count($collection);
if (!is_null($metric)) {
$this->createPerPeriodMetric($projectId, (string) $metric, $count);
}
return $count;
} catch (Exception $e) {
if (is_callable($this->errorHandler)) {
call_user_func($this->errorHandler, $e, "fetch_count_project_{$projectId}_collection_{$collection}");
} else {
throw $e;
}
}
return 0;
}
/**
* Deployments Total
*
* Total sum of storage used by deployments
*
* @param string $projectId
*
* @return int
* @throws Exception
*/
private function deploymentsTotal(string $projectId): int
{
return $this->sum($projectId, 'deployments', 'size', 'deployments.$all.storage.size');
}
/**
* Users Stats
*
* Metric: users.count
*
* @param string $projectId
*
* @return void
* @throws Exception
*/
private function usersStats(string $projectId): void
{
$this->count($projectId, 'users', 'users.$all.count.total');
}
/**
* Storage Stats
*
* Metrics: buckets.$all.count.total, files.$all.count.total, files.bucketId,count.total,
* files.$all.storage.size, files.bucketId.storage.size, project.$all.storage.size
*
* @param string $projectId
*
* @return void
* @throws Authorization
* @throws Structure
*/
private function storageStats(string $projectId): void
{
$projectFilesTotal = 0;
$projectFilesCount = 0;
$metric = 'buckets.$all.count.total';
$this->count($projectId, 'buckets', $metric);
$this->foreachDocument($projectId, 'buckets', [], function ($bucket) use (&$projectFilesCount, &$projectFilesTotal, $projectId,) {
$metric = "files.{$bucket->getId()}.count.total";
$count = $this->count($projectId, 'bucket_' . $bucket->getInternalId(), $metric);
$projectFilesCount += $count;
$metric = "files.{$bucket->getId()}.storage.size";
$sum = $this->sum($projectId, 'bucket_' . $bucket->getInternalId(), 'sizeOriginal', $metric);
$projectFilesTotal += $sum;
});
$this->createPerPeriodMetric($projectId, 'files.$all.count.total', $projectFilesCount);
$this->createPerPeriodMetric($projectId, 'files.$all.storage.size', $projectFilesTotal);
$deploymentsTotal = $this->deploymentsTotal($projectId);
$this->createPerPeriodMetric($projectId, 'project.$all.storage.size', $projectFilesTotal + $deploymentsTotal);
}
/**
* Database Stats
*
* Collect all database stats
* Metrics: databases.$all.count.total, collections.$all.count.total, collections.databaseId.count.total,
* documents.$all.count.all, documents.databaseId.count.total, documents.databaseId/collectionId.count.total
*
* @param string $projectId
*
* @return void
* @throws Authorization
* @throws Structure
*/
private function databaseStats(string $projectId): void
{
$projectDocumentsCount = 0;
$projectCollectionsCount = 0;
$this->count($projectId, 'databases', 'databases.$all.count.total');
$this->foreachDocument($projectId, 'databases', [], function ($database) use (&$projectDocumentsCount, &$projectCollectionsCount, $projectId) {
$metric = "collections.{$database->getId()}.count.total";
$count = $this->count($projectId, 'database_' . $database->getInternalId(), $metric);
$projectCollectionsCount += $count;
$databaseDocumentsCount = 0;
$this->foreachDocument($projectId, 'database_' . $database->getInternalId(), [], function ($collection) use (&$projectDocumentsCount, &$databaseDocumentsCount, $projectId, $database) {
$metric = "documents.{$database->getId()}/{$collection->getId()}.count.total";
$count = $this->count($projectId, 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $metric);
$projectDocumentsCount += $count;
$databaseDocumentsCount += $count;
});
$this->createPerPeriodMetric($projectId, "documents.{$database->getId()}.count.total", $databaseDocumentsCount);
});
$this->createPerPeriodMetric($projectId, 'collections.$all.count.total', $projectCollectionsCount);
$this->createPerPeriodMetric($projectId, 'documents.$all.count.total', $projectDocumentsCount);
}
/**
* Collect Stats
*
* Collect all database related stats
*
* @return void
* @throws Exception
*/
public function collect(): void
{
$this->foreachDocument('console', 'projects', [], function (Document $project) {
$projectId = $project->getInternalId();
$this->usersStats($projectId);
$this->databaseStats($projectId);
$this->storageStats($projectId);
});
}
}
+143 -35
View File
@@ -2,6 +2,7 @@
namespace Appwrite\Usage\Calculators;
use Utopia\App;
use Appwrite\Usage\Calculator;
use Utopia\Database\Database;
use Utopia\Database\Document;
@@ -10,12 +11,54 @@ use DateTime;
class TimeSeries extends Calculator
{
/**
* InfluxDB
*
* @var InfluxDatabase
*/
protected InfluxDatabase $influxDB;
/**
* Utopia Database
*
* @var Database
*/
protected Database $database;
/**
* Error Handler Callback
*
* @var callable
*/
protected $errorHandler;
/**
* Latest times for metric that was synced to the database
*
* @var array
*/
private array $latestTime = [];
// all the mertics that we are collecting
/**
* Periods the metrics are collected for
* @var array
*/
protected array $periods = [
[
'key' => '1h',
'startTime' => '-24 hours'
],
[
'key' => '1d',
'startTime' => '-30 days'
]
];
/**
* All the metrics that we are collecting
*
* @var array
*/
protected array $metrics = [
'project.$all.network.requests' => [
'table' => 'appwrite_usage_project_{scope}_network_requests',
@@ -189,12 +232,6 @@ class TimeSeries extends Calculator
'executions.$all.compute.total' => [
'table' => 'appwrite_usage_executions_{scope}_compute',
],
'builds.$all.compute.time' => [
'table' => 'appwrite_usage_executions_{scope}_compute_time',
],
'executions.$all.compute.time' => [
'table' => 'appwrite_usage_executions_{scope}_compute_time',
],
'builds.$all.compute.total' => [
'table' => 'appwrite_usage_builds_{scope}_compute',
],
@@ -230,14 +267,7 @@ class TimeSeries extends Calculator
'table' => 'appwrite_usage_builds_{scope}_compute',
'groupBy' => ['functionId'],
],
'executions.functionId.compute.time' => [
'table' => 'appwrite_usage_executions_{scope}_compute_time',
'groupBy' => ['functionId'],
],
'builds.functionId.compute.time' => [
'table' => 'appwrite_usage_builds_{scope}_compute_time',
'groupBy' => ['functionId'],
],
'executions.functionId.compute.failure' => [
'table' => 'appwrite_usage_executions_{scope}_compute',
'groupBy' => ['functionId'],
@@ -267,19 +297,94 @@ class TimeSeries extends Calculator
],
],
// counters
'users.$all.count.total' => [
'table' => 'appwrite_usage_users_{scope}_count_total',
],
'buckets.$all.count.total' => [
'table' => 'appwrite_usage_buckets_{scope}_count_total',
],
'files.$all.count.total' => [
'table' => 'appwrite_usage_files_{scope}_count_total',
],
'files.bucketId.count.total' => [
'table' => 'appwrite_usage_files_{scope}_count_total',
'groupBy' => ['bucketId']
],
'databases.$all.count.total' => [
'table' => 'appwrite_usage_databases_{scope}_count_total',
],
'collections.$all.count.total' => [
'table' => 'appwrite_usage_collections_{scope}_count_total',
],
'documents.$all.count.total' => [
'table' => 'appwrite_usage_documents_{scope}_count_total',
],
'collections.databaseId.count.total' => [
'table' => 'appwrite_usage_collections_{scope}_count_total',
'groupBy' => ['databaseId']
],
'documents.databaseId.count.total' => [
'table' => 'appwrite_usage_documents_{scope}_count_total',
'groupBy' => ['databaseId']
],
'documents.databaseId/collectionId.count.total' => [
'table' => 'appwrite_usage_documents_{scope}_count_total',
'groupBy' => ['databaseId', 'collectionId']
],
'deployments.$all.storage.size' => [
'table' => 'appwrite_usage_deployments_{scope}_storage_size',
],
'project.$all.storage.size' => [
'table' => 'appwrite_usage_project_{scope}_storage_size',
],
'files.$all.storage.size' => [
'table' => 'appwrite_usage_files_{scope}_storage_size',
],
'files.$bucketId.storage.size' => [
'table' => 'appwrite_usage_files_{scope}_storage_size',
'groupBy' => ['bucketId']
],
'builds.$all.compute.time' => [
'table' => 'appwrite_usage_executions_{scope}_compute_time',
],
'executions.$all.compute.time' => [
'table' => 'appwrite_usage_executions_{scope}_compute_time',
],
'executions.functionId.compute.time' => [
'table' => 'appwrite_usage_executions_{scope}_compute_time',
'groupBy' => ['functionId'],
],
'builds.functionId.compute.time' => [
'table' => 'appwrite_usage_builds_{scope}_compute_time',
'groupBy' => ['functionId'],
],
'project.$all.compute.time' => [ // Built time + execution time
'table' => 'appwrite_usage_project_{scope}_compute_time',
'groupBy' => ['functionId'],
],
'deployments.$all.storage.size' => [
'table' => 'appwrite_usage_deployments_{scope}_storage_size'
],
'project.$all.storage.size' => [
'table' => 'appwrite_usage_project_{scope}_storage_size'
],
'files.$all.storage.size' => [
'table' => 'appwrite_usage_files_{scope}_storage_size'
],
'files.bucketId.storage.size' => [
'table' => 'appwrite_usage_files_{scope}_storage_size',
'groupBy' => ['bucketId']
]
];
protected array $period = [
'key' => '30m',
'startTime' => '-24 hours',
];
public function __construct(Database $database, InfluxDatabase $influxDB, callable $errorHandler = null)
public function __construct(string $region, Database $database, InfluxDatabase $influxDB, callable $errorHandler = null)
{
parent::__construct($region);
$this->database = $database;
$this->influxDB = $influxDB;
$this->errorHandler = $errorHandler;
@@ -301,9 +406,7 @@ class TimeSeries extends Calculator
private function createOrUpdateMetric(string $projectId, string $time, string $period, string $metric, int $value, int $type): void
{
$id = \md5("{$time}_{$period}_{$metric}");
$this->database->setNamespace('_console');
$project = $this->database->getDocument('projects', $projectId);
$this->database->setNamespace('_' . $project->getInternalId());
$this->database->setNamespace('_' . $projectId);
try {
$document = $this->database->getDocument('stats', $id);
@@ -315,6 +418,7 @@ class TimeSeries extends Calculator
'metric' => $metric,
'value' => $value,
'type' => $type,
'region' => $this->region,
]));
} else {
$this->database->updateDocument(
@@ -365,7 +469,7 @@ class TimeSeries extends Calculator
$query .= "WHERE \"time\" > '{$start}' ";
$query .= "AND \"time\" < '{$end}' ";
$query .= "AND \"metric_type\"='counter' {$filters} ";
$query .= "GROUP BY time({$period['key']}), \"projectId\" {$groupBy} ";
$query .= "GROUP BY time({$period['key']}), \"projectId\", \"projectInternalId\" {$groupBy} ";
$query .= "FILL(null)";
try {
@@ -387,9 +491,11 @@ class TimeSeries extends Calculator
}
$value = (!empty($point['value'])) ? $point['value'] : 0;
if (empty($point['projectInternalId'] ?? null)) {
continue;
}
$this->createOrUpdateMetric(
$projectId,
$point['projectInternalId'],
$point['time'],
$period['key'],
$metricUpdated,
@@ -416,14 +522,16 @@ class TimeSeries extends Calculator
*/
public function collect(): void
{
foreach ($this->metrics as $metric => $options) { //for each metrics
try {
$this->syncFromInfluxDB($metric, $options, $this->period);
} catch (\Exception $e) {
if (is_callable($this->errorHandler)) {
call_user_func($this->errorHandler, $e);
} else {
throw $e;
foreach ($this->periods as $period) {
foreach ($this->metrics as $metric => $options) { //for each metrics
try {
$this->syncFromInfluxDB($metric, $options, $period);
} catch (\Exception $e) {
if (is_callable($this->errorHandler)) {
call_user_func($this->errorHandler, $e);
} else {
throw $e;
}
}
}
}
+35 -14
View File
@@ -76,11 +76,14 @@ class Stats
/**
* Submit data to StatsD.
* Send various metrics to StatsD based on the parameters that are set
* @return void
*/
public function submit(): void
{
$projectId = $this->params['projectId'] ?? '';
$tags = ",projectId={$projectId},version=" . App::getEnv('_APP_VERSION', 'UNKNOWN');
$projectInternalId = $this->params['projectInternalId'];
$tags = ",projectInternalId={$projectInternalId},projectId={$projectId},version=" . App::getEnv('_APP_VERSION', 'UNKNOWN');
// the global namespace is prepended to every key (optional)
$this->statsd->setNamespace($this->namespace);
@@ -91,8 +94,8 @@ class Stats
$this->statsd->increment('project.{scope}.network.requests' . $tags . ',method=' . \strtolower($httpMethod));
}
$inbound = $this->params['networkRequestSize'] ?? 0;
$outbound = $this->params['networkResponseSize'] ?? 0;
$inbound = $this->params['project.{scope}.network.inbound'] ?? 0;
$outbound = $this->params['project.{scope}.network.outbound'] ?? 0;
$this->statsd->count('project.{scope}.network.inbound' . $tags, $inbound);
$this->statsd->count('project.{scope}.network.outbound' . $tags, $outbound);
$this->statsd->count('project.{scope}.network.bandwidth' . $tags, $inbound + $outbound);
@@ -102,12 +105,13 @@ class Stats
'users.{scope}.requests.read',
'users.{scope}.requests.update',
'users.{scope}.requests.delete',
'users.{scope}.count.total',
];
foreach ($usersMetrics as $metric) {
$value = $this->params[$metric] ?? 0;
if ($value >= 1) {
$this->statsd->increment($metric . $tags);
if ($value === 1 || $value === -1) {
$this->statsd->count($metric . $tags, $value);
}
}
@@ -124,13 +128,16 @@ class Stats
'documents.{scope}.requests.read',
'documents.{scope}.requests.update',
'documents.{scope}.requests.delete',
'databases.{scope}.count.total',
'collections.{scope}.count.total',
'documents.{scope}.count.total'
];
foreach ($dbMetrics as $metric) {
$value = $this->params[$metric] ?? 0;
if ($value >= 1) {
if ($value === 1 || $value === -1) {
$dbTags = $tags . ",collectionId=" . ($this->params['collectionId'] ?? '') . ",databaseId=" . ($this->params['databaseId'] ?? '');
$this->statsd->increment($metric . $dbTags);
$this->statsd->count($metric . $dbTags, $value);
}
}
@@ -143,13 +150,16 @@ class Stats
'files.{scope}.requests.read',
'files.{scope}.requests.update',
'files.{scope}.requests.delete',
'buckets.{scope}.count.total',
'files.{scope}.count.total',
'files.{scope}.storage.size'
];
foreach ($storageMertics as $metric) {
$value = $this->params[$metric] ?? 0;
if ($value >= 1) {
if ($value !== 0) {
$storageTags = $tags . ",bucketId=" . ($this->params['bucketId'] ?? '');
$this->statsd->increment($metric . $storageTags);
$this->statsd->count($metric . $storageTags, $value);
}
}
@@ -176,19 +186,30 @@ class Stats
$functionBuildTime = ($this->params['buildTime'] ?? 0) * 1000; // ms
$functionBuildStatus = $this->params['buildStatus'] ?? '';
$functionCompute = $functionExecutionTime + $functionBuildTime;
$functionTags = $tags . ',functionId=' . $functionId;
$deploymentSize = $this->params['deployment.{scope}.storage.size'] ?? 0;
$storageSize = $this->params['files.{scope}.storage.size'] ?? 0;
if ($deploymentSize + $storageSize > 0 || $deploymentSize + $storageSize <= -1) {
$this->statsd->count('project.{scope}.storage.size' . $tags, $deploymentSize + $storageSize);
}
if ($deploymentSize !== 0) {
$this->statsd->count('deployments.{scope}.storage.size' . $functionTags, $deploymentSize);
}
if ($functionExecution >= 1) {
$this->statsd->increment('executions.{scope}.compute' . $tags . ',functionId=' . $functionId . ',functionStatus=' . $functionExecutionStatus);
$this->statsd->increment('executions.{scope}.compute' . $functionTags . ',functionStatus=' . $functionExecutionStatus);
if ($functionExecutionTime > 0) {
$this->statsd->count('executions.{scope}.compute.time' . $tags . ',functionId=' . $functionId, $functionExecutionTime);
$this->statsd->count('executions.{scope}.compute.time' . $functionTags, $functionExecutionTime);
}
}
if ($functionBuild >= 1) {
$this->statsd->increment('builds.{scope}.compute' . $tags . ',functionId=' . $functionId . ',functionBuildStatus=' . $functionBuildStatus);
$this->statsd->count('builds.{scope}.compute.time' . $tags . ',functionId=' . $functionId, $functionBuildTime);
$this->statsd->increment('builds.{scope}.compute' . $functionTags . ',functionBuildStatus=' . $functionBuildStatus);
$this->statsd->count('builds.{scope}.compute.time' . $functionTags, $functionBuildTime);
}
if ($functionBuild + $functionExecution >= 1) {
$this->statsd->count('project.{scope}.compute.time' . $tags . ',functionId=' . $functionId, $functionCompute);
$this->statsd->count('project.{scope}.compute.time' . $functionTags, $functionCompute);
}
$this->reset();
@@ -7,7 +7,8 @@ use Appwrite\Utopia\Database\Validator\Queries\Base;
class Projects extends Base
{
public const ALLOWED_ATTRIBUTES = [
'name'
'name',
'teamId'
];
/**
+5
View File
@@ -70,6 +70,7 @@ use Appwrite\Utopia\Response\Model\HealthStatus;
use Appwrite\Utopia\Response\Model\HealthTime;
use Appwrite\Utopia\Response\Model\HealthVersion;
use Appwrite\Utopia\Response\Model\Mock; // Keep last
use Appwrite\Utopia\Response\Model\Provider;
use Appwrite\Utopia\Response\Model\Runtime;
use Appwrite\Utopia\Response\Model\UsageBuckets;
use Appwrite\Utopia\Response\Model\UsageCollection;
@@ -194,6 +195,8 @@ class Response extends SwooleResponse
public const MODEL_WEBHOOK_LIST = 'webhookList';
public const MODEL_KEY = 'key';
public const MODEL_KEY_LIST = 'keyList';
public const MODEL_PROVIDER = 'provider';
public const MODEL_PROVIDER_LIST = 'providerList';
public const MODEL_PLATFORM = 'platform';
public const MODEL_PLATFORM_LIST = 'platformList';
public const MODEL_DOMAIN = 'domain';
@@ -260,6 +263,7 @@ class Response extends SwooleResponse
->setModel(new BaseList('Projects List', self::MODEL_PROJECT_LIST, 'projects', self::MODEL_PROJECT, true, false))
->setModel(new BaseList('Webhooks List', self::MODEL_WEBHOOK_LIST, 'webhooks', self::MODEL_WEBHOOK, true, false))
->setModel(new BaseList('API Keys List', self::MODEL_KEY_LIST, 'keys', self::MODEL_KEY, true, false))
->setModel(new BaseList('Providers List', self::MODEL_PROVIDER_LIST, 'platforms', self::MODEL_PROVIDER, true, false))
->setModel(new BaseList('Platforms List', self::MODEL_PLATFORM_LIST, 'platforms', self::MODEL_PLATFORM, true, false))
->setModel(new BaseList('Domains List', self::MODEL_DOMAIN_LIST, 'domains', self::MODEL_DOMAIN, true, false))
->setModel(new BaseList('Countries List', self::MODEL_COUNTRY_LIST, 'countries', self::MODEL_COUNTRY))
@@ -314,6 +318,7 @@ class Response extends SwooleResponse
->setModel(new Webhook())
->setModel(new Key())
->setModel(new Domain())
->setModel(new Provider())
->setModel(new Platform())
->setModel(new Variable())
->setModel(new Country())
@@ -82,6 +82,12 @@ class Deployment extends Model
'default' => '',
'example' => 'enabled',
])
->addRule('buildTime', [
'type' => self::TYPE_INTEGER,
'description' => 'The current build time in seconds.',
'default' => 0,
'example' => 128,
])
;
}
+30 -27
View File
@@ -2,6 +2,7 @@
namespace Appwrite\Utopia\Response\Model;
use Appwrite\Auth\Auth;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
use Utopia\Config\Config;
@@ -101,12 +102,25 @@ class Project extends Model
'default' => '',
'example' => '131102020',
])
->addRule('authDuration', [
'type' => self::TYPE_INTEGER,
'description' => 'Session duration in seconds.',
'default' => Auth::TOKEN_EXPIRATION_LOGIN_LONG,
'example' => 60,
])
->addRule('authLimit', [
'type' => self::TYPE_INTEGER,
'description' => 'Max users allowed. 0 is unlimited.',
'default' => 0,
'example' => 100,
])
->addRule('providers', [
'type' => Response::MODEL_PROVIDER,
'description' => 'List of Providers.',
'default' => [],
'example' => new \stdClass(),
'array' => true,
])
->addRule('platforms', [
'type' => Response::MODEL_PLATFORM,
'description' => 'List of Platforms.',
@@ -138,32 +152,8 @@ class Project extends Model
;
$services = Config::getParam('services', []);
$providers = Config::getParam('providers', []);
$auth = Config::getParam('auth', []);
foreach ($providers as $index => $provider) {
if (!$provider['enabled']) {
continue;
}
$name = (isset($provider['name'])) ? $provider['name'] : 'Unknown';
$this
->addRule('provider' . \ucfirst($index) . 'Appid', [
'type' => self::TYPE_STRING,
'description' => $name . ' OAuth app ID.',
'example' => '123247283472834787438',
'default' => '',
])
->addRule('provider' . \ucfirst($index) . 'Secret', [
'type' => self::TYPE_STRING,
'description' => $name . ' OAuth secret ID.',
'example' => 'djsgudsdsewe43434343dd34...',
'default' => '',
])
;
}
foreach ($auth as $index => $method) {
$name = $method['name'] ?? '';
$key = $method['key'] ?? '';
@@ -224,6 +214,7 @@ class Project extends Model
*/
public function filter(Document $document): Document
{
// Services
$values = $document->getAttribute('services', []);
$services = Config::getParam('services', []);
@@ -236,10 +227,12 @@ class Project extends Model
$document->setAttribute('serviceStatusFor' . ucfirst($key), $value);
}
// Auth
$authValues = $document->getAttribute('auths', []);
$auth = Config::getParam('auth', []);
$document->setAttribute('authLimit', $authValues['limit'] ?? 0);
$document->setAttribute('authDuration', $authValues['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG);
foreach ($auth as $index => $method) {
$key = $method['key'];
@@ -247,17 +240,27 @@ class Project extends Model
$document->setAttribute('auth' . ucfirst($key), $value);
}
// Providers
$providers = Config::getParam('providers', []);
$providerValues = $document->getAttribute('authProviders', []);
$projectProviders = [];
foreach ($providers as $key => $provider) {
if (!$provider['enabled']) {
// Disabled by Appwrite configuration, exclude from response
continue;
}
$appId = $providerValues[$key . 'Appid'] ?? '';
$secret = $providerValues[$key . 'Secret'] ?? '';
$document->setAttribute('provider' . ucfirst($key) . 'Appid', $appId)->setAttribute('provider' . ucfirst($key) . 'Secret', $secret);
$projectProviders[] = new Document([
'name' => ucfirst($key),
'appId' => $providerValues[$key . 'Appid'] ?? '',
'secret' => $providerValues[$key . 'Secret'] ?? '',
'enabled' => $providerValues[$key . 'Enabled'] ?? false,
]);
}
$document->setAttribute("providers", $projectProviders);
return $document;
}
}
@@ -0,0 +1,63 @@
<?php
namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
class Provider extends Model
{
/**
* @var bool
*/
protected bool $public = false;
public function __construct()
{
$this
->addRule('name', [
'type' => self::TYPE_STRING,
'description' => 'Provider name.',
'default' => '',
'example' => 'GitHub',
])
->addRule('appId', [
'type' => self::TYPE_STRING,
'description' => 'OAuth 2.0 application ID.',
'default' => '',
'example' => '259125845563242502',
])
->addRule('secret', [
'type' => self::TYPE_STRING,
'description' => 'OAuth 2.0 application secret. Might be JSON string if provider requires extra configuration.',
'default' => '',
'example' => 'Bpw_g9c2TGXxfgLshDbSaL8tsCcqgczQ',
])
->addRule('enabled', [
'type' => self::TYPE_BOOLEAN,
'description' => 'Provider is active and can be used to create session.',
'example' => '',
])
;
}
/**
* Get Name
*
* @return string
*/
public function getName(): string
{
return 'Provider';
}
/**
* Get Type
*
* @return string
*/
public function getType(): string
{
return Response::MODEL_PROVIDER;
}
}
@@ -17,45 +17,45 @@ class UsageBuckets extends Model
'example' => '30d',
])
->addRule('filesCount', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of files in this bucket.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('filesStorage', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total storage of files in this bucket.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('filesCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for files created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('filesRead', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for files read.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('filesUpdate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for files updated.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('filesDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for files deleted.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
;
@@ -17,38 +17,38 @@ class UsageCollection extends Model
'example' => '30d',
])
->addRule('documentsCount', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of documents.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsRead', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents read.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsUpdate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents updated.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents deleted.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
;
@@ -17,73 +17,73 @@ class UsageDatabase extends Model
'example' => '30d',
])
->addRule('documentsCount', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of documents.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collectionsCount', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of collections.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsRead', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents read.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsUpdate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents updated.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents deleted.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collectionsCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for collections created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collectionsRead', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for collections read.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collectionsUpdate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for collections updated.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collectionsDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for collections delete.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
;
@@ -17,108 +17,108 @@ class UsageDatabases extends Model
'example' => '30d',
])
->addRule('databasesCount', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of documents.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsCount', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of documents.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collectionsCount', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of collections.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('databasesCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('databasesRead', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents read.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('databasesUpdate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents updated.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('databasesDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of collections.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsRead', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents read.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsUpdate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents updated.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents deleted.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collectionsCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for collections created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collectionsRead', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for collections read.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collectionsUpdate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for collections updated.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collectionsDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for collections delete.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
;
@@ -17,59 +17,59 @@ class UsageFunction extends Model
'example' => '30d',
])
->addRule('executionsTotal', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for number of function executions.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('executionsFailure', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function execution failures.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('executionsSuccess', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function execution successes.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('executionsTime', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function execution duration.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('buildsTotal', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for number of function builds.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('buildsFailure', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function build failures.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('buildsSuccess', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function build successes.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('buildsTime', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function build duration.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
;
@@ -17,59 +17,59 @@ class UsageFunctions extends Model
'example' => '30d',
])
->addRule('executionsTotal', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for number of function executions.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('executionsFailure', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function execution failures.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('executionsSuccess', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function execution successes.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('executionsTime', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function execution duration.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('buildsTotal', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for number of function builds.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('buildsFailure', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function build failures.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('buildsSuccess', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function build successes.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('buildsTime', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function build duration.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
;
@@ -17,52 +17,59 @@ class UsageProject extends Model
'example' => '30d',
])
->addRule('requests', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for number of requests.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('network', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for consumed bandwidth.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('executions', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function executions.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documents', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for number of documents.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collections', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for number of collections.',
->addRule('databases', [
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for number of databases.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('users', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for number of users.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('storage', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for the occupied storage size (in bytes).',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('buckets', [
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for number of buckets.',
'default' => [],
'example' => [],
'array' => true
])
;
@@ -17,80 +17,80 @@ class UsageStorage extends Model
'example' => '30d',
])
->addRule('storage', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for the occupied storage size (in bytes).',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('filesCount', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of files.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('bucketsCount', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of buckets.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('bucketsCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for buckets created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('bucketsRead', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for buckets read.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('bucketsUpdate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for buckets updated.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('bucketsDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for buckets deleted.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('filesCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for files created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('filesRead', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for files read.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('filesUpdate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for files updated.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('filesDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for files deleted.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
;
@@ -17,59 +17,59 @@ class UsageUsers extends Model
'example' => '30d',
])
->addRule('usersCount', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of users.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('usersCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for users created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('usersRead', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for users read.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('usersUpdate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for users updated.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('usersDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for users deleted.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('sessionsCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for sessions created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('sessionsProviderCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for sessions created for a provider ( email, anonymous or oauth2 ).',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('sessionsDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for sessions deleted.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
;