Installation
composer require dmp/loggable-bundle
Register the bundle in config/app.php under providers:
Dmp\LoggableBundle\LoggableServiceProvider::class,
Enable Annotation Processing
Ensure your Laravel application supports annotations (e.g., via ramsey/uuid or doctrine/annotations). If not, install:
composer require doctrine/annotations
First Use Case Annotate a method in a service/controller:
use Dmp\LoggableBundle\Annotation\Loggable;
class UserService {
/**
* @Loggable
*/
public function updateUser($userId, $data) {
// Your logic here
}
}
The method execution will now be logged automatically, including input parameters, return values, and exceptions.
Annotation Placement
Apply @Loggable to methods where you want execution logging:
/**
* @Loggable
*/
public function processOrder(Order $order) { ... }
/**
* @Loggable
*/
class OrderProcessor { ... }
Integration with Laravel Logging
The bundle uses Laravel’s default logger (Log::channel()). Customize logging channels in config/logging.php for structured logs (e.g., Monolog handlers).
Dynamic Logging Override log behavior via method arguments:
/**
* @Loggable(logLevel="debug", skipParams=["password"])
*/
public function login($email, $password) { ... }
logLevel: debug, info, warning, error (default: info).skipParams: Array of parameter names to exclude from logs.logResponse: Boolean to log return values (default: true).Middleware/Event Integration Use the bundle alongside Laravel’s middleware or events for layered logging:
// Log before/after middleware
public function handle($request, Closure $next) {
Log::info('Request started', ['url' => $request->url()]);
$response = $next($request);
Log::info('Request completed', ['status' => $response->status()]);
return $response;
}
Testing Mock the logger in tests to verify logs:
$mock = Mockery::mock('overload:Log');
$mock->shouldReceive('info')->once();
Annotation Parsing
doctrine/annotations cache is stale.php artisan cache:clear
php artisan config:clear
Performance Overhead
config/logging.php for production):
'default' => env('LOG_CHANNEL', 'stack'),
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['single'],
'ignore_exceptions' => false,
],
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => env('APP_ENV') === 'production' ? 'warning' : 'debug',
],
],
Circular Dependencies
UserService logging OrderService which logs UserService) may cause infinite loops.Parameter Serialization
__toString() or use skipParams to exclude problematic parameters.Verify Annotation Processing Check if annotations are registered:
$reflection = new ReflectionClass(UserService::class);
$method = $reflection->getMethod('updateUser');
$annotations = \Doctrine\Common\Annotations\Reader::getInstance()->getMethodAnnotation($method, Loggable::class);
Log Bundle Initialization
Add debug logs in LoggableServiceProvider to confirm the bundle loads:
public function boot() {
Log::debug('LoggableBundle initialized');
}
Check for Conflicts
Ensure no other packages override the Loggable annotation or aspect-oriented logic.
Custom Log Formatters Override the default log format by binding a custom formatter to the container:
$this->app->bind(LogFormatterInterface::class, CustomLogFormatter::class);
Add Conditional Logging
Extend the Loggable annotation to support dynamic conditions:
/**
* @Loggable(condition="request()->user()->isAdmin()")
*/
public function adminAction() { ... }
(Requires custom implementation of the condition attribute parser.)
Integrate with Monitoring Tools Pipe logs to external services (e.g., Sentry, Datadog) by extending the logger channel:
'channels' => [
'loggable' => [
'driver' => 'monolog',
'handler' => \Monolog\Handler\PushHandler::class,
'with' => [
'bubble' => false,
'handler' => new \Monolog\Handler\SyslogHandler('loggable'),
],
],
],
Support for Async Logging Use Laravel’s queue-based logging to offload I/O:
'channels' => [
'loggable' => [
'driver' => 'async',
'queue' => 'logs',
],
],
How can I help you explore Laravel packages today?