mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
refactor(realtime): drop the utopia/logger error path, Sentry spans only
This commit is contained in:
@@ -297,7 +297,7 @@ return [
|
||||
],
|
||||
[
|
||||
'name' => '_APP_LOGGING_CONFIG_REALTIME',
|
||||
'description' => 'Optional separate logging DSN for the Realtime server, so its errors can be routed to a dedicated project. Same DSN format as `_APP_LOGGING_CONFIG`; falls back to `_APP_LOGGING_CONFIG` when empty. When the provider is Sentry (`sentry://PROJECT_ID:SENTRY_API_KEY@SENTRY_HOST/`), Realtime errors are exported as spans to that Sentry project.',
|
||||
'description' => 'Optional separate logging DSN for the Realtime server so its errors go to a dedicated Sentry project. Same DSN format as `_APP_LOGGING_CONFIG`; falls back to `_APP_LOGGING_CONFIG` when empty. Realtime errors are exported as spans, so only the Sentry provider (`sentry://PROJECT_ID:SENTRY_API_KEY@SENTRY_HOST/`) takes effect here — other providers configured via `_APP_LOGGING_CONFIG` apply to the HTTP server and workers only.',
|
||||
'introduction' => '1.8.1',
|
||||
'default' => '',
|
||||
'required' => false,
|
||||
|
||||
@@ -9,8 +9,7 @@ use Utopia\System\System;
|
||||
/**
|
||||
* Export Realtime error spans to a dedicated Sentry project (`_APP_LOGGING_CONFIG_REALTIME`, falling
|
||||
* back to `_APP_LOGGING_CONFIG`) — only here, not in app/init/span.php, so the HTTP/worker/CLI
|
||||
* servers keep reporting to the default project. The `realtimeLogger` registry skips the Sentry
|
||||
* logger for the same condition so each Realtime error is reported once; keep the two in sync.
|
||||
* servers keep reporting to the default project. Only error-bearing spans are sampled.
|
||||
*/
|
||||
$loggingConfig = System::getEnv('_APP_LOGGING_CONFIG_REALTIME', '') ?: System::getEnv('_APP_LOGGING_CONFIG', '');
|
||||
if (empty($loggingConfig)) {
|
||||
|
||||
@@ -110,25 +110,6 @@ $register->set('logger', static fn () => $createLogger(
|
||||
System::getEnv('_APP_LOGGING_PROVIDER', ''),
|
||||
));
|
||||
|
||||
$register->set('realtimeLogger', static function () use ($createLogger): ?Logger {
|
||||
$providerConfig = System::getEnv('_APP_LOGGING_CONFIG_REALTIME', '') ?: System::getEnv('_APP_LOGGING_CONFIG', '');
|
||||
if (empty($providerConfig)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Sentry Realtime errors are exported as spans by app/init/realtime/span.php (same condition),
|
||||
// not via utopia/logger — building both would report each error to Sentry twice.
|
||||
try {
|
||||
if ((new DSN($providerConfig))->getScheme() === 'sentry') {
|
||||
return null;
|
||||
}
|
||||
} catch (Throwable) {
|
||||
// Legacy ;-delimited config, not a DSN; $createLogger handles it.
|
||||
}
|
||||
|
||||
return $createLogger($providerConfig);
|
||||
});
|
||||
|
||||
$register->set('pools', function () {
|
||||
$group = new Group();
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -320,58 +319,12 @@ if (!function_exists('recordRealtimeErrorSpan')) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('pushRealtimeErrorLog')) {
|
||||
/** Push a Realtime error to the utopia/logger provider — non-Sentry providers only; Sentry goes via recordRealtimeErrorSpan(). */
|
||||
function pushRealtimeErrorLog(Throwable $error, string $action, array $tags, ?Document $project, ?Document $user, ?Authorization $authorization): void
|
||||
{
|
||||
global $register;
|
||||
|
||||
$logger = $register->get('realtimeLogger');
|
||||
if (!$logger) {
|
||||
return;
|
||||
}
|
||||
|
||||
$log = new Log();
|
||||
$log->setNamespace('realtime');
|
||||
$log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname()));
|
||||
$log->setVersion(System::getEnv('_APP_VERSION', 'UNKNOWN'));
|
||||
$log->setType(Log::TYPE_ERROR);
|
||||
$log->setMessage($error->getMessage());
|
||||
$log->setAction($action);
|
||||
|
||||
$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');
|
||||
}
|
||||
|
||||
$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() ?? []);
|
||||
|
||||
$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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allows overriding
|
||||
if (!function_exists('logError')) {
|
||||
function logError(Throwable $error, string $action, array $tags = [], ?Document $project = null, ?Document $user = null, ?Authorization $authorization = null): void
|
||||
{
|
||||
if (!$error instanceof Exception) {
|
||||
recordRealtimeErrorSpan($error, $action, $tags, $project, $user, $authorization);
|
||||
pushRealtimeErrorLog($error, $action, $tags, $project, $user, $authorization);
|
||||
}
|
||||
|
||||
Console::error('[Error] Type: ' . get_class($error));
|
||||
|
||||
Reference in New Issue
Block a user