diff --git a/composer.lock b/composer.lock index 1854fe86be..bf8963e887 100644 --- a/composer.lock +++ b/composer.lock @@ -2446,7 +2446,7 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "7a4c9b48b3ad06fb850cf8394c671603223bc872" + "reference": "4327c4cbaafc39cd94ec4d977cbdc25c8e9df613" }, "require": { "ext-json": "*", @@ -2495,7 +2495,7 @@ "upf", "utopia" ], - "time": "2022-07-14T02:00:12+00:00" + "time": "2022-07-14T07:30:15+00:00" }, { "name": "utopia-php/preloader", @@ -5437,5 +5437,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.2.0" } diff --git a/src/Appwrite/Platform/Action.php b/src/Appwrite/Platform/Action.php new file mode 100644 index 0000000000..314d7ede20 --- /dev/null +++ b/src/Appwrite/Platform/Action.php @@ -0,0 +1,110 @@ +get('logger'); + + if ($logger) { + $version = App::getEnv('_APP_VERSION', 'UNKNOWN'); + + $log = new Log(); + $log->setNamespace("usage"); + $log->setServer(\gethostname()); + $log->setVersion($version); + $log->setType(Log::TYPE_ERROR); + $log->setMessage($error->getMessage()); + + $log->addTag('code', $error->getCode()); + $log->addTag('verboseType', get_class($error)); + + $log->addExtra('file', $error->getFile()); + $log->addExtra('line', $error->getLine()); + $log->addExtra('trace', $error->getTraceAsString()); + $log->addExtra('detailedTrace', $error->getTrace()); + + $log->setAction($action); + + $isProduction = App::getEnv('_APP_ENV', 'development') === 'production'; + $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); + + $responseCode = $logger->addLog($log); + Console::info('Usage stats log pushed with status code: ' . $responseCode); + } + + Console::warning("Failed: {$error->getMessage()}"); + Console::warning($error->getTraceAsString()); + } + + protected function getDatabase(Registry &$register, string $namespace): Database + { + $attempts = 0; + + do { + try { + $attempts++; + + $db = $register->get('db'); + $redis = $register->get('cache'); + + $cache = new Cache(new RedisCache($redis)); + $database = new Database(new MariaDB($db), $cache); + $database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); + $database->setNamespace($namespace); + + if (!$database->exists($database->getDefaultDatabase(), 'projects')) { + throw new Exception('Projects collection not ready'); + } + break; // leave loop if successful + } catch (\Exception$e) { + Console::warning("Database not ready. Retrying connection ({$attempts})..."); + if ($attempts >= DATABASE_RECONNECT_MAX_ATTEMPTS) { + throw new \Exception('Failed to connect to database: ' . $e->getMessage()); + } + sleep(DATABASE_RECONNECT_SLEEP); + } + } while ($attempts < DATABASE_RECONNECT_MAX_ATTEMPTS); + + return $database; + } + + protected function getInfluxDB(Registry &$register): InfluxDatabase + { + /** @var InfluxDB\Client $client */ + $client = $register->get('influxdb'); + $attempts = 0; + $max = 10; + $sleep = 1; + + do { // check if telegraf database is ready + try { + $attempts++; + $database = $client->selectDB('telegraf'); + if (in_array('telegraf', $client->listDatabases())) { + break; // leave the do-while if successful + } + } catch (\Throwable$th) { + Console::warning("InfluxDB not ready. Retrying connection ({$attempts})..."); + if ($attempts >= $max) { + throw new \Exception('InfluxDB database not ready yet'); + } + sleep($sleep); + } + } while ($attempts < $max); + return $database; + } +} \ No newline at end of file diff --git a/src/Appwrite/Task/Usage.php b/src/Appwrite/Task/Usage.php index f2f0b73f76..2093f32720 100644 --- a/src/Appwrite/Task/Usage.php +++ b/src/Appwrite/Task/Usage.php @@ -2,88 +2,21 @@ namespace Appwrite\Task; +use Appwrite\Platform\Action; use Throwable; use Exception; use Appwrite\Stats\Usage as InfluxUsage; use Appwrite\Stats\UsageDB; -use InfluxDB\Database as InfluxDatabase; use Utopia\App; -use Utopia\Cache\Adapter\Redis as RedisCache; -use Utopia\Cache\Cache; use Utopia\CLI\Console; -use Utopia\Database\Adapter\MariaDB; -use Utopia\Database\Database; use Utopia\Database\Validator\Authorization; -use Utopia\Registry\Registry; -use Utopia\Logger\Log; -use Utopia\Platform\Action; class Usage extends Action { public const NAME = 'usage'; - protected function getDatabase(Registry &$register, string $namespace): Database - { - $attempts = 0; - - do { - try { - $attempts++; - - $db = $register->get('db'); - $redis = $register->get('cache'); - - $cache = new Cache(new RedisCache($redis)); - $database = new Database(new MariaDB($db), $cache); - $database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); - $database->setNamespace($namespace); - - if (!$database->exists($database->getDefaultDatabase(), 'projects')) { - throw new Exception('Projects collection not ready'); - } - break; // leave loop if successful - } catch (\Exception$e) { - Console::warning("Database not ready. Retrying connection ({$attempts})..."); - if ($attempts >= DATABASE_RECONNECT_MAX_ATTEMPTS) { - throw new \Exception('Failed to connect to database: ' . $e->getMessage()); - } - sleep(DATABASE_RECONNECT_SLEEP); - } - } while ($attempts < DATABASE_RECONNECT_MAX_ATTEMPTS); - - return $database; - } - - protected function getInfluxDB(Registry &$register): InfluxDatabase - { - /** @var InfluxDB\Client $client */ - $client = $register->get('influxdb'); - $attempts = 0; - $max = 10; - $sleep = 1; - - do { // check if telegraf database is ready - try { - $attempts++; - $database = $client->selectDB('telegraf'); - if (in_array('telegraf', $client->listDatabases())) { - break; // leave the do-while if successful - } - } catch (\Throwable$th) { - Console::warning("InfluxDB not ready. Retrying connection ({$attempts})..."); - if ($attempts >= $max) { - throw new \Exception('InfluxDB database not ready yet'); - } - sleep($sleep); - } - } while ($attempts < $max); - return $database; - } - public function __construct() { - - $this ->desc('Schedules syncing data from influxdb to Appwrite console db') ->callback(fn () => $this->action()); @@ -91,45 +24,12 @@ class Usage extends Action public function action() { - global $register; Authorization::disable(); Authorization::setDefaultStatus(false); - $logError = function (Throwable $error, string $action = 'syncUsageStats') use ($register) { - $logger = $register->get('logger'); - - if ($logger) { - $version = App::getEnv('_APP_VERSION', 'UNKNOWN'); - - $log = new Log(); - $log->setNamespace("usage"); - $log->setServer(\gethostname()); - $log->setVersion($version); - $log->setType(Log::TYPE_ERROR); - $log->setMessage($error->getMessage()); - - $log->addTag('code', $error->getCode()); - $log->addTag('verboseType', get_class($error)); - - $log->addExtra('file', $error->getFile()); - $log->addExtra('line', $error->getLine()); - $log->addExtra('trace', $error->getTraceAsString()); - $log->addExtra('detailedTrace', $error->getTrace()); - - $log->setAction($action); - - $isProduction = App::getEnv('_APP_ENV', 'development') === 'production'; - $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); - - $responseCode = $logger->addLog($log); - Console::info('Usage stats log pushed with status code: ' . $responseCode); - } - - Console::warning("Failed: {$error->getMessage()}"); - Console::warning($error->getTraceAsString()); - }; + $logError = fn(Throwable $error, string $action = 'syncUsageStats') => $this->logError($register, $error, $action); Console::title('Usage Aggregation V1'); Console::success(APP_NAME . ' usage aggregation process v1 has started');