Skip to content

Commit

Permalink
Add reporter for Model::preventAccessingMissingAttributes() (#824)
Browse files Browse the repository at this point in the history
  • Loading branch information
stayallive committed Apr 11, 2024
1 parent 25e1cd2 commit 054e0d6
Showing 1 changed file with 52 additions and 1 deletion.
53 changes: 52 additions & 1 deletion src/Sentry/Laravel/Integration.php
Expand Up @@ -2,6 +2,7 @@

namespace Sentry\Laravel;

use Illuminate\Database\Eloquent\MissingAttributeException;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\LazyLoadingViolationException;
use Illuminate\Foundation\Configuration\Exceptions;
Expand Down Expand Up @@ -240,6 +241,55 @@ public static function captureUnhandledException(Throwable $throwable): ?EventId
return SentrySdk::getCurrentHub()->captureException($throwable, $hint);
}

/**
* Returns a callback that can be passed to `Model::handleMissingAttributeViolationUsing` to report missing attribute violations to Sentry.
*
* @param callable|null $callback Optional callback to be called after the violation is reported to Sentry.
*
* @return callable
*/
public static function missingAttributeViolationReporter(?callable $callback = null): callable
{
return new class($callback) {
use ResolvesEventOrigin;

/** @var callable|null $callback */
private $callback;

public function __construct(?callable $callback)
{
$this->callback = $callback;
}

public function __invoke(Model $model, string $attribute): void
{
SentrySdk::getCurrentHub()->withScope(function (Scope $scope) use ($model, $attribute) {
$scope->setContext('violation', [
'model' => get_class($model),
'attribute' => $attribute,
'origin' => $this->resolveEventOrigin(),
'kind' => 'missing_attribute',
]);

SentrySdk::getCurrentHub()->captureEvent(
tap(Event::createEvent(), static function (Event $event) {
$event->setLevel(Severity::warning());
}),
EventHint::fromArray([
'exception' => new MissingAttributeException($model, $attribute),
'mechanism' => new ExceptionMechanism(ExceptionMechanism::TYPE_GENERIC, true),
])
);
});

// Forward the violation to the next handler if there is one
if ($this->callback !== null) {
call_user_func($this->callback, $model, $attribute);
}
}
};
}

/**
* Returns a callback that can be passed to `Model::handleLazyLoadingViolationUsing` to report lazy loading violations to Sentry.
*
Expand All @@ -263,7 +313,7 @@ public function __construct(?callable $callback)
public function __invoke(Model $model, string $relation): void
{
// Laravel uses these checks itself to not throw an exception if the model doesn't exist or was just created
// See: https://github.com/laravel/framework/blob/438d02d3a891ab4d73ffea2c223b5d37947b5e93/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php#L563
// See: https://github.com/laravel/framework/blob/438d02d3a891ab4d73ffea2c223b5d37947b5e93/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php#L559-L561
if (!$model->exists || $model->wasRecentlyCreated) {
return;
}
Expand All @@ -273,6 +323,7 @@ public function __invoke(Model $model, string $relation): void
'model' => get_class($model),
'relation' => $relation,
'origin' => $this->resolveEventOrigin(),
'kind' => 'lazy_loading',
]);

SentrySdk::getCurrentHub()->captureEvent(
Expand Down

0 comments on commit 054e0d6

Please sign in to comment.