Exception Viewer plugin screenshot
Dark mode ready
Multilingual support
Supports v5.x

Exception Viewer

A Simple & Beautiful Exception Viewer plugin for your Filament Panels.

Tags: Panels
Supported versions:
5.x 4.x 3.x 2.x
Bezhan Salleh avatar Author: Bezhan Salleh

Documentation

filament-exceptions-art

FILAMENT 4.x FILAMENT 5.x Packagist Tests Passing Code Style Passing Downloads

A Simple & Beautiful Exception Viewer for FilamentPHP's Admin Panel

Version Compatibility:

  • Filament 4.x & 5.x → use version 4.x
  • Filament 3.x → use version 3.x
  • Filament 2.x → use version 1.x

#Installation

  1. You can install the package via composer:
composer require bezhansalleh/filament-exceptions
  1. Publish and run the migration via:
php artisan exceptions:install
  1. Register the plugin for the Filament Panel
public function panel(Panel $panel): Panel
{
    return $panel
        ->plugins([
            \BezhanSalleh\FilamentExceptions\FilamentExceptionsPlugin::make()
        ]);
}

That's it! The package automatically registers itself with Laravel's exception handler and starts recording exceptions.

[!IMPORTANT] The plugin follows Filament's theming rules. So, to use the plugin create a custom theme if you haven't already, and add the following line to your theme.css file:

@source '../../../../vendor/bezhansalleh/filament-exceptions/resources/views/**/*.blade.php';

Now build your theme using:

npm run build

#Recording Control

By default, exceptions are recorded automatically. You can control this behavior in your AppServiceProvider's boot() method:

#Stop/Start Recording

use BezhanSalleh\FilamentExceptions\FilamentExceptions;

public function boot(): void
{
    // Stop recording exceptions
    FilamentExceptions::stopRecording();

    // Resume recording
    FilamentExceptions::startRecording();

    // Check if recording is active
    FilamentExceptions::isRecording();
}

#Conditional Recording

Use recordUsing() to define custom logic for when exceptions should be recorded:

use BezhanSalleh\FilamentExceptions\FilamentExceptions;

public function boot(): void
{
    // Only record in production
    FilamentExceptions::recordUsing(fn () => app()->isProduction());

    // Skip specific exception types
    FilamentExceptions::recordUsing(function (Throwable $e) {
        return ! $e instanceof \Illuminate\Validation\ValidationException
            && ! $e instanceof \Illuminate\Auth\AuthenticationException;
    });

    // Combine multiple conditions
    FilamentExceptions::recordUsing(function (Throwable $e) {
        if (! app()->isProduction()) {
            return false;
        }

        // Skip 4xx HTTP exceptions
        if ($e instanceof \Symfony\Component\HttpKernel\Exception\HttpException
            && $e->getStatusCode() < 500) {
            return false;
        }

        return true;
    });
}

#Configuration Options

When registering the FilamentExceptions plugin, you can chain various methods to customize its behavior. Here are all available configuration options:

#Navigation

FilamentExceptionsPlugin::make()
    ->navigationBadge(bool | Closure $condition = true)
    ->navigationBadgeColor(string | array | Closure $color)
    ->navigationGroup(string | Closure | null $group)
    ->navigationParentItem(string | Closure | null $item)
    ->navigationIcon(string | Closure | null $icon)
    ->activeNavigationIcon(string | Closure | null $icon)
    ->navigationLabel(string | Closure | null $label)
    ->navigationSort(int | Closure | null $sort)
    ->registerNavigation(bool | Closure $shouldRegisterNavigation)
    ->subNavigationPosition(SubNavigationPosition | Closure $position)

#Labels and Search

FilamentExceptionsPlugin::make()
    ->modelLabel(string | Closure | null $label)
    ->pluralModelLabel(string | Closure | null $label)
    ->titleCaseModelLabel(bool | Closure $condition = true)
    ->globallySearchable(bool | Closure $condition = true)

#Mass Pruning Settings

FilamentExceptionsPlugin::make()
    ->modelPruneInterval(Carbon $interval)

Note This requires laravel scheduler to be setup and configured in order to work. You can see how to do that here Running The Scheduler

#Tenancy Configuration

FilamentExceptionsPlugin::make()
    ->scopeToTenant(bool | Closure $condition = true)
    ->tenantOwnershipRelationshipName(string | Closure | null $ownershipRelationshipName)
    ->tenantRelationshipName(string | Closure | null $relationshipName)

#General Configuration

FilamentExceptionsPlugin::make()
    ->cluster(string | Closure | null $cluster)
    ->slug(string | Closure | null $slug)

Example usage:

return $panel
    ->plugins([
        FilamentExceptionsPlugin::make()
            ->navigationLabel('Error Logs')
            ->navigationIcon('heroicon-o-bug-ant')
            ->navigationBadge()
            ->navigationGroup('System')
            ->modelPruneInterval(now()->subDays(7))
    ]);

#Custom Exception Model

  1. Extend the base model as follow:
<?php

namespace App\Models;

use BezhanSalleh\FilamentExceptions\Models\Exception as BaseException;

class MyCustomException extends BaseException
{
    ...
}
  1. Then, in a service provider's boot() method for instance AppServiceProvider:
use App\Models\MyCustomException;
use BezhanSalleh\FilamentExceptions\FilamentExceptions;
...
   public function boot()
   {
       FilamentExceptions::model(MyCustomException::class);
   }
...

#Translations

Publish the translations with

php artisan vendor:publish --tag=filament-exceptions-translations

#Testing

composer test

#Changelog

Please see CHANGELOG for more information on what has changed recently.

#Contributing

Please see CONTRIBUTING for details.

#Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

#Credits

#License

The MIT License (MIT). Please see License File for more information.