2
2
3
3
namespace Sentry \Laravel ;
4
4
5
+ use Illuminate \Database \Eloquent \MissingAttributeException ;
5
6
use Illuminate \Database \Eloquent \Model ;
6
7
use Illuminate \Database \LazyLoadingViolationException ;
7
8
use Illuminate \Foundation \Configuration \Exceptions ;
@@ -240,6 +241,55 @@ public static function captureUnhandledException(Throwable $throwable): ?EventId
240
241
return SentrySdk::getCurrentHub ()->captureException ($ throwable , $ hint );
241
242
}
242
243
244
+ /**
245
+ * Returns a callback that can be passed to `Model::handleMissingAttributeViolationUsing` to report missing attribute violations to Sentry.
246
+ *
247
+ * @param callable|null $callback Optional callback to be called after the violation is reported to Sentry.
248
+ *
249
+ * @return callable
250
+ */
251
+ public static function missingAttributeViolationReporter (?callable $ callback = null ): callable
252
+ {
253
+ return new class ($ callback ) {
254
+ use ResolvesEventOrigin;
255
+
256
+ /** @var callable|null $callback */
257
+ private $ callback ;
258
+
259
+ public function __construct (?callable $ callback )
260
+ {
261
+ $ this ->callback = $ callback ;
262
+ }
263
+
264
+ public function __invoke (Model $ model , string $ attribute ): void
265
+ {
266
+ SentrySdk::getCurrentHub ()->withScope (function (Scope $ scope ) use ($ model , $ attribute ) {
267
+ $ scope ->setContext ('violation ' , [
268
+ 'model ' => get_class ($ model ),
269
+ 'attribute ' => $ attribute ,
270
+ 'origin ' => $ this ->resolveEventOrigin (),
271
+ 'kind ' => 'missing_attribute ' ,
272
+ ]);
273
+
274
+ SentrySdk::getCurrentHub ()->captureEvent (
275
+ tap (Event::createEvent (), static function (Event $ event ) {
276
+ $ event ->setLevel (Severity::warning ());
277
+ }),
278
+ EventHint::fromArray ([
279
+ 'exception ' => new MissingAttributeException ($ model , $ attribute ),
280
+ 'mechanism ' => new ExceptionMechanism (ExceptionMechanism::TYPE_GENERIC , true ),
281
+ ])
282
+ );
283
+ });
284
+
285
+ // Forward the violation to the next handler if there is one
286
+ if ($ this ->callback !== null ) {
287
+ call_user_func ($ this ->callback , $ model , $ attribute );
288
+ }
289
+ }
290
+ };
291
+ }
292
+
243
293
/**
244
294
* Returns a callback that can be passed to `Model::handleLazyLoadingViolationUsing` to report lazy loading violations to Sentry.
245
295
*
@@ -263,7 +313,7 @@ public function __construct(?callable $callback)
263
313
public function __invoke (Model $ model , string $ relation ): void
264
314
{
265
315
// Laravel uses these checks itself to not throw an exception if the model doesn't exist or was just created
266
- // See: https://github.com/laravel/framework/blob/438d02d3a891ab4d73ffea2c223b5d37947b5e93/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php#L563
316
+ // See: https://github.com/laravel/framework/blob/438d02d3a891ab4d73ffea2c223b5d37947b5e93/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php#L559-L561
267
317
if (!$ model ->exists || $ model ->wasRecentlyCreated ) {
268
318
return ;
269
319
}
@@ -273,6 +323,7 @@ public function __invoke(Model $model, string $relation): void
273
323
'model ' => get_class ($ model ),
274
324
'relation ' => $ relation ,
275
325
'origin ' => $ this ->resolveEventOrigin (),
326
+ 'kind ' => 'lazy_loading ' ,
276
327
]);
277
328
278
329
SentrySdk::getCurrentHub ()->captureEvent (
0 commit comments