eryndrix / exception-logger
Exception logging package for Laravel with PSR-3 levels and attribute-based configuration.
Requires
- php: ^8.5
- illuminate/support: ^13.0
Requires (Dev)
- larastan/larastan: ^3.11
- orchestra/testbench: ^11.0
- pestphp/pest: ^5.1
- pestphp/pest-plugin-laravel: ^5.0
- phpstan/phpstan: ^2.2
- phpstan/phpstan-strict-rules: ^2.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
A Laravel package for structured exception logging with PSR-3 levels and attribute-based configuration. It allows you to define log levels per exception class using PHP attributes or configuration, and customize which exception details (stack trace, file, line, etc.) are included in logs based on severity.
Features
- PSR-3 compliant: Supports all 8 standard log levels (
debug,info,notice,warning,error,critical,alert,emergency) - Attribute-Based Configuration: Use
#[Log]attribute to define log level on exception classes - Configurable Context: Control which exception details to include in logs (exception class, code, file, line, trace)
- Level-Specific Context: Different context configuration for each log level
- Exception Level Mapping: Map exception classes to log levels via config
Installation
composer require eryndrix/exception-logger
The service provider auto-registers. To publish the configuration file:
php artisan vendor:publish --tag="exception-logger-config"
Requirements
- PHP ^8.5
- Laravel ^13.0
Quick Start
- Use built-in exceptions
use Eryndrix\Logging\Exceptions\PaginationException; use Eryndrix\Logging\Exceptions\UserNotFoundException; use Eryndrix\Logging\Exceptions\UnexpectedException; throw new PaginationException(perPage: 500); // WARNING throw new UserNotFoundException(); // WARNING throw new UnexpectedException(message: 'Oops'); // CRITICAL
- Or create your own
use Eryndrix\Logging\Attributes\{Level, Log}; #[Log(level: Level::WARNING)] final class PaginationException extends \DomainException {} #[Log(level: Level::WARNING)] final class UserNotFoundException extends \LogicException {} #[Log(level: Level::CRITICAL)] final class UnexpectedException extends \RuntimeException {}
- Log exceptions
Inject ExceptionLoggerInterface and call log():
use Eryndrix\Logging\Contracts\ExceptionLoggerInterface; class MyService { public function __construct( private ExceptionLoggerInterface $logger ) {} public function handle(): void { try { // ... } catch (\Throwable $e) { $this->logger->log(exception: $e); } } }
The logger resolves the level in this order:
#[Log]attribute on the exception classexception_levelsconfig mappingdefault_levelfallback
Logger Interface
For direct logging without level resolution, use LoggerInterface:
use Eryndrix\Logging\Contracts\LoggerInterface; class MyService { public function __construct( private LoggerInterface $logger ) {} public function handle(): void { $exception = new \RuntimeException( message: 'error' ); $this->logger->error( message: 'Something went wrong', e: $exception ); $this->logger->warning( message: 'Potential issue', e: $exception ); $this->logger->debug( message: 'Debug info', e: $exception ); } }
Configuration
The published config (config/exception-logger.php) has three sections:
default_level
Fallback level for exceptions without explicit configuration:
'default_level' => env('DEFAULT_LOG_LEVEL', 'error')
Tip: Use error in production, debug in development.
exception_levels
Map exception classes to levels without modifying them:
'exception_levels' => [ \DomainException::class => 'warning', \InvalidArgumentException::class => 'warning', \App\Exceptions\PaginationException::class => 'warning', ]
context
Control which details to include per log level:
'context' => [ 'emergency' => [ 'exception' => true, 'code' => true, 'file' => true, 'line' => true, 'trace' => true, ], 'error' => [ 'exception' => true, 'code' => true, 'file' => true, 'line' => true, 'trace' => false, ], 'warning' => [ 'exception' => true, 'code' => true, 'file' => false, 'line' => false, 'trace' => false, ], // ... other levels ]
Available fields:
| Field | Description |
|---|---|
exception |
Exception class name |
code |
Exception code (integer) |
file |
File where exception was thrown (full path) |
line |
Line number |
trace |
Full stack trace (can be very verbose) |
Security note: In production, disable file, line, and trace to avoid exposing internal paths.
Example Log Output
With the default config, a PaginationException produces:
{
"message": "Per page must be between 1 and 100. Given: 500.",
"context": {
"exception": "Eryndrix\\Logging\\Exceptions\\PaginationException",
"code": 0,
"file": "/vendor/eryndrix/exception-logger/src/Exceptions/PaginationException.php",
"line": 24
},
"level": "warning"
}
Testing
Run package tests:
./vendor/bin/pest
License
This project is licensed under the MIT License.