如何在Laravel 6中向Sentry.io报告带有stacktrace的ModelNotFoundException



我使用下面的laravel 6代码向Sentry.io:报告异常

public function report(Exception $exception)
{
if ($this->shouldReport($exception) && app()->bound('sentry')) {
app('sentry')->captureException($exception);
}
parent::report($exception);
}

所有异常都可以向哨兵报告。然而,最近我发现ModelNotFoundException没有发送到Sentry。此外,我发现了原因,这是由于文件的以下代码中存在ModelNotFoundException(Illuminate\Foundation\Exceptions\Handler.php(:

protected $internalDontReport = [
AuthenticationException::class,
AuthorizationException::class,
HttpException::class,
HttpResponseException::class,
ModelNotFoundException::class,
SuspiciousOperationException::class,
TokenMismatchException::class,
ValidationException::class,
];

作为内置代码,我无法删除上面代码中的ModelNotFoundException。有没有办法将ModelNotFoundException发送到sentry?

$internalDontReport受到保护,因此您可以覆盖它,尽管最好不要覆盖它,因为列表将来可能会更改,并要求您保持同步。

您可以删除$this->shouldReport($exception),但这将导致所有被忽略的异常被报告,这可能不是您想要的。

如果你只关心ModelNotFoundException:,你可以这样做

protected $doReportToSentry = [
IlluminateDatabaseEloquentModelNotFoundException::class,
];
public function report(Exception $e)
{
if ($this->shouldReportToSentry($e) && app()->bound('sentry')) {
app('sentry')->captureException($e);
}
parent::report($e);
}
protected function shouldReportToSentry(Exception $e)
{
if ($this->shouldReport($e)) {
return true;
}
return !is_null(IlluminateSupportArr::first($this->doReportToSentry, function ($type) use ($e) {
return $e instanceof $type;
}));
}

您可以向$doReportToSentry数组添加任何要确保报告的类,即使Laravel可能(默认情况下(会忽略它

我自己也遇到过类似的问题,findOrFail在找不到本应始终存在的模型时返回404响应。我希望它返回500并记录它,这样我就可以意识到数据库的不一致性。

我的解决方案是覆盖AppExceptionsHandler.php中的几个方法,如下所示:

protected function shouldntReport(Throwable $e): bool
{
$shouldntReport = parent::shouldntReport($e);
return $e instanceof ModelNotFoundException ? false : $shouldntReport;
}
protected function prepareException(Throwable $e): Throwable
{
if ($e instanceof ModelNotFoundException) {
return $e;
}
return parent::prepareException($e);
}

第一个覆盖shouldntReport会将错误写入日志。

第二个超控prepareException导致返回500错误而不是404错误。

如果你对404错误很满意,只想将其记录下来(并发送到Sentry(,请随意只覆盖第一个方法。

请记住,如果你这样做,你需要检查模型是否存在,并在需要时手动返回404。但这将避免,例如,丢失的子实体返回404,并使其看起来像根实体丢失的问题。

例如,如果你希望所有用户都与一个角色模型有关系,而一个用户没有角色,我的更改使其不会返回404错误。这是数据库不一致,应该是500错误。404错误会使其看起来像是没有找到用户,这是错误的。找不到的是角色,而不是用户。

我是新手,无法对@Chris的回答发表评论。

我用的是Laravel 10。

由于类ModelNotFoundException扩展了RecordsNotFoundException,我不得不对进行此更改

protected function prepareException(Throwable $e): Throwable
{
if ($e instanceof ModelNotFoundException) {
return $e;
}
if ($e instanceof RecordsNotFoundException) {
return $e;
}
return parent::prepareException($e);
}

最新更新