From 072409410e212b1b9094ecfe3ec746722a9875fb Mon Sep 17 00:00:00 2001 From: Irfan Date: Thu, 7 Jul 2022 21:28:01 +0500 Subject: [PATCH] improves sentry integration and order of exceptions --- .env.dist | 6 +- app/Exceptions/GithubReport.php | 24 +++--- app/Exceptions/Handler.php | 132 ++++++++++++-------------------- bootstrap/app.php | 5 ++ config/sentry.php | 4 +- 5 files changed, 74 insertions(+), 97 deletions(-) diff --git a/.env.dist b/.env.dist index 91e63d7..e1a5956 100755 --- a/.env.dist +++ b/.env.dist @@ -121,12 +121,12 @@ INSIGHTS_MAX_STORE_TIME=172800 ### # Error reporting ### -REPORTING=true +REPORTING=false REPORTING_DRIVER=sentry SENTRY_LARAVEL_DSN="https://examplePublicKey@o0.ingest.sentry.io/0" -SENTRY_TRACES_SAMPLE_RATE=1 +SENTRY_TRACES_SAMPLE_RATE=0.5 ### # Endpoints ### -DISABLE_USER_LISTS=false \ No newline at end of file +DISABLE_USER_LISTS=false diff --git a/app/Exceptions/GithubReport.php b/app/Exceptions/GithubReport.php index e13af7e..6a190d8 100755 --- a/app/Exceptions/GithubReport.php +++ b/app/Exceptions/GithubReport.php @@ -15,54 +15,54 @@ class GithubReport /** * @var string */ - private $name; + private string $name; /** * @var string */ - private $code; + private string $code; /** * @var string */ - private $error; + private string $error; /** * @var string */ - private $requestUri; + private string $requestUri; /** * @var string */ - private $requestMethod; + private string $requestMethod; /** * @var string */ - private $repo; + private string $repo; /** * @var string */ - private $trace; + private string $trace; /** * @var string */ - private $jikanVersion; + private string $jikanVersion; /** * @var string */ - private $redisRunning; + private string $redisRunning; /** * @var string */ - private $instanceType; + private string $instanceType; /** - * @var + * @var string */ - private $phpVersion; + private string $phpVersion; /** * @param \Exception $exception diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index da86c21..72dbe24 100755 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -3,10 +3,7 @@ namespace App\Exceptions; use App\Events\SourceHeartbeatEvent; -use App\Http\HttpHelper; use Exception; -use GuzzleHttp\Exception\ClientException; -use GuzzleHttp\Exception\ConnectException; use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Http\JsonResponse; @@ -16,11 +13,9 @@ use Jikan\Exception\BadResponseException; use Jikan\Exception\ParserException; use Laravel\Lumen\Exceptions\Handler as ExceptionHandler; use Predis\Connection\ConnectionException; -use Symfony\Component\Debug\Exception\FlattenException; use Symfony\Component\HttpClient\Exception\TimeoutException; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\HttpException; -use Illuminate\Support\Facades\Cache; /** * Class Handler @@ -41,6 +36,13 @@ class Handler extends ExceptionHandler BadResponseException::class ]; + /** + * @var string[] + */ + protected array $acceptableForReportingDriver = [ + ParserException::class + ]; + /** * @param \Throwable $e * @throws Exception @@ -55,13 +57,10 @@ class Handler extends ExceptionHandler * @param \Throwable $e * @return JsonResponse|Response */ - public function render($request, \Throwable $e) + public function render($request, \Throwable $e): JsonResponse|Response { $githubReport = GithubReport::make($e, $request); - - if (app()->bound('sentry') && $this->shouldReport($e)) { - app('sentry')->captureException($e); - } + $this->reportToSentry($e); // ConnectionException from Redis server if ($e instanceof ConnectionException) { @@ -83,18 +82,6 @@ class Handler extends ExceptionHandler ], 500); } - if ($e instanceof ConnectException) { - event(new SourceHeartbeatEvent(SourceHeartbeatEvent::BAD_HEALTH, $e->getCode())); - - return response() - ->json([ - 'status' => $e->getCode(), - 'type' => 'BadResponseException', - 'message' => 'Jikan failed to connect to MyAnimeList.net. MyAnimeList.net may be down/unavailable, refuses to connect or took too long to respond.', - 'error' => $e->getMessage() - ], 503); - } - // ParserException from Jikan PHP API if ($e instanceof ParserException) { $githubReport->setRepo(env('GITHUB_API', 'jikan-me/jikan')); @@ -108,9 +95,9 @@ class Handler extends ExceptionHandler ], 500); } - // BadResponseException from Guzzle dep via Jikan PHP API + // BadResponseException from Jikan PHP API // This is basically the response MyAnimeList returns to Jikan - if ($e instanceof BadResponseException || $e instanceof ClientException) { + if ($e instanceof BadResponseException) { switch ($e->getCode()) { case 404: // $this->set404Cache($request, $e); @@ -157,6 +144,28 @@ class Handler extends ExceptionHandler } } + if ($e instanceof TimeoutException) { + return response() + ->json([ + 'status' => 408, + 'type' => 'TimeoutException', + 'message' => 'Request to MyAnimeList.net timed out (' .env('SOURCE_TIMEOUT', 5) . ' seconds)', + 'error' => $e->getMessage() + ], 408); + } + + if ($e instanceof Exception && $e->getMessage() === "Undefined index: url") { + event(new SourceHeartbeatEvent(SourceHeartbeatEvent::BAD_HEALTH, $e->getCode())); + + return response() + ->json([ + 'status' => $e->getCode(), + 'type' => 'BadResponseException', + 'message' => 'Jikan failed to connect to MyAnimeList.net. MyAnimeList.net may be down/unavailable, refuses to connect or took too long to respond. Retry the request!', + 'error' => $e->getMessage() + ], 503); + } + // Bad REST API requests if ($e instanceof HttpException) { return response() @@ -168,71 +177,32 @@ class Handler extends ExceptionHandler ], $e->getStatusCode()); } - if ($e instanceof TimeoutException) { - return response() - ->json([ - 'status' => 408, - 'type' => 'TimeoutException', - 'message' => 'Request to MyAnimeList.net timed out (' .env('SOURCE_TIMEOUT', 5) . ' seconds)', - 'error' => $e->getMessage() - ], 408); - } - - if ($e instanceof Exception) { - if ($e->getMessage() === "Undefined index: url") { - event(new SourceHeartbeatEvent(SourceHeartbeatEvent::BAD_HEALTH, $e->getCode())); - - return response() - ->json([ - 'status' => $e->getCode(), - 'type' => 'BadResponseException', - 'message' => 'Jikan failed to connect to MyAnimeList.net. MyAnimeList.net may be down/unavailable, refuses to connect or took too long to respond. Retry the request!', - 'error' => $e->getMessage() - ], 503); - } - - - return response() - ->json([ - 'status' => 500, - 'type' => "Exception", - 'message' => 'Unhandled Exception. Please follow report_url to generate an issue on GitHub', - 'trace' => "{$e->getFile()} at line {$e->getLine()}", - 'error' => $e->getMessage(), - 'report_url' => env('GITHUB_REPORTING', true) ? (string) $githubReport : null - ], 500); - } + return response() + ->json([ + 'status' => 500, + 'type' => "Exception", + 'message' => 'Unhandled Exception. Please follow report_url to generate an issue on GitHub', + 'trace' => "{$e->getFile()} at line {$e->getLine()}", + 'error' => $e->getMessage(), + 'report_url' => env('GITHUB_REPORTING', true) ? (string) $githubReport : null + ], 500); } + /** - * @param Request $request - * @param BadResponseException $e + * @param Exception|\Throwable $e + * @return void */ - private function set404Cache(Request $request, BadResponseException $e) + private function reportToSentry(\Exception|\Throwable $e): void { - if (!env('CACHING') || env('MICROCACHING')) { + if (!app()->bound('sentry')) { return; } - $fingerprint = "request:404:".sha1(env('APP_URL') . $request->getRequestUri()); - - if (Cache::has($fingerprint)) { - return; + foreach ($this->acceptableForReportingDriver as $type) { + if ($e instanceof $type) { + app('sentry')->captureException($e); + } } - - $routeController = HttpHelper::requestControllerName($request); - $cacheTtl = env('CACHE_DEFAULT_EXPIRE', 86400); - - if (\in_array($routeController, [ - 'AnimeController', - 'MangaController', - 'CharacterController', - 'PersonController' - ])) { - $cacheTtl = env('CACHE_404_EXPIRE', 604800); - } - - - Cache::put($fingerprint, $e->getMessage(), $cacheTtl); } } diff --git a/bootstrap/app.php b/bootstrap/app.php index 7d5d8fc..c59ee1e 100755 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -117,6 +117,11 @@ if (env('REPORTING') && env('REPORTING_DRIVER') === 'sentry') { $app->register(\Sentry\Laravel\ServiceProvider::class); // Sentry Performance Monitoring (optional) $app->register(\Sentry\Laravel\Tracing\ServiceProvider::class); + + \Sentry\configureScope(function (\Sentry\State\Scope $scope): void { + $scope->setTag('rest.jikan.version', env('APP_VERSION')); + $scope->setTag('parser.jikan.version', JIKAN_PARSER_VERSION); + }); } // Guzzle removed as of lumen 8.x diff --git a/config/sentry.php b/config/sentry.php index 0f2c2e1..5d5a8ff 100644 --- a/config/sentry.php +++ b/config/sentry.php @@ -8,7 +8,7 @@ return [ // 'release' => trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')), // When left empty or `null` the Laravel environment will be used - 'environment' => env('SENTRY_ENVIRONMENT'), + 'environment' => env('APP_ENV'), 'breadcrumbs' => [ // Capture Laravel logs in breadcrumbs @@ -54,4 +54,6 @@ return [ 'controllers_base_namespace' => env('SENTRY_CONTROLLERS_BASE_NAMESPACE', 'App\\Http\\Controllers'), + 'release' => env('APP_VERSION') + ];