diff --git a/app/cli.php b/app/cli.php index a6267fa341..3e093dc13d 100644 --- a/app/cli.php +++ b/app/cli.php @@ -28,13 +28,13 @@ use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; use Utopia\DI\Container; use Utopia\DSN\DSN; -use Utopia\Logger\Log; use Utopia\Platform\Service; use Utopia\Pools\Group; use Utopia\Queue\Broker\Pool as BrokerPool; use Utopia\Queue\Publisher; use Utopia\Queue\Queue; use Utopia\Registry\Registry; +use Utopia\Span\Span; use Utopia\System\System; use Utopia\Telemetry\Adapter\None as NoTelemetry; @@ -267,8 +267,8 @@ $container->set('queueForFunctions', function (Publisher $publisher) { $container->set('queueForDeletes', function (Publisher $publisher) { return new Delete($publisher); }, ['publisher']); -$container->set('logError', function (Registry $register) { - return function (Throwable $error, string $namespace, string $action) use ($register) { +$container->set('logError', function () { + return function (Throwable $error, string $namespace, string $action) { Console::error('[Error] Timestamp: ' . date('c', time())); Console::error('[Error] Type: ' . get_class($error)); Console::error('[Error] Message: ' . $error->getMessage()); @@ -276,48 +276,42 @@ $container->set('logError', function (Registry $register) { Console::error('[Error] Line: ' . $error->getLine()); Console::error('[Error] Trace: ' . $error->getTraceAsString()); - $logger = $register->get('logger'); + $span = Span::current(); + $shouldFinish = false; + if ($span === null) { + $span = Span::init($action); + $shouldFinish = true; + } - if ($logger) { - $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); + Span::add('level', 'error'); + Span::add('logger', $namespace); + Span::add('server.name', System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); + Span::add('release', System::getEnv('_APP_VERSION', 'UNKNOWN')); + Span::add('environment', System::getEnv('_APP_ENV', 'development') === 'production' ? 'production' : 'staging'); + Span::add('appwrite.error.publish', true); + Span::add('appwrite.error.action', $action); + Span::add('error.message', $error->getMessage()); + Span::add('error.type', get_class($error)); + Span::add('error.code', $error->getCode()); + Span::add('error.file', $error->getFile()); + Span::add('error.line', $error->getLine()); + Span::add('error.trace', $error->getTraceAsString()); + Span::add('error.detailedTrace', \json_encode($error->getTrace()) ?: null); - $log = new Log(); - $log->setNamespace($namespace); - $log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \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()); - - if ($error->getPrevious() !== null) { - if ($error->getPrevious()->getMessage() != $error->getMessage()) { - $log->addExtra('previousMessage', $error->getPrevious()->getMessage()); - } - $log->addExtra('previousFile', $error->getPrevious()->getFile()); - $log->addExtra('previousLine', $error->getPrevious()->getLine()); + if ($error->getPrevious() !== null) { + if ($error->getPrevious()->getMessage() != $error->getMessage()) { + Span::add('error.previous.message', $error->getPrevious()->getMessage()); } + Span::add('error.previous.file', $error->getPrevious()->getFile()); + Span::add('error.previous.line', $error->getPrevious()->getLine()); + } - $log->setAction($action); - - $isProduction = System::getEnv('_APP_ENV', 'development') === 'production'; - $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); - - try { - $responseCode = $logger->addLog($log); - Console::info('Error log pushed with status code: ' . $responseCode); - } catch (Throwable $th) { - Console::error('Error pushing log: ' . $th->getMessage()); - } + Span::error($error); + if ($shouldFinish) { + $span->finish(); } }; -}, ['register']); +}, []); $container->set('executor', fn () => new Executor(), []); diff --git a/app/controllers/general.php b/app/controllers/general.php index eb4899a3d8..7b17cb166d 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -57,10 +57,6 @@ use Utopia\Domains\Domain; use Utopia\DSN\DSN; use Utopia\Http\Http; use Utopia\Locale\Locale; -use Utopia\Logger\Adapter\Sentry; -use Utopia\Logger\Log; -use Utopia\Logger\Log\User; -use Utopia\Logger\Logger; use Utopia\Platform\Service; use Utopia\Span\Span; use Utopia\System\System; @@ -69,7 +65,7 @@ use Utopia\Validator\Text; Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE); -function router(Http $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Event $queueForEvents, Bus $bus, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Authorization $authorization, ?Key $apiKey, DeleteEvent $queueForDeletes, int $executionsRetentionCount) +function router(Http $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, Bus $bus, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Authorization $authorization, ?Key $apiKey, DeleteEvent $queueForDeletes, int $executionsRetentionCount) { $host = $request->getHostname(); if (!empty($previewHostname)) { @@ -146,7 +142,7 @@ function router(Http $utopia, Database $dbForPlatform, callable $getProjectDB, S /** * Set projectId to update the Error hook logger, since x-appwrite-project is not available when executing custom domain function */ - $log->addTag('projectId', $project->getId()); + Span::add('projectId', $project->getId()); } if (array_key_exists('proxy', $project->getAttribute('services', []))) { @@ -830,7 +826,6 @@ Http::init() ->inject('swooleRequest') ->inject('request') ->inject('response') - ->inject('log') ->inject('project') ->inject('dbForPlatform') ->inject('getProjectDB') @@ -849,7 +844,7 @@ Http::init() ->inject('authorization') ->inject('queueForDeletes') ->inject('executionsRetentionCount') - ->action(function (Http $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, Reader $geodb, Event $queueForEvents, Bus $bus, Executor $executor, array $platform, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization, DeleteEvent $queueForDeletes, int $executionsRetentionCount) { + ->action(function (Http $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, Reader $geodb, Event $queueForEvents, Bus $bus, Executor $executor, array $platform, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization, DeleteEvent $queueForDeletes, int $executionsRetentionCount) { /* * Appwrite Router */ @@ -857,7 +852,7 @@ Http::init() $platformHostnames = $platform['hostnames'] ?? []; // Only run Router when external domain if (!\in_array($hostname, $platformHostnames) || !empty($previewHostname)) { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $bus, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $bus, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount)) { $utopia->getRoute()?->label('router', true); } } @@ -1131,7 +1126,6 @@ Http::options() ->inject('swooleRequest') ->inject('request') ->inject('response') - ->inject('log') ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('queueForEvents') @@ -1148,14 +1142,14 @@ Http::options() ->inject('authorization') ->inject('queueForDeletes') ->inject('executionsRetentionCount') - ->action(function (Http $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, Bus $bus, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization, DeleteEvent $queueForDeletes, int $executionsRetentionCount) { + ->action(function (Http $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, Bus $bus, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization, DeleteEvent $queueForDeletes, int $executionsRetentionCount) { /* * Appwrite Router */ $platformHostnames = $platform['hostnames'] ?? []; // Only run Router when external domain if (!in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $bus, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $bus, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount)) { $utopia->getRoute()?->label('router', true); } } @@ -1184,12 +1178,10 @@ Http::error() ->inject('request') ->inject('response') ->inject('project') - ->inject('logger') - ->inject('log') ->inject('bus') ->inject('devKey') ->inject('authorization') - ->action(function (Throwable $error, Http $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, Bus $bus, Document $devKey, Authorization $authorization) { + ->action(function (Throwable $error, Http $utopia, Request $request, Response $response, Document $project, Bus $bus, Document $devKey, Authorization $authorization) { $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); $route = $utopia->getRoute(); $class = \get_class($error); @@ -1232,27 +1224,8 @@ Http::error() $providerConfig = System::getEnv('_APP_EXPERIMENT_LOGGING_CONFIG', ''); if (!empty($providerConfig) && $error->getCode() >= 400 && $error->getCode() < 500) { - // Register error logger - try { - $loggingProvider = new DSN($providerConfig); - $providerName = $loggingProvider->getScheme(); - - if (!empty($providerName) && $providerName === 'sentry') { - $key = $loggingProvider->getPassword(); - $projectId = $loggingProvider->getUser() ?? ''; - $host = 'https://' . $loggingProvider->getHost(); - $sampleRate = $loggingProvider->getParam('sample', 0.01); - - $adapter = new Sentry($projectId, $key, $host); - $logger = new Logger($adapter); - $logger->setSample($sampleRate); - $publish = true; - } else { - throw new \Exception('Invalid experimental logging provider'); - } - } catch (\Throwable $th) { - Console::warning('Failed to initialize logging provider: ' . $th->getMessage()); - } + $publish = true; + Span::add('appwrite.error.experimental', true); } /** @@ -1277,7 +1250,7 @@ Http::error() } } - if ($logger && $publish) { + if ($publish) { try { /** @var Utopia\Database\Document $user */ $user = $utopia->getResource('user'); @@ -1285,12 +1258,6 @@ Http::error() // All good, user is optional information for logger } - if (isset($user) && !$user->isEmpty()) { - $log->setUser(new User($user->getId())); - } else { - $log->setUser(new User('guest-' . hash('sha256', $request->getIP()))); - } - try { $dsn = new DSN($project->getAttribute('database', 'console')); } catch (\InvalidArgumentException) { @@ -1298,30 +1265,26 @@ Http::error() $dsn = new DSN('mysql://' . $project->getAttribute('database', 'console')); } - $log->setNamespace("http"); - $log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); - $log->setVersion($version); - $log->setType(Log::TYPE_ERROR); - $log->setMessage($error->getMessage()); - - $log->addTag('database', $dsn->getHost()); - $log->addTag('method', $route?->getMethod() ?? $request->getMethod()); - $log->addTag('url', $request->getURI()); - $log->addTag('verboseType', get_class($error)); - $log->addTag('code', $error->getCode()); - - $tags = $log->getTags(); - if (!isset($tags['projectId'])) { - $log->addTag('projectId', $project->getId()); - } - - $log->addTag('hostname', $request->getHostname()); - $log->addTag('locale', (string)$request->getParam('locale', $request->getHeader('x-appwrite-locale', ''))); - - $log->addExtra('file', $error->getFile()); - $log->addExtra('line', $error->getLine()); - $log->addExtra('trace', $error->getTraceAsString()); - $log->addExtra('roles', $authorization->getRoles()); + Span::add('level', 'error'); + Span::add('logger', 'http'); + Span::add('server.name', System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); + Span::add('release', $version); + Span::add('environment', System::getEnv('_APP_ENV', 'development') === 'production' ? 'production' : 'staging'); + Span::add('appwrite.error.publish', true); + Span::add('database', $dsn->getHost()); + Span::add('method', $route?->getMethod() ?? $request->getMethod()); + Span::add('url', $request->getURI()); + Span::add('verboseType', get_class($error)); + Span::add('code', $error->getCode()); + Span::add('projectId', $project->getId()); + Span::add('hostname', $request->getHostname()); + Span::add('locale', (string)$request->getParam('locale', $request->getHeader('x-appwrite-locale', ''))); + Span::add('userId', isset($user) && !$user->isEmpty() ? $user->getId() : 'guest-' . hash('sha256', $request->getIP())); + Span::add('error.message', $error->getMessage()); + Span::add('error.file', $error->getFile()); + Span::add('error.line', $error->getLine()); + Span::add('error.trace', $error->getTraceAsString()); + Span::add('roles', \json_encode($authorization->getRoles()) ?: null); try { /* add queries to log */ @@ -1396,7 +1359,7 @@ Http::error() } if (!empty($formattedQueries)) { - $log->addExtra('queries', $formattedQueries); + Span::add('queries', \json_encode($formattedQueries) ?: null); } } } catch (Throwable $_) { @@ -1416,18 +1379,8 @@ Http::error() $action = 'http.' . $request->getMethod() . '.' . $path; } - $log->setAction($action); - $log->addTag('service', $action); - - $isProduction = System::getEnv('_APP_ENV', 'development') === 'production'; - $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); - - try { - $responseCode = $logger->addLog($log); - Console::info('Error log pushed with status code: ' . $responseCode); - } catch (Throwable $th) { - Console::error('Error pushing log: ' . $th->getMessage()); - } + Span::add('appwrite.error.action', $action); + Span::add('service', $action); } /** Wrap all exceptions inside Appwrite\Extend\Exception */ @@ -1536,7 +1489,6 @@ Http::get('/robots.txt') ->inject('swooleRequest') ->inject('request') ->inject('response') - ->inject('log') ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('queueForEvents') @@ -1550,13 +1502,13 @@ Http::get('/robots.txt') ->inject('authorization') ->inject('queueForDeletes') ->inject('executionsRetentionCount') - ->action(function (Http $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, Bus $bus, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey, Authorization $authorization, DeleteEvent $queueForDeletes, int $executionsRetentionCount) { + ->action(function (Http $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, Bus $bus, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey, Authorization $authorization, DeleteEvent $queueForDeletes, int $executionsRetentionCount) { $platformHostnames = $platform['hostnames'] ?? []; if (in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) { $template = new View(__DIR__ . '/../views/general/robots.phtml'); $response->text($template->render(false)); } else { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $bus, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $bus, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount)) { $utopia->getRoute()?->label('router', true); } } @@ -1570,7 +1522,6 @@ Http::get('/humans.txt') ->inject('swooleRequest') ->inject('request') ->inject('response') - ->inject('log') ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('queueForEvents') @@ -1584,13 +1535,13 @@ Http::get('/humans.txt') ->inject('authorization') ->inject('queueForDeletes') ->inject('executionsRetentionCount') - ->action(function (Http $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, Bus $bus, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey, Authorization $authorization, DeleteEvent $queueForDeletes, int $executionsRetentionCount) { + ->action(function (Http $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, Bus $bus, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey, Authorization $authorization, DeleteEvent $queueForDeletes, int $executionsRetentionCount) { $platformHostnames = $platform['hostnames'] ?? []; if (in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) { $template = new View(__DIR__ . '/../views/general/humans.phtml'); $response->text($template->render(false)); } else { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $bus, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $bus, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount)) { $utopia->getRoute()?->label('router', true); } } diff --git a/app/http.php b/app/http.php index b72f3b7f34..5ca77a3f89 100644 --- a/app/http.php +++ b/app/http.php @@ -29,8 +29,6 @@ use Utopia\Database\Query; use Utopia\Http\Adapter\Swoole\Server; use Utopia\Http\Files; use Utopia\Http\Http; -use Utopia\Logger\Log; -use Utopia\Logger\Log\User; use Utopia\Span\Span; use Utopia\System\System; @@ -552,72 +550,41 @@ $swooleAdapter->onRequest(function ($utopiaRequest, $utopiaResponse) use ($files $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); - $logger = $app->getResource("logger"); - if ($logger) { - try { - /** @var Utopia\Database\Document $user */ - $user = $app->getResource('user'); - } catch (\Throwable $_th) { - // All good, user is optional information for logger - } - - $route = $app->getRoute(); - - $log = $app->getResource("log"); - - if (isset($user) && !$user->isEmpty()) { - $log->setUser(new User($user->getId())); - } else { - $log->setUser(new User('guest-' . hash('sha256', $request->getIP()))); - } - - $log->setNamespace("http"); - $log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); - $log->setVersion($version); - $log->setType(Log::TYPE_ERROR); - $log->setMessage($th->getMessage()); - - $log->addTag('method', $route?->getMethod() ?? $request->getMethod()); - $log->addTag('url', $route?->getPath() ?? $request->getURI()); - $log->addTag('verboseType', get_class($th)); - $log->addTag('code', $th->getCode()); - // $log->addTag('projectId', $project->getId()); // TODO: Figure out how to get ProjectID, if it becomes relevant - $log->addTag('hostname', $request->getHostname()); - $log->addTag('locale', (string)$request->getParam('locale', $request->getHeader('x-appwrite-locale', ''))); - - $log->addExtra('file', $th->getFile()); - $log->addExtra('line', $th->getLine()); - $log->addExtra('trace', $th->getTraceAsString()); - $log->addExtra('roles', isset($authorization) ? $authorization->getRoles() : []); - - $sdk = $route?->getLabel("sdk", false); - - $action = 'UNKNOWN_NAMESPACE.UNKNOWN.METHOD'; - if (!empty($sdk)) { - if (\is_array($sdk)) { - $sdk = $sdk[0]; - } - /** @var Appwrite\SDK\Method $sdk */ - $action = $sdk->getNamespace() . '.' . $sdk->getMethodName(); - } elseif ($route === null) { - $path = ltrim(parse_url($request->getURI(), PHP_URL_PATH) ?? '/', '/') ?: 'root'; - $action = 'http.' . $request->getMethod() . '.' . $path; - } - - $log->setAction($action); - $log->addTag('service', $action); - - $isProduction = System::getEnv('_APP_ENV', 'development') === 'production'; - $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); - - try { - $responseCode = $logger->addLog($log); - Console::info('Error log pushed with status code: ' . $responseCode); - } catch (Throwable $th) { - Console::error('Error pushing log: ' . $th->getMessage()); + $route = $app->getRoute(); + $sdk = $route?->getLabel("sdk", false); + + $action = 'UNKNOWN_NAMESPACE.UNKNOWN.METHOD'; + if (!empty($sdk)) { + if (\is_array($sdk)) { + $sdk = $sdk[0]; } + /** @var Appwrite\SDK\Method $sdk */ + $action = $sdk->getNamespace() . '.' . $sdk->getMethodName(); + } elseif ($route === null) { + $path = ltrim(parse_url($request->getURI(), PHP_URL_PATH) ?? '/', '/') ?: 'root'; + $action = 'http.' . $request->getMethod() . '.' . $path; } + Span::add('level', 'error'); + Span::add('logger', 'http'); + Span::add('server.name', System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); + Span::add('release', $version); + Span::add('environment', System::getEnv('_APP_ENV', 'development') === 'production' ? 'production' : 'staging'); + Span::add('appwrite.error.publish', true); + Span::add('appwrite.error.action', $action); + Span::add('method', $route?->getMethod() ?? $request->getMethod()); + Span::add('url', $route?->getPath() ?? $request->getURI()); + Span::add('verboseType', get_class($th)); + Span::add('code', $th->getCode()); + Span::add('hostname', $request->getHostname()); + Span::add('locale', (string)$request->getParam('locale', $request->getHeader('x-appwrite-locale', ''))); + Span::add('service', $action); + Span::add('error.message', $th->getMessage()); + Span::add('error.file', $th->getFile()); + Span::add('error.line', $th->getLine()); + Span::add('error.trace', $th->getTraceAsString()); + Span::add('roles', isset($authorization) ? (\json_encode($authorization->getRoles()) ?: null) : '[]'); + $swooleResponse = $utopiaResponse->getSwooleResponse(); $swooleResponse->setStatusCode(500); diff --git a/app/init/registers.php b/app/init/registers.php index 54c0053a33..c4aefdaeb5 100644 --- a/app/init/registers.php +++ b/app/init/registers.php @@ -9,7 +9,6 @@ use MaxMind\Db\Reader; use Swoole\Database\PDOProxy; use Utopia\Cache\Adapter\Redis as RedisCache; use Utopia\Config\Config; -use Utopia\Console; use Utopia\Database\Adapter\MariaDB; use Utopia\Database\Adapter\Mongo; use Utopia\Database\Adapter\MySQL; @@ -19,11 +18,6 @@ use Utopia\Database\PDO; use Utopia\Domains\Validator\PublicDomain; use Utopia\DSN\DSN; use Utopia\Http\Http; -use Utopia\Logger\Adapter\AppSignal; -use Utopia\Logger\Adapter\LogOwl; -use Utopia\Logger\Adapter\Raygun; -use Utopia\Logger\Adapter\Sentry; -use Utopia\Logger\Logger; use Utopia\Messaging\Adapter\Email\SMTP; use Utopia\Mongo\Client as MongoClient; use Utopia\Pools\Adapter\Stack as StackPool; @@ -46,109 +40,6 @@ if (!Http::isProduction()) { PublicDomain::allow(['request-catcher-webhook']); } -$register->set('logger', function () { - // Register error logger - $providerName = System::getEnv('_APP_LOGGING_PROVIDER', ''); - $providerConfig = System::getEnv('_APP_LOGGING_CONFIG', ''); - - if (empty($providerConfig)) { - return; - } - - try { - $loggingProvider = new DSN($providerConfig); - - $providerName = $loggingProvider->getScheme(); - $providerConfig = match ($providerName) { - 'sentry' => ['key' => $loggingProvider->getPassword(), 'projectId' => $loggingProvider->getUser() ?? '', 'host' => 'https://' . $loggingProvider->getHost()], - 'logowl' => ['ticket' => $loggingProvider->getUser() ?? '', 'host' => $loggingProvider->getHost()], - default => ['key' => $loggingProvider->getHost()], - }; - } catch (Throwable $th) { - // Fallback for older Appwrite versions up to 1.5.x that use _APP_LOGGING_PROVIDER and _APP_LOGGING_CONFIG environment variables - Console::warning('Using deprecated logging configuration. Please update your configuration to use DSN format.' . $th->getMessage()); - $configChunks = \explode(";", $providerConfig); - - $providerConfig = match ($providerName) { - 'sentry' => [ 'key' => $configChunks[0], 'projectId' => $configChunks[1] ?? '', 'host' => '',], - 'logowl' => ['ticket' => $configChunks[0], 'host' => ''], - default => ['key' => $providerConfig], - }; - } - - if (empty($providerName)) { - return; - } - - if (!Logger::hasProvider($providerName)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, "Logging provider not supported. Logging is disabled"); - } - - try { - $adapter = match ($providerName) { - 'sentry' => new Sentry($providerConfig['projectId'], $providerConfig['key'], $providerConfig['host']), - 'logowl' => new LogOwl($providerConfig['ticket'], $providerConfig['host']), - 'raygun' => new Raygun($providerConfig['key']), - 'appsignal' => new AppSignal($providerConfig['key']), - default => null - }; - } catch (Throwable $th) { - $adapter = null; - } - - if ($adapter === null) { - Console::error("Logging provider not supported. Logging is disabled"); - return; - } - - return new Logger($adapter); -}); - -$register->set('realtimeLogger', function () { - // Register error logger for realtime, falls back to default logging config - $providerConfig = System::getEnv('_APP_LOGGING_CONFIG_REALTIME', '') - ?: System::getEnv('_APP_LOGGING_CONFIG', ''); - - if (empty($providerConfig)) { - return; - } - - $loggingProvider = new DSN($providerConfig); - $providerName = $loggingProvider->getScheme(); - $providerConfig = match ($providerName) { - 'sentry' => ['key' => $loggingProvider->getPassword(), 'projectId' => $loggingProvider->getUser() ?? '', 'host' => 'https://' . $loggingProvider->getHost()], - 'logowl' => ['ticket' => $loggingProvider->getUser() ?? '', 'host' => $loggingProvider->getHost()], - default => ['key' => $loggingProvider->getHost()], - }; - - if (empty($providerName)) { - return; - } - - if (!Logger::hasProvider($providerName)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, "Logging provider not supported. Logging is disabled"); - } - - try { - $adapter = match ($providerName) { - 'sentry' => new Sentry($providerConfig['projectId'], $providerConfig['key'], $providerConfig['host']), - 'logowl' => new LogOwl($providerConfig['ticket'], $providerConfig['host']), - 'raygun' => new Raygun($providerConfig['key']), - 'appsignal' => new AppSignal($providerConfig['key']), - default => null - }; - } catch (Throwable $th) { - $adapter = null; - } - - if ($adapter === null) { - Console::error("Logging provider not supported. Logging is disabled"); - return; - } - - return new Logger($adapter); -}); - $register->set('pools', function () { $group = new Group(); diff --git a/app/init/resources.php b/app/init/resources.php index 29506bfc9c..66ca1a0ac4 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -45,10 +45,6 @@ global $register; global $container; $container = new Container(); -$container->set('logger', function ($register) { - return $register->get('logger'); -}, ['register']); - $container->set('hooks', function ($register) { return $register->get('hooks'); }, ['register']); diff --git a/app/init/resources/request.php b/app/init/resources/request.php index 1aa53b7403..520033333f 100644 --- a/app/init/resources/request.php +++ b/app/init/resources/request.php @@ -48,7 +48,6 @@ use Utopia\Domains\Domain; use Utopia\DSN\DSN; use Utopia\Http\Http; use Utopia\Locale\Locale; -use Utopia\Logger\Log; use Utopia\Pools\Group; use Utopia\Queue\Publisher; use Utopia\Storage\Device; @@ -67,12 +66,6 @@ return function (Container $container): void { return $utopia; }, ['utopia']); - $container->set('log', fn () => new Log(), []); - - $container->set('logger', function ($register) { - return $register->get('logger'); - }, ['register']); - $container->set('authorization', function () { return new Authorization(); }, []); diff --git a/app/init/span.php b/app/init/span.php index 8afa01b2df..23a2a2c6c2 100644 --- a/app/init/span.php +++ b/app/init/span.php @@ -1,10 +1,89 @@ getScheme(); + + if ($providerName !== 'sentry') { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Logging provider not supported. Logging is disabled'); + } + + $dsn = 'https://' . $loggingProvider->getPassword() . '@' . $loggingProvider->getHost() . '/' . ($loggingProvider->getUser() ?? ''); + + Span::addExporter( + new Exporter\Sentry( + dsn: $dsn, + environment: System::getEnv('_APP_ENV', 'development') === 'production' ? 'production' : 'staging', + release: System::getEnv('_APP_VERSION', 'UNKNOWN'), + serverName: System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname()), + classifier: fn (string $key): SentryField => match ($key) { + 'appwrite.error.action', + 'appwrite.error.publish', + 'code', + 'database', + 'dnsDomain', + 'embeddingModel', + 'error.code', + 'error.type', + 'hostname', + 'locale', + 'method', + 'projectId', + 'service', + 'type', + 'url', + 'userId', + 'verboseType' => SentryField::Tag, + default => SentryField::Context, + }, + ), + sampler: $sampler ?? fn (Span $span): bool => $span->getError() !== null + && $span->get('appwrite.error.publish') === true + && $span->get('appwrite.error.experimental') !== true, + ); + } catch (Throwable $th) { + Console::warning('Failed to initialize logging provider: ' . $th->getMessage()); + } +}; + +if (!empty($loggingConfig)) { + $addSentryExporter($loggingConfig); +} + +$experimentalLoggingConfig = System::getEnv('_APP_EXPERIMENT_LOGGING_CONFIG', ''); +if (!empty($experimentalLoggingConfig)) { + $sampleRate = 0.01; + try { + $sampleRate = (float) (new DSN($experimentalLoggingConfig))->getParam('sample', $sampleRate); + } catch (Throwable) { + } + + $addSentryExporter( + $experimentalLoggingConfig, + fn (Span $span): bool => $span->getError() !== null + && $span->get('appwrite.error.experimental') === true + && \mt_rand() / \mt_getrandmax() <= $sampleRate, + ); +} + Span::addExporter(new Exporter\Pretty(), function (Span $span): bool { if (\str_starts_with($span->getAction(), 'listener.')) { return $span->getError() !== null; diff --git a/app/init/worker/message.php b/app/init/worker/message.php index dfe6af9bd9..b18c78d866 100644 --- a/app/init/worker/message.php +++ b/app/init/worker/message.php @@ -22,10 +22,10 @@ use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; use Utopia\DI\Container; use Utopia\DSN\DSN; -use Utopia\Logger\Log; use Utopia\Pools\Group; use Utopia\Queue\Publisher; use Utopia\Registry\Registry; +use Utopia\Span\Span; use Utopia\Storage\Device\Telemetry as TelemetryDevice; use Utopia\System\System; use Utopia\Telemetry\Adapter as Telemetry; @@ -36,8 +36,6 @@ use Utopia\Telemetry\Adapter as Telemetry; * must be fresh for each worker job. */ return function (Container $container): void { - $container->set('log', fn () => new Log(), []); - $container->set('usage', fn () => new Context(), []); $container->set('authorization', function () { @@ -352,51 +350,45 @@ return function (Container $container): void { return new TelemetryDevice($telemetry, getDevice(APP_STORAGE_CACHE . '/app-' . $project->getId())); }, ['project', 'telemetry']); - $container->set('logError', function (Registry $register, Document $project) { - return function (Throwable $error, string $namespace, string $action, ?array $extras = null) use ($register, $project) { - $logger = $register->get('logger'); + $container->set('logError', function (Document $project) { + return function (Throwable $error, string $namespace, string $action, ?array $extras = null) use ($project) { + $span = Span::current(); + $shouldFinish = false; + if ($span === null) { + $span = Span::init($action); + $shouldFinish = true; + } - if ($logger) { - $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); + Span::add('level', 'error'); + Span::add('logger', $namespace); + Span::add('server.name', System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); + Span::add('release', System::getEnv('_APP_VERSION', 'UNKNOWN')); + Span::add('environment', System::getEnv('_APP_ENV', 'development') === 'production' ? 'production' : 'staging'); + Span::add('appwrite.error.publish', true); + Span::add('appwrite.error.action', $action); + Span::add('code', $error->getCode()); + Span::add('verboseType', \get_class($error)); + Span::add('projectId', $project->getId()); + Span::add('error.message', $error->getMessage()); + Span::add('error.file', $error->getFile()); + Span::add('error.line', $error->getLine()); + Span::add('error.trace', $error->getTraceAsString()); - $log = new Log(); - $log->setNamespace($namespace); - $log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \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->addTag('projectId', $project->getId()); - - $log->addExtra('file', $error->getFile()); - $log->addExtra('line', $error->getLine()); - $log->addExtra('trace', $error->getTraceAsString()); - - if ($error->getPrevious() !== null) { - if ($error->getPrevious()->getMessage() != $error->getMessage()) { - $log->addExtra('previousMessage', $error->getPrevious()->getMessage()); - } - $log->addExtra('previousFile', $error->getPrevious()->getFile()); - $log->addExtra('previousLine', $error->getPrevious()->getLine()); + if ($error->getPrevious() !== null) { + if ($error->getPrevious()->getMessage() != $error->getMessage()) { + Span::add('error.previous.message', $error->getPrevious()->getMessage()); } + Span::add('error.previous.file', $error->getPrevious()->getFile()); + Span::add('error.previous.line', $error->getPrevious()->getLine()); + } - foreach (($extras ?? []) as $key => $value) { - $log->addExtra($key, $value); - } + foreach (($extras ?? []) as $key => $value) { + Span::add($key, \is_scalar($value) || $value === null ? $value : (\json_encode($value) ?: null)); + } - $log->setAction($action); - - $isProduction = System::getEnv('_APP_ENV', 'development') === 'production'; - $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); - - try { - $responseCode = $logger->addLog($log); - Console::info('Error log pushed with status code: ' . $responseCode); - } catch (Throwable $th) { - Console::error('Error pushing log: ' . $th->getMessage()); - } + Span::error($error); + if ($shouldFinish) { + $span->finish(); } Console::warning("Failed: {$error->getMessage()}"); @@ -409,7 +401,7 @@ return function (Container $container): void { Console::warning("Previous File: {$error->getPrevious()->getFile()} Line: {$error->getPrevious()->getLine()}"); } }; - }, ['register', 'project']); + }, ['project']); $container->set('getAudit', function (Database $dbForPlatform, callable $getProjectDB) { return function (Document $project) use ($dbForPlatform, $getProjectDB) { diff --git a/app/realtime.php b/app/realtime.php index 352903d942..dd3ae2b0ac 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -35,7 +35,6 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\DI\Container; use Utopia\DSN\DSN; -use Utopia\Logger\Log; use Utopia\Pools\Group; use Utopia\Registry\Registry; use Utopia\Span\Span; @@ -282,45 +281,39 @@ $server = new Server($adapter); if (!function_exists('logError')) { function logError(Throwable $error, string $action, array $tags = [], ?Document $project = null, ?Document $user = null, ?Authorization $authorization = null): void { - global $register; - - $logger = $register->get('realtimeLogger'); - - if ($logger && !$error instanceof Exception) { - $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); - - $log = new Log(); - $log->setNamespace("realtime"); - $log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \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->addTag('projectId', $project?->getId() ?: 'n/a'); - $log->addTag('userId', $user?->getId() ?: 'n/a'); - - foreach ($tags as $key => $value) { - $log->addTag($key, $value ?: 'n/a'); + if (!$error instanceof Exception) { + $span = Span::current(); + $shouldFinish = false; + if ($span === null) { + $span = Span::init($action); + $shouldFinish = true; } - $log->addExtra('file', $error->getFile()); - $log->addExtra('line', $error->getLine()); - $log->addExtra('trace', $error->getTraceAsString()); - $log->addExtra('detailedTrace', $error->getTrace()); - $log->addExtra('roles', $authorization?->getRoles() ?? []); + Span::add('level', 'error'); + Span::add('logger', 'realtime'); + Span::add('server.name', System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); + Span::add('release', System::getEnv('_APP_VERSION', 'UNKNOWN')); + Span::add('environment', System::getEnv('_APP_ENV', 'development') === 'production' ? 'production' : 'staging'); + Span::add('appwrite.error.publish', true); + Span::add('appwrite.error.action', $action); + Span::add('code', $error->getCode()); + Span::add('verboseType', get_class($error)); + Span::add('projectId', $project?->getId() ?: 'n/a'); + Span::add('userId', $user?->getId() ?: 'n/a'); - $log->setAction($action); + foreach ($tags as $key => $value) { + Span::add($key, \is_scalar($value) ? ($value ?: 'n/a') : (\json_encode($value) ?: 'n/a')); + } - $isProduction = System::getEnv('_APP_ENV', 'development') === 'production'; - $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); - - try { - $responseCode = $logger->addLog($log); - Console::info('Error log pushed with status code: ' . $responseCode); - } catch (Throwable $th) { - Console::error('Error pushing log: ' . $th->getMessage()); + Span::add('error.message', $error->getMessage()); + Span::add('error.file', $error->getFile()); + Span::add('error.line', $error->getLine()); + Span::add('error.trace', $error->getTraceAsString()); + Span::add('error.detailedTrace', \json_encode($error->getTrace()) ?: null); + Span::add('roles', \json_encode($authorization?->getRoles() ?? []) ?: null); + Span::error($error); + if ($shouldFinish) { + $span->finish(); } } diff --git a/app/worker.php b/app/worker.php index 12b822c4eb..ccddc9895b 100644 --- a/app/worker.php +++ b/app/worker.php @@ -9,13 +9,12 @@ use Swoole\Runtime; use Utopia\Console; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; -use Utopia\Logger\Log; -use Utopia\Logger\Logger; use Utopia\Platform\Service; use Utopia\Pools\Group; use Utopia\Queue\Adapter\Swoole; use Utopia\Queue\Broker\Pool as BrokerPool; use Utopia\Queue\Server; +use Utopia\Span\Span; use Utopia\System\System; Runtime::enableCoroutine(); @@ -35,8 +34,6 @@ $container->set('authorization', function () { $container->set('project', fn () => new Document([]), []); -$container->set('log', fn () => new Log(), []); - $container->set('consumer', function (Group $pools) { return new BrokerPool(consumer: $pools->get('consumer')); }, ['pools']); @@ -113,37 +110,36 @@ try { $worker ->error() ->inject('error') - ->inject('logger') - ->inject('log') ->inject('project') ->inject('authorization') - ->action(function (Throwable $error, ?Logger $logger, Log $log, Document $project, Authorization $authorization) use ($queueName) { + ->action(function (Throwable $error, Document $project, Authorization $authorization) use ($queueName) { $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); + $action = 'appwrite-queue-' . $queueName; + $span = Span::current(); + $shouldFinish = false; + if ($span === null) { + $span = Span::init($action); + $shouldFinish = true; + } - if ($logger) { - $log->setNamespace('appwrite-worker'); - $log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); - $log->setVersion($version); - $log->setType(Log::TYPE_ERROR); - $log->setMessage($error->getMessage()); - $log->setAction('appwrite-queue-' . $queueName); - $log->addTag('verboseType', get_class($error)); - $log->addTag('code', $error->getCode()); - $log->addTag('projectId', $project->getId()); - $log->addExtra('file', $error->getFile()); - $log->addExtra('line', $error->getLine()); - $log->addExtra('trace', $error->getTraceAsString()); - $log->addExtra('roles', $authorization->getRoles()); - - $isProduction = System::getEnv('_APP_ENV', 'development') === 'production'; - $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); - - try { - $responseCode = $logger->addLog($log); - Console::info('Error log pushed with status code: ' . $responseCode); - } catch (Throwable $th) { - Console::error('Error pushing log: ' . $th->getMessage()); - } + Span::add('level', 'error'); + Span::add('logger', 'appwrite-worker'); + Span::add('server.name', System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); + Span::add('release', $version); + Span::add('environment', System::getEnv('_APP_ENV', 'development') === 'production' ? 'production' : 'staging'); + Span::add('appwrite.error.publish', true); + Span::add('appwrite.error.action', $action); + Span::add('verboseType', get_class($error)); + Span::add('code', $error->getCode()); + Span::add('projectId', $project->getId()); + Span::add('error.message', $error->getMessage()); + Span::add('error.file', $error->getFile()); + Span::add('error.line', $error->getLine()); + Span::add('error.trace', $error->getTraceAsString()); + Span::add('roles', \json_encode($authorization->getRoles()) ?: null); + Span::error($error); + if ($shouldFinish) { + $span->finish(); } Console::error('[Error] Type: ' . get_class($error)); diff --git a/composer.json b/composer.json index 683da6f21b..1f660a87d4 100644 --- a/composer.json +++ b/composer.json @@ -72,7 +72,6 @@ "utopia-php/validators": "0.2.*", "utopia-php/image": "0.8.*", "utopia-php/locale": "0.8.*", - "utopia-php/logger": "0.6.*", "utopia-php/messaging": "0.22.*", "utopia-php/migration": "1.9.*", "utopia-php/platform": "0.13.*", diff --git a/composer.lock b/composer.lock index 50b6355c46..b73808be3a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4bee36b21a57e754d2b3417e72dc9599", + "content-hash": "788e59ef0f1f12947b5c3700f905c635", "packages": [ { "name": "adhocore/jwt", @@ -4423,60 +4423,6 @@ }, "time": "2025-08-12T12:58:26+00:00" }, - { - "name": "utopia-php/logger", - "version": "0.6.2", - "source": { - "type": "git", - "url": "https://github.com/utopia-php/logger.git", - "reference": "25b5bd2ad8bb51292f76332faa7034644fd0941d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/utopia-php/logger/zipball/25b5bd2ad8bb51292f76332faa7034644fd0941d", - "reference": "25b5bd2ad8bb51292f76332faa7034644fd0941d", - "shasum": "" - }, - "require": { - "php": ">=8.0" - }, - "require-dev": { - "laravel/pint": "1.2.*", - "phpstan/phpstan": "1.9.x-dev", - "phpunit/phpunit": "^9.3", - "vimeo/psalm": "4.0.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "Utopia\\Logger\\": "src/Logger" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Utopia Logger library is simple and lite library for logging information, such as errors or warnings. This library is aiming to be as simple and easy to learn and use.", - "keywords": [ - "appsignal", - "errors", - "framework", - "logger", - "logging", - "logs", - "php", - "raygun", - "sentry", - "upf", - "utopia", - "warnings" - ], - "support": { - "issues": "https://github.com/utopia-php/logger/issues", - "source": "https://github.com/utopia-php/logger/tree/0.6.2" - }, - "time": "2024-10-14T16:02:49+00:00" - }, { "name": "utopia-php/messaging", "version": "0.22.0", diff --git a/src/Appwrite/Certificates/Adapter.php b/src/Appwrite/Certificates/Adapter.php index 47d865ad08..6e747629d2 100644 --- a/src/Appwrite/Certificates/Adapter.php +++ b/src/Appwrite/Certificates/Adapter.php @@ -2,8 +2,6 @@ namespace Appwrite\Certificates; -use Utopia\Logger\Log; - interface Adapter { public function issueCertificate(string $certName, string $domain, ?string $domainType): ?string; @@ -12,7 +10,7 @@ interface Adapter public function getCertificateStatus(string $domain, ?string $domainType): string; - public function isRenewRequired(string $domain, ?string $domainType, Log $log): bool; + public function isRenewRequired(string $domain, ?string $domainType): bool; public function deleteCertificate(string $domain): void; } diff --git a/src/Appwrite/Certificates/LetsEncrypt.php b/src/Appwrite/Certificates/LetsEncrypt.php index 001d04941e..5a186ea0bc 100644 --- a/src/Appwrite/Certificates/LetsEncrypt.php +++ b/src/Appwrite/Certificates/LetsEncrypt.php @@ -7,7 +7,7 @@ use Exception; use Utopia\Console; use Utopia\Database\DateTime; use Utopia\Http\Http; -use Utopia\Logger\Log; +use Utopia\Span\Span; class LetsEncrypt implements Adapter { @@ -95,7 +95,7 @@ class LetsEncrypt implements Adapter throw new CertificateStatusException('Certificate status retrieval is not supported for LetsEncrypt.'); } - public function isRenewRequired(string $domain, ?string $domainType, Log $log): bool + public function isRenewRequired(string $domain, ?string $domainType): bool { $certPath = APP_STORAGE_CERTIFICATES . '/' . $domain . '/cert.pem'; if (\file_exists($certPath)) { @@ -103,15 +103,15 @@ class LetsEncrypt implements Adapter $validTo = $certData['validTo_time_t'] ?? 0; if (empty($validTo)) { - $log->addTag('certificateDomain', $domain); + Span::add('certificateDomain', $domain); throw new Exception('Unable to read certificate file (cert.pem).'); } // LetsEncrypt allows renewal 30 days before expiry $expiryInAdvance = (60 * 60 * 24 * 30); if ($validTo - $expiryInAdvance > \time()) { - $log->addTag('certificateDomain', $domain); - $log->addExtra('certificateData', \is_array($certData) ? \json_encode($certData) : \strval($certData)); + Span::add('certificateDomain', $domain); + Span::add('certificateData', \is_array($certData) ? \json_encode($certData) : \strval($certData)); return false; } } diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Action.php b/src/Appwrite/Platform/Modules/Avatars/Http/Action.php index d6b58b33dd..0b3766ff15 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Action.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Action.php @@ -12,7 +12,6 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; use Utopia\Image\Image; -use Utopia\Logger\Logger; class Action extends PlatformAction { @@ -57,7 +56,7 @@ class Action extends PlatformAction unset($image); } - protected function getUserGitHub(string $userId, Document $project, Database $dbForProject, Database $dbForPlatform, ?Logger $logger, Authorization $authorization): array + protected function getUserGitHub(string $userId, Document $project, Database $dbForProject, Database $dbForPlatform, Authorization $authorization): array { try { $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php index a6a013ef21..bef94b57f3 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Back/Get.php @@ -12,7 +12,6 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; -use Utopia\Logger\Logger; use Utopia\Platform\Action as UtopiaAction; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\Range; @@ -52,12 +51,11 @@ class Get extends Action ->inject('heroes') ->inject('contributors') ->inject('employees') - ->inject('logger') ->inject('authorization') ->callback($this->action(...)); } - public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization) + public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, Authorization $authorization) { $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); @@ -69,7 +67,7 @@ class Get extends Action $userId = $user->getId(); $email = $user->getAttribute('email', ''); - $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization); + $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $authorization); $githubId = $gitHub['id'] ?? ''; $isHero = \array_key_exists($email, $heroes); diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php index d0c600192b..be4bc97c2e 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/Front/Get.php @@ -12,7 +12,6 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; -use Utopia\Logger\Logger; use Utopia\Platform\Action as UtopiaAction; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\Range; @@ -52,12 +51,11 @@ class Get extends Action ->inject('heroes') ->inject('contributors') ->inject('employees') - ->inject('logger') ->inject('authorization') ->callback($this->action(...)); } - public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization) + public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, Authorization $authorization) { $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); @@ -70,7 +68,7 @@ class Get extends Action $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); - $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization); + $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $authorization); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; diff --git a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php index ad74d6c192..850a8a2df4 100644 --- a/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php +++ b/src/Appwrite/Platform/Modules/Avatars/Http/Cards/Cloud/OG/Get.php @@ -12,7 +12,6 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; -use Utopia\Logger\Logger; use Utopia\Platform\Action as UtopiaAction; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\Range; @@ -52,12 +51,11 @@ class Get extends Action ->inject('heroes') ->inject('contributors') ->inject('employees') - ->inject('logger') ->inject('authorization') ->callback($this->action(...)); } - public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization) + public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, Authorization $authorization) { $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); @@ -74,7 +72,7 @@ class Get extends Action $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); - $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization); + $gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $authorization); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Embeddings/Text/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Embeddings/Text/Create.php index 8a7137e38b..457861b1e4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Embeddings/Text/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Embeddings/Text/Create.php @@ -14,9 +14,7 @@ use Utopia\Agents\Adapters\Ollama; use Utopia\Agents\Agent; use Utopia\Database\Document; use Utopia\Http\Adapter\Swoole\Response as SwooleResponse; -use Utopia\Logger\Log; -use Utopia\Logger\Logger; -use Utopia\System\System; +use Utopia\Span\Span; use Utopia\Validator\ArrayList; use Utopia\Validator\Text; use Utopia\Validator\WhiteList; @@ -79,12 +77,10 @@ class Create extends CreateDocumentAction ->inject('project') ->inject('embeddingAgent') ->inject('usage') - ->inject('log') - ->inject('logger') ->callback($this->action(...)); } - public function action(array $texts, string $model, UtopiaResponse $response, Document $project, Agent $embeddingAgent, Context $usage, Log $log, ?Logger $logger): void + public function action(array $texts, string $model, UtopiaResponse $response, Document $project, Agent $embeddingAgent, Context $usage): void { $results = []; $embeddingAgent->getAdapter()->setModel($model); @@ -104,23 +100,18 @@ class Create extends CreateDocumentAction } catch (\Exception $e) { $error = 'Error while generating embedding'; $totalErrors += 1; - if ($logger) { - $log->setNamespace("http"); - $log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); - $log->setVersion(System::getEnv('_APP_VERSION', 'UNKNOWN')); - $log->setType(Log::TYPE_ERROR); - $log->setMessage($e->getMessage()); - - $log->addTag('embeddingModel', $model); - $log->addTag('code', $e->getCode()); - $log->addTag('projectId', $project->getId()); - - $log->addExtra('file', $e->getFile()); - $log->addExtra('line', $e->getLine()); - $log->addExtra('trace', $e->getTraceAsString()); - - $logger->addLog($log); - } + Span::add('level', 'error'); + Span::add('logger', 'http'); + Span::add('appwrite.error.publish', true); + Span::add('appwrite.error.action', 'vectorsDB.createTextEmbeddings'); + Span::add('embeddingModel', $model); + Span::add('code', $e->getCode()); + Span::add('projectId', $project->getId()); + Span::add('error.message', $e->getMessage()); + Span::add('error.file', $e->getFile()); + Span::add('error.line', $e->getLine()); + Span::add('error.trace', $e->getTraceAsString()); + Span::error($e); } $results[] = new Document([ diff --git a/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php b/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php index 39902aea53..63cd630424 100644 --- a/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php +++ b/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php @@ -14,9 +14,9 @@ use Utopia\Database\Exception\NotFound; use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; use Utopia\Database\Query; -use Utopia\Logger\Log; use Utopia\Platform\Action; use Utopia\Queue\Message; +use Utopia\Span\Span; class Databases extends Action { @@ -38,7 +38,6 @@ class Databases extends Action ->inject('dbForProject') ->inject('getDatabasesDB') ->inject('queueForRealtime') - ->inject('log') ->callback($this->action(...)); } @@ -48,11 +47,10 @@ class Databases extends Action * @param Database $dbForPlatform * @param Database $dbForProject * @param Realtime $queueForRealtime - * @param Log $log * @return void * @throws \Exception */ - public function action(Message $message, Document $project, Database $dbForPlatform, Database $dbForProject, callable $getDatabasesDB, Realtime $queueForRealtime, Log $log): void + public function action(Message $message, Document $project, Database $dbForPlatform, Database $dbForProject, callable $getDatabasesDB, Realtime $queueForRealtime): void { $payload = $message->getPayload(); @@ -68,14 +66,14 @@ class Databases extends Action * @var Database $dbForDatabases */ $dbForDatabases = $getDatabasesDB($database); - $log->addTag('projectId', $project->getId()); - $log->addTag('type', $type); + Span::add('projectId', $project->getId()); + Span::add('type', $type); if ($database->isEmpty()) { throw new Exception('Missing database'); } - $log->addTag('databaseId', $database->getId()); + Span::add('databaseId', $database->getId()); match (\strval($type)) { DATABASE_TYPE_DELETE_DATABASE => $this->deleteDatabase($database, $dbForProject, $dbForDatabases), diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 352fb56e28..5fd8bcca47 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -31,9 +31,9 @@ use Utopia\Database\Query; use Utopia\Detector\Detection\Rendering\SSR; use Utopia\Detector\Detection\Rendering\XStatic; use Utopia\Detector\Detector\Rendering; -use Utopia\Logger\Log; use Utopia\Platform\Action; use Utopia\Queue\Message; +use Utopia\Span\Span; use Utopia\Storage\Device; use Utopia\Storage\Device\Local; use Utopia\System\System; @@ -70,7 +70,6 @@ class Builds extends Action ->inject('deviceForSites') ->inject('isResourceBlocked') ->inject('deviceForFiles') - ->inject('log') ->inject('executor') ->inject('plan') ->callback($this->action(...)); @@ -96,7 +95,6 @@ class Builds extends Action Device $deviceForSites, callable $isResourceBlocked, Device $deviceForFiles, - Log $log, Executor $executor, array $plan ): void { @@ -114,8 +112,8 @@ class Builds extends Action $template = new Document($payload['template'] ?? []); $platform = $payload['platform'] ?? Config::getParam('platform', []); - $log->addTag('projectId', $project->getId()); - $log->addTag('type', $type); + Span::add('projectId', $project->getId()); + Span::add('type', $type); switch ($type) { case BUILD_TYPE_DEPLOYMENT: @@ -141,7 +139,6 @@ class Builds extends Action $deployment, $template, $isResourceBlocked, - $log, $executor, $plan, $platform, @@ -177,7 +174,6 @@ class Builds extends Action Document $deployment, Document $template, callable $isResourceBlocked, - Log $log, Executor $executor, array $plan, array $platform, @@ -199,7 +195,7 @@ class Builds extends Action 'functions' => $deviceForFunctions, }; - $log->addTag($resourceKey, $resource->getId()); + Span::add($resourceKey, $resource->getId()); $resource = $dbForProject->getDocument($resource->getCollection(), $resource->getId()); if ($resource->isEmpty()) { @@ -210,7 +206,7 @@ class Builds extends Action throw new \Exception('Resource is blocked'); } - $log->addTag('deploymentId', $deployment->getId()); + Span::add('deploymentId', $deployment->getId()); $deployment = $dbForProject->getDocument('deployments', $deployment->getId()); if ($deployment->isEmpty()) { diff --git a/src/Appwrite/Platform/Modules/Proxy/Action.php b/src/Appwrite/Platform/Modules/Proxy/Action.php index 8baf54c790..c87ef73c18 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Action.php +++ b/src/Appwrite/Platform/Modules/Proxy/Action.php @@ -8,7 +8,7 @@ use Appwrite\Platform\Action as PlatformAction; use Utopia\Database\Document; use Utopia\DNS\Message\Record; use Utopia\Domains\Domain; -use Utopia\Logger\Log; +use Utopia\Span\Span; use Utopia\System\System; use Utopia\Validator\AnyOf; use Utopia\Validator\Domain as ValidatorDomain; @@ -91,10 +91,9 @@ class Action extends PlatformAction * Verify or re-verify a rule * * @param Document $rule Rule to verify - * @param Log|null $log Log instance to add timings to * @return void */ - protected function verifyRule(Document $rule, ?Log $log = null): void + protected function verifyRule(Document $rule): void { $dnsValidatorClass = $this->dnsValidatorClass; $dnsEnv = System::getEnv('_APP_DNS', '8.8.8.8'); @@ -117,10 +116,8 @@ class Action extends PlatformAction $validationStart = \microtime(true); $validator = new $dnsValidatorClass($caaTarget, Record::TYPE_CAA, $dnsServers); if (!$validator->isValid($domain->get())) { - if (!\is_null($log)) { - $log->addExtra('dnsTimingCaa', \strval(\microtime(true) - $validationStart)); - $log->addTag('dnsDomain', $domain->get()); - } + Span::add('dnsTimingCaa', \strval(\microtime(true) - $validationStart)); + Span::add('dnsDomain', $domain->get()); throw new Exception(Exception::RULE_VERIFICATION_FAILED, $validator->getDescription()); } } @@ -200,10 +197,8 @@ class Action extends PlatformAction $validationStart = \microtime(true); if (!$validator->isValid($domain->get())) { - if (!\is_null($log)) { - $log->addExtra('dnsTiming', \strval(\microtime(true) - $validationStart)); - $log->addTag('dnsDomain', $domain->get()); - } + Span::add('dnsTiming', \strval(\microtime(true) - $validationStart)); + Span::add('dnsDomain', $domain->get()); throw new Exception(Exception::RULE_VERIFICATION_FAILED, $mainValidator->getDescription()); } } diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php index a6a3e44194..5a218bbaae 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php @@ -14,7 +14,6 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; -use Utopia\Logger\Log; use Utopia\Platform\Scope\HTTP; use Utopia\System\System; use Utopia\Validator\Domain as ValidatorDomain; @@ -66,11 +65,10 @@ class Create extends Action ->inject('queueForEvents') ->inject('dbForPlatform') ->inject('platform') - ->inject('log') ->callback($this->action(...)); } - public function action(string $domain, Response $response, Document $project, Certificate $publisherForCertificates, Event $queueForEvents, Database $dbForPlatform, array $platform, Log $log) + public function action(string $domain, Response $response, Document $project, Certificate $publisherForCertificates, Event $queueForEvents, Database $dbForPlatform, array $platform) { $this->validateDomainRestrictions($domain, $platform); @@ -100,7 +98,7 @@ class Create extends Action if ($rule->getAttribute('status', '') === RULE_STATUS_CREATED) { try { - $this->verifyRule($rule, $log); + $this->verifyRule($rule); $rule->setAttribute('status', RULE_STATUS_CERTIFICATE_GENERATING); } catch (Exception $err) { $rule->setAttribute('logs', $err->getMessage()); diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php index 4a8bd4897e..86dc238766 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php @@ -15,7 +15,6 @@ use Utopia\Database\Document; use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\UID; -use Utopia\Logger\Log; use Utopia\Platform\Scope\HTTP; use Utopia\System\System; use Utopia\Validator\Domain as ValidatorDomain; @@ -71,11 +70,10 @@ class Create extends Action ->inject('dbForPlatform') ->inject('dbForProject') ->inject('platform') - ->inject('log') ->callback($this->action(...)); } - public function action(string $domain, string $functionId, string $branch, Response $response, Document $project, Certificate $publisherForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject, array $platform, Log $log) + public function action(string $domain, string $functionId, string $branch, Response $response, Document $project, Certificate $publisherForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject, array $platform) { $this->validateDomainRestrictions($domain, $platform); @@ -118,7 +116,7 @@ class Create extends Action if ($rule->getAttribute('status', '') === RULE_STATUS_CREATED) { try { - $this->verifyRule($rule, $log); + $this->verifyRule($rule); $rule->setAttribute('status', RULE_STATUS_CERTIFICATE_GENERATING); } catch (Exception $err) { $rule->setAttribute('logs', $err->getMessage()); diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php index 5964a20772..7205a9d855 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php @@ -15,7 +15,6 @@ use Utopia\Database\Document; use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\UID; -use Utopia\Logger\Log; use Utopia\Platform\Scope\HTTP; use Utopia\System\System; use Utopia\Validator\Domain as ValidatorDomain; @@ -74,11 +73,10 @@ class Create extends Action ->inject('dbForPlatform') ->inject('dbForProject') ->inject('platform') - ->inject('log') ->callback($this->action(...)); } - public function action(string $domain, string $url, int $statusCode, string $resourceId, string $resourceType, Response $response, Document $project, Certificate $publisherForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject, array $platform, Log $log) + public function action(string $domain, string $url, int $statusCode, string $resourceId, string $resourceType, Response $response, Document $project, Certificate $publisherForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject, array $platform) { $this->validateDomainRestrictions($domain, $platform); @@ -123,7 +121,7 @@ class Create extends Action if ($rule->getAttribute('status', '') === RULE_STATUS_CREATED) { try { - $this->verifyRule($rule, $log); + $this->verifyRule($rule); $rule->setAttribute('status', RULE_STATUS_CERTIFICATE_GENERATING); } catch (Exception $err) { $rule->setAttribute('logs', $err->getMessage()); diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php index a9dfa93a49..8fcec1203d 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php @@ -15,7 +15,6 @@ use Utopia\Database\Document; use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\UID; -use Utopia\Logger\Log; use Utopia\Platform\Scope\HTTP; use Utopia\System\System; use Utopia\Validator\Domain as ValidatorDomain; @@ -71,11 +70,10 @@ class Create extends Action ->inject('dbForPlatform') ->inject('dbForProject') ->inject('platform') - ->inject('log') ->callback($this->action(...)); } - public function action(string $domain, string $siteId, ?string $branch, Response $response, Document $project, Certificate $publisherForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject, array $platform, Log $log) + public function action(string $domain, string $siteId, ?string $branch, Response $response, Document $project, Certificate $publisherForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject, array $platform) { $this->validateDomainRestrictions($domain, $platform); @@ -118,7 +116,7 @@ class Create extends Action if ($rule->getAttribute('status', '') === RULE_STATUS_CREATED) { try { - $this->verifyRule($rule, $log); + $this->verifyRule($rule); $rule->setAttribute('status', RULE_STATUS_CERTIFICATE_GENERATING); } catch (Exception $err) { $rule->setAttribute('logs', $err->getMessage()); diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Verification/Update.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Verification/Update.php index 9e81f6ff18..85fd332bbd 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Verification/Update.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Verification/Update.php @@ -14,7 +14,6 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Validator\UID; -use Utopia\Logger\Log; use Utopia\Platform\Scope\HTTP; class Update extends Action @@ -60,7 +59,6 @@ class Update extends Action ->inject('queueForEvents') ->inject('project') ->inject('dbForPlatform') - ->inject('log') ->callback($this->action(...)); } @@ -70,8 +68,7 @@ class Update extends Action Certificate $publisherForCertificates, Event $queueForEvents, Document $project, - Database $dbForPlatform, - Log $log + Database $dbForPlatform ) { $rule = $dbForPlatform->getDocument('rules', $ruleId); @@ -88,7 +85,7 @@ class Update extends Action } try { - $this->verifyRule($rule, $log); + $this->verifyRule($rule); // Reset logs and status for the rule $rule = $dbForPlatform->updateDocument('rules', $rule->getId(), new Document([ 'logs' => '', diff --git a/src/Appwrite/Platform/Tasks/Doctor.php b/src/Appwrite/Platform/Tasks/Doctor.php index 3eeaa95e64..46324faa19 100644 --- a/src/Appwrite/Platform/Tasks/Doctor.php +++ b/src/Appwrite/Platform/Tasks/Doctor.php @@ -11,7 +11,6 @@ use Utopia\Database\Adapter\Pool as DatabasePool; use Utopia\Domains\Domain; use Utopia\DSN\DSN; use Utopia\Http\Http; -use Utopia\Logger\Logger; use Utopia\Messaging\Adapter\Email as EmailAdapter; use Utopia\Messaging\Messages\Email as EmailMessage; use Utopia\Platform\Action; @@ -129,7 +128,7 @@ class Doctor extends Action $providerName = $loggingProvider->getScheme(); - if (empty($providerName) || !Logger::hasProvider($providerName)) { + if ($providerName !== 'sentry') { Console::log('🔴 Logging adapter is disabled'); } else { Console::log('🟢 Logging adapter is enabled (' . $providerName . ')'); diff --git a/src/Appwrite/Platform/Workers/Certificates.php b/src/Appwrite/Platform/Workers/Certificates.php index 4d04a3c92c..a197648d9b 100644 --- a/src/Appwrite/Platform/Workers/Certificates.php +++ b/src/Appwrite/Platform/Workers/Certificates.php @@ -28,8 +28,8 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Authorization as ValidatorAuthorization; use Utopia\Domains\Domain; use Utopia\Locale\Locale; -use Utopia\Logger\Log; use Utopia\Queue\Message; +use Utopia\Span\Span; use Utopia\System\System; class Certificates extends Action @@ -56,7 +56,6 @@ class Certificates extends Action ->inject('queueForFunctions') ->inject('queueForRealtime') ->inject('publisherForCertificates') - ->inject('log') ->inject('certificates') ->inject('plan') ->inject('authorization') @@ -72,7 +71,6 @@ class Certificates extends Action * @param Func $queueForFunctions * @param Realtime $queueForRealtime * @param Certificate $publisherForCertificates - * @param Log $log * @param CertificatesAdapter $certificates * @param array $plan * @param ValidatorAuthorization $authorization @@ -89,7 +87,6 @@ class Certificates extends Action Func $queueForFunctions, Realtime $queueForRealtime, Certificate $publisherForCertificates, - Log $log, CertificatesAdapter $certificates, array $plan, ValidatorAuthorization $authorization, @@ -108,15 +105,15 @@ class Certificates extends Action $validationDomain = $certificateMessage->validationDomain; $action = $certificateMessage->action; - $log->addTag('domain', $domain->get()); + Span::add('domain', $domain->get()); switch ($action) { case \Appwrite\Event\Certificate::ACTION_DOMAIN_VERIFICATION: - $this->handleDomainVerificationAction($domain, $dbForPlatform, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $publisherForCertificates, $log, $authorization, $validationDomain); + $this->handleDomainVerificationAction($domain, $dbForPlatform, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $publisherForCertificates, $authorization, $validationDomain); break; case \Appwrite\Event\Certificate::ACTION_GENERATION: - $this->handleCertificateGenerationAction($domain, $domainType, $dbForPlatform, $queueForMails, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $log, $certificates, $authorization, $skipRenewCheck, $plan, $validationDomain); + $this->handleCertificateGenerationAction($domain, $domainType, $dbForPlatform, $queueForMails, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $certificates, $authorization, $skipRenewCheck, $plan, $validationDomain); break; default: @@ -132,7 +129,6 @@ class Certificates extends Action * @param Func $queueForFunctions * @param Realtime $queueForRealtime * @param Certificate $publisherForCertificates - * @param Log $log * @param ValidatorAuthorization $authorization * @param string|null $validationDomain * @return void @@ -148,7 +144,6 @@ class Certificates extends Action Func $queueForFunctions, Realtime $queueForRealtime, Certificate $publisherForCertificates, - Log $log, ValidatorAuthorization $authorization, ?string $validationDomain = null ): void { @@ -170,7 +165,7 @@ class Certificates extends Action try { // Verify DNS records - $this->validateDomain($rule, $domain, $log, $validationDomain); + $this->validateDomain($rule, $domain, $validationDomain); // Reset logs and status for the rule $rule->setAttribute('logs', ''); $rule->setAttribute('status', RULE_STATUS_CERTIFICATE_GENERATING); @@ -214,7 +209,6 @@ class Certificates extends Action * @param Webhook $queueForWebhooks * @param Func $queueForFunctions * @param Realtime $queueForRealtime - * @param Log $log * @param CertificatesAdapter $certificates * @param ValidatorAuthorization $authorization * @param bool $skipRenewCheck @@ -238,7 +232,6 @@ class Certificates extends Action Webhook $queueForWebhooks, Func $queueForFunctions, Realtime $queueForRealtime, - Log $log, CertificatesAdapter $certificates, ValidatorAuthorization $authorization, bool $skipRenewCheck = false, @@ -311,10 +304,10 @@ class Certificates extends Action // Validate domain and DNS records. Skip if job is forced if (!$skipRenewCheck) { - $this->validateDomain($rule, $domain, $log, $validationDomain); + $this->validateDomain($rule, $domain, $validationDomain); // If certificate exists already, double-check expiry date. Skip if job is forced - if (!$certificates->isRenewRequired($domain->get(), $domainType, $log)) { + if (!$certificates->isRenewRequired($domain->get(), $domainType)) { Console::info("Skipping, renew isn't required"); return; } @@ -476,13 +469,12 @@ class Certificates extends Action * * @param Document $rule Rule to validate * @param Domain $domain Domain to validate - * @param Log $log Logger for adding metrics * @param string|null $validationDomain Override for main domain check * * @return void * @throws Exception */ - private function validateDomain(Document $rule, Domain $domain, Log $log, ?string $validationDomain = null): void + private function validateDomain(Document $rule, Domain $domain, ?string $validationDomain = null): void { $mainDomain = $validationDomain ?? $this->getMainDomain(); $isMainDomain = !isset($mainDomain) || $domain->get() === $mainDomain; @@ -494,7 +486,7 @@ class Certificates extends Action } try { - $this->verifyRule($rule, $log); + $this->verifyRule($rule); } catch (AppwriteException $err) { $msg = $err->getMessage() . "\n"; $msg .= "Verify your DNS records are correctly configured and try again.\n"; diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index a5fe352b07..ccf9178eb4 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -25,9 +25,9 @@ use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; use Utopia\Database\Query; use Utopia\DSN\DSN; -use Utopia\Logger\Log; use Utopia\Platform\Action; use Utopia\Queue\Message; +use Utopia\Span\Span; use Utopia\Storage\Device; use Utopia\System\System; @@ -65,7 +65,6 @@ class Deletes extends Action ->inject('executionRetention') ->inject('executionsRetentionCount') ->inject('auditRetention') - ->inject('log') ->inject('queueForDeletes') ->inject('getAudit') ->callback($this->action(...)); @@ -92,7 +91,6 @@ class Deletes extends Action string $executionRetention, int $executionsRetentionCount, string $auditRetention, - Log $log, DeleteEvent $queueForDeletes, callable $getAudit, ): void { @@ -109,8 +107,8 @@ class Deletes extends Action $resourceType = $payload['resourceType'] ?? null; $document = new Document($payload['document'] ?? []); - $log->addTag('projectId', $project->getId()); - $log->addTag('type', $type); + Span::add('projectId', $project->getId()); + Span::add('type', $type); switch (\strval($type)) { case DELETE_TYPE_DOCUMENT: diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index 8167fb975d..936e168f29 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -20,7 +20,6 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Query; -use Utopia\Logger\Log; use Utopia\Platform\Action; use Utopia\Queue\Message; use Utopia\Span\Span; @@ -49,7 +48,6 @@ class Functions extends Action ->inject('queueForRealtime') ->inject('queueForEvents') ->inject('bus') - ->inject('log') ->inject('executor') ->inject('isResourceBlocked') ->callback($this->action(...)); @@ -64,7 +62,6 @@ class Functions extends Action Realtime $queueForRealtime, Event $queueForEvents, Bus $bus, - Log $log, Executor $executor, callable $isResourceBlocked ): void { @@ -112,9 +109,9 @@ class Functions extends Action $function = $dbForProject->getDocument('functions', $functionId); } - $log->addTag('functionId', $function->getId()); - $log->addTag('projectId', $project->getId()); - $log->addTag('type', $type); + Span::add('functionId', $function->getId()); + Span::add('projectId', $project->getId()); + Span::add('type', $type); if (empty($events) && !$function->isEmpty()) { $traceProjectId = System::getEnv('_APP_TRACE_PROJECT_ID', ''); @@ -168,7 +165,6 @@ class Functions extends Action Console::success('Iterating function: ' . $function->getAttribute('name')); $this->execute( - log: $log, dbForProject: $dbForProject, queueForWebhooks: $queueForWebhooks, queueForFunctions: $queueForFunctions, @@ -212,7 +208,6 @@ class Functions extends Action $execution = new Document($payload['execution'] ?? []); $user = new Document($payload['user'] ?? []); $this->execute( - log: $log, dbForProject: $dbForProject, queueForWebhooks: $queueForWebhooks, queueForFunctions: $queueForFunctions, @@ -238,7 +233,6 @@ class Functions extends Action case 'schedule': $execution = new Document($payload['execution'] ?? []); $this->execute( - log: $log, dbForProject: $dbForProject, queueForWebhooks: $queueForWebhooks, queueForFunctions: $queueForFunctions, @@ -342,7 +336,6 @@ class Functions extends Action } /** - * @param Log $log * @param Database $dbForProject * @param Func $queueForFunctions * @param Realtime $queueForRealtime @@ -363,7 +356,6 @@ class Functions extends Action * @return void */ private function execute( - Log $log, Database $dbForProject, Webhook $queueForWebhooks, Func $queueForFunctions, @@ -390,7 +382,7 @@ class Functions extends Action $deploymentId = $function->getAttribute('deploymentId', ''); $spec = Config::getParam('specifications')[$function->getAttribute('runtimeSpecification', APP_COMPUTE_SPECIFICATION_DEFAULT)]; - $log->addTag('deploymentId', $deploymentId); + Span::add('deploymentId', $deploymentId); /** Check if deployment exists */ $deployment = $dbForProject->getDocument('deployments', $deploymentId); diff --git a/src/Appwrite/Platform/Workers/Mails.php b/src/Appwrite/Platform/Workers/Mails.php index 5cd4639988..d07ebaa8b2 100644 --- a/src/Appwrite/Platform/Workers/Mails.php +++ b/src/Appwrite/Platform/Workers/Mails.php @@ -6,7 +6,6 @@ use Appwrite\Template\Template; use Exception; use Swoole\Runtime; use Utopia\Database\Document; -use Utopia\Logger\Log; use Utopia\Messaging\Adapter\Email as EmailAdapter; use Utopia\Messaging\Adapter\Email\SMTP; use Utopia\Messaging\Messages\Email as EmailMessage; @@ -14,6 +13,7 @@ use Utopia\Messaging\Messages\Email\Attachment; use Utopia\Platform\Action; use Utopia\Queue\Message; use Utopia\Registry\Registry; +use Utopia\Span\Span; use Utopia\System\System; class Mails extends Action @@ -38,7 +38,6 @@ class Mails extends Action ->inject('message') ->inject('project') ->inject('register') - ->inject('log') ->callback($this->action(...)); } @@ -54,11 +53,10 @@ class Mails extends Action * @param Message $message * @param Document $project * @param Registry $register - * @param Log $log * @return void * @throws Exception */ - public function action(Message $message, Document $project, Registry $register, Log $log): void + public function action(Message $message, Document $project, Registry $register): void { Runtime::setHookFlags(SWOOLE_HOOK_ALL ^ SWOOLE_HOOK_TCP); $payload = $message->getPayload(); @@ -74,7 +72,7 @@ class Mails extends Action } $type = empty($smtp) ? 'cloud' : 'smtp'; - $log->addTag('type', $type); + Span::add('type', $type); $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; $hostname = System::getEnv('_APP_CONSOLE_DOMAIN'); diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index 03adebc4b5..719e79a982 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -16,7 +16,6 @@ use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\DSN\DSN; -use Utopia\Logger\Log; use Utopia\Messaging\Adapter\Email as EmailAdapter; use Utopia\Messaging\Adapter\Email\Mailgun; use Utopia\Messaging\Adapter\Email\Resend; @@ -70,7 +69,6 @@ class Messaging extends Action ->desc('Messaging worker') ->inject('message') ->inject('project') - ->inject('log') ->inject('dbForProject') ->inject('deviceForFiles') ->inject('publisherForUsage') @@ -80,7 +78,6 @@ class Messaging extends Action /** * @param Message $message * @param Document $project - * @param Log $log * @param Database $dbForProject * @param Device $deviceForFiles * @param UsagePublisher $publisherForUsage @@ -90,7 +87,6 @@ class Messaging extends Action public function action( Message $message, Document $project, - Log $log, Database $dbForProject, Device $deviceForFiles, UsagePublisher $publisherForUsage @@ -112,7 +108,7 @@ class Messaging extends Action $message = new Document($payload['message'] ?? []); $recipients = $payload['recipients'] ?? []; - $this->sendInternalSMSMessage($message, $project, $recipients, $log); + $this->sendInternalSMSMessage($message, $project, $recipients); break; case MESSAGE_SEND_TYPE_EXTERNAL: $message = $dbForProject->getDocument('messages', $payload['messageId']); @@ -412,7 +408,7 @@ class Messaging extends Action } } - private function sendInternalSMSMessage(Document $message, Document $project, array $recipients, Log $log): void + private function sendInternalSMSMessage(Document $message, Document $project, array $recipients): void { if ($this->adapter === null) { $this->adapter = $this->createInternalSMSAdapter(); diff --git a/src/Appwrite/Platform/Workers/Webhooks.php b/src/Appwrite/Platform/Workers/Webhooks.php index a7f4595966..f5211b1acb 100644 --- a/src/Appwrite/Platform/Workers/Webhooks.php +++ b/src/Appwrite/Platform/Workers/Webhooks.php @@ -11,9 +11,9 @@ use Exception; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; -use Utopia\Logger\Log; use Utopia\Platform\Action; use Utopia\Queue\Message; +use Utopia\Span\Span; use Utopia\System\System; class Webhooks extends Action @@ -38,7 +38,6 @@ class Webhooks extends Action ->inject('dbForPlatform') ->inject('queueForMails') ->inject('publisherForUsage') - ->inject('log') ->inject('plan') ->callback($this->action(...)); } @@ -49,12 +48,11 @@ class Webhooks extends Action * @param Database $dbForPlatform * @param Mail $queueForMails * @param UsagePublisher $publisherForUsage - * @param Log $log * @param array $plan * @return void * @throws Exception */ - public function action(Message $message, Document $project, Database $dbForPlatform, Mail $queueForMails, UsagePublisher $publisherForUsage, Log $log, array $plan): void + public function action(Message $message, Document $project, Database $dbForPlatform, Mail $queueForMails, UsagePublisher $publisherForUsage, array $plan): void { $this->errors = []; $payload = $message->getPayload(); @@ -69,7 +67,7 @@ class Webhooks extends Action $webhookPayload = json_encode($payload['payload']); $user = new Document($payload['user'] ?? []); - $log->addTag('projectId', $project->getId()); + Span::add('projectId', $project->getId()); foreach ($project->getAttribute('webhooks', []) as $webhook) { if (array_intersect($webhook->getAttribute('events', []), $events)) {