Error Tracking
Learn how to capture and report errors with the Laravel SDK.
Automatic Error Capturing
The Laravel SDK automatically captures all unhandled exceptions. Once installed, exceptions thrown in your application are reported to Nadi without any additional code.
// This is automatically captured
public function show($id)
{
$user = User::findOrFail($id); // 404 exceptions are captured
}Manual Error Capturing
Capturing Exceptions
Capture exceptions while still handling them in your code:
use Nadi\Laravel\Facades\Nadi;
try {
$this->processPayment($order);
} catch (PaymentException $e) {
Nadi::captureException($e);
// Continue handling the exception
return back()->withError('Payment failed. Please try again.');
}Capturing with Context
Add context when capturing:
use Nadi\Laravel\Facades\Nadi;
try {
$this->processPayment($order);
} catch (PaymentException $e) {
Nadi::captureException($e, [
'extra' => [
'order_id' => $order->id,
'amount' => $order->total,
'gateway' => $order->payment_gateway,
],
'tags' => [
'payment_type' => 'credit_card',
],
]);
}Capturing Messages
Log important events without exceptions:
use Nadi\Laravel\Facades\Nadi;
// Info level message
Nadi::captureMessage('User upgraded to premium');
// With explicit level
Nadi::captureMessage('API rate limit approaching', 'warning');
// With context
Nadi::captureMessage('Large export completed', 'info', [
'extra' => [
'records' => 50000,
'duration_ms' => 12500,
],
]);Available levels: debug, info, warning, error, fatal
Error Levels
Automatic Level Assignment
The SDK assigns levels based on exception type:
| Exception Type | Level |
|---|---|
ErrorException (E_ERROR, E_PARSE) | fatal |
ErrorException (E_WARNING) | warning |
ErrorException (E_NOTICE) | info |
| Other exceptions | error |
Custom Level Mapping
Override levels for specific exceptions in config/nadi.php:
'exception_levels' => [
\App\Exceptions\MinorException::class => 'warning',
\App\Exceptions\DeprecationException::class => 'info',
\App\Exceptions\CriticalException::class => 'fatal',
],Filtering Exceptions
Ignoring Exceptions
Don't report certain exception types:
// config/nadi.php
'dont_report' => [
\Illuminate\Auth\AuthenticationException::class,
\Illuminate\Validation\ValidationException::class,
\Symfony\Component\HttpKernel\Exception\NotFoundHttpException::class,
\App\Exceptions\ExpectedException::class,
],Allowlist Mode
Only report specific exceptions (ignores dont_report):
// config/nadi.php
'report_only' => [
\App\Exceptions\CriticalException::class,
\App\Exceptions\PaymentException::class,
],Dynamic Filtering
Filter exceptions at runtime:
// AppServiceProvider.php
use Nadi\Laravel\Facades\Nadi;
public function boot()
{
Nadi::beforeCapture(function ($event, $hint) {
// Don't report exceptions from bots
if (request()->header('User-Agent') === 'Bot/1.0') {
return null; // Returning null prevents capture
}
return $event;
});
}Exception Handler Integration
Laravel 11+
The SDK integrates automatically. For custom behavior, modify bootstrap/app.php:
use Nadi\Laravel\Facades\Nadi;
return Application::configure(basePath: dirname(__DIR__))
->withExceptions(function (Exceptions $exceptions) {
$exceptions->report(function (Throwable $e) {
Nadi::captureException($e);
});
})
->create();Laravel 9-10
Modify app/Exceptions/Handler.php:
use Nadi\Laravel\Facades\Nadi;
public function register()
{
$this->reportable(function (Throwable $e) {
Nadi::captureException($e);
});
}Queue Job Exceptions
Queue job exceptions are automatically captured. Configure in config/nadi.php:
'capture_queue_exceptions' => true,Additional context is included:
- Job class name
- Queue name
- Attempt number
- Job payload (filtered)
Manual Queue Exception Handling
use Nadi\Laravel\Facades\Nadi;
class ProcessOrder implements ShouldQueue
{
public function handle()
{
try {
$this->process();
} catch (\Exception $e) {
Nadi::captureException($e, [
'tags' => ['job' => 'process_order'],
'extra' => ['order_id' => $this->order->id],
]);
throw $e; // Re-throw for retry logic
}
}
}Console Command Exceptions
Exceptions in Artisan commands are automatically captured:
class ImportData extends Command
{
public function handle()
{
// Exceptions here are captured with command context
$this->import();
}
}Scheduled Task Exceptions
Enable scheduled task exception capturing:
// config/nadi.php
'capture_schedule_exceptions' => true,Breadcrumbs
Breadcrumbs provide a trail of events leading up to an error:
use Nadi\Laravel\Facades\Nadi;
// Add a breadcrumb
Nadi::addBreadcrumb('Loaded user profile', 'navigation', [
'user_id' => $user->id,
]);
// Later, when an error occurs, breadcrumbs are included
throw new \Exception('Failed to update profile');Automatic Breadcrumbs
The SDK automatically records:
- Route navigation
- Database queries (optional)
- Log messages
- HTTP requests
- User authentication events
Configure in config/nadi.php:
'breadcrumbs' => [
'sql_queries' => true,
'log_messages' => true,
'http_requests' => true,
'auth_events' => true,
'max_breadcrumbs' => 100,
],Error Grouping
Nadi automatically groups similar errors. The grouping is based on:
- Exception class
- Error message (with dynamic values normalized)
- Stack trace signature
Custom Fingerprinting
Override the default grouping:
use Nadi\Laravel\Facades\Nadi;
Nadi::beforeCapture(function ($event, $hint) {
// Group all timeout errors together
if ($hint['exception'] instanceof TimeoutException) {
$event['fingerprint'] = ['timeout-exception'];
}
return $event;
});Next Steps
- Context & Metadata - Add rich context to errors
- User Identification - Track affected users
- Sampling - Control which errors are captured