spatie/laravel-http-logger
Laravel middleware that logs incoming HTTP requests (payload, headers, etc.) to your configured log/channel, creating a safety net for critical form submissions and debugging. Includes toggleable enable flag plus customizable log profile and writer.
Installation:
composer require spatie/laravel-http-logger
Publish the config file:
php artisan vendor:publish --provider="Spatie\HttpLogger\HttpLoggerServiceProvider" --tag="config"
Register Middleware:
Add the middleware to your app/Http/Kernel.php under $middleware or $middlewareGroups (e.g., web):
\Spatie\HttpLogger\HttpLoggerMiddleware::class,
First Use Case: Log a critical form submission (e.g., a lead capture form) by ensuring the middleware is applied to the route handling it. The package will automatically log:
GET, POST, etc.)Example route:
Route::post('/leads', [LeadController::class, 'store'])->middleware('web');
Selective Logging:
Use the log config option to restrict logging to specific routes or HTTP methods:
'log' => [
'methods' => ['POST', 'PUT', 'PATCH', 'DELETE'],
'paths' => ['/leads', '/payments/*'],
],
This avoids cluttering logs with GET requests or non-critical endpoints.
Excluding Sensitive Data:
Sanitize payloads by defining blacklisted keys in config/http-logger.php:
'blacklist' => [
'password',
'credit_card_number',
'api_key',
],
Use regex patterns for dynamic exclusion:
'blacklist' => [
'/^password.*$/i',
],
Custom Log Channels:
Direct logs to a dedicated channel (e.g., single or daily) by extending the config:
'channel' => env('HTTP_LOG_CHANNEL', 'stack'),
Configure the channel in config/logging.php.
Integration with Monitoring: Pipe logs to external services (e.g., Sentry, Datadog) by extending the logger:
use Spatie\HttpLogger\Loggers\Logger;
class CustomLogger extends Logger
{
public function log(array $data)
{
parent::log($data);
// Send to external service
Sentry::captureMessage(json_encode($data));
}
}
Bind the custom logger in AppServiceProvider:
$this->app->bind(\Spatie\HttpLogger\Loggers\Logger::class, CustomLogger::class);
Conditional Logging: Dynamically enable/disable logging based on environment or user roles:
if (app()->environment('production') && auth()->check()) {
config(['http-logger.log' => true]);
}
Performance Overhead:
log config to restrict scope.'log' => [
'exclude' => ['/api/*', '/health'],
],
Payload Size Limits:
config/logging.php:
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['single'],
'ignore_exceptions' => false,
'max_files' => 5,
'max_size' => 1024, // Increase size in KB
],
],
Middleware Order:
HttpLoggerMiddleware after authentication middleware to log user context (e.g., auth:api). Example:
$middlewareGroups['api'] = [
\App\Http\Middleware\Authenticate::class,
\Spatie\HttpLogger\HttpLoggerMiddleware::class,
];
Sensitive Data Leaks:
password or token can expose PII.^/secret_.*$/i).Log Rotation:
single channel:
'single' => [
'driver' => 'single',
'path' => storage_path('logs/http/http.log'),
'level' => 'debug',
],
Verify Logging:
Check if logs appear in storage/logs/laravel.log (or your configured channel). Use:
tail -f storage/logs/laravel.log | grep "HTTP_LOGGER"
Middleware Not Triggering:
Kernel.php.handle method to confirm execution:
\Log::debug('HTTP Logger triggered', ['request' => $request->all()]);
Blacklist Not Working:
dd($request->all()) in a route to verify payload structure before logging.Custom Log Format: Extend the logger to modify the log structure:
class CustomLogger extends Logger
{
protected function prepareLogData(Request $request): array
{
$data = parent::prepareLogData($request);
$data['custom_field'] = 'value';
return $data;
}
}
Database Logging: Store logs in a database table by creating a custom logger:
class DatabaseLogger extends Logger
{
public function log(array $data)
{
\App\Models\HttpLog::create($data);
}
}
Rate Limiting:
Combine with throttle middleware to log excessive requests:
Route::middleware(['throttle:10,1', 'http-logger'])->group(function () {
// Rate-limited routes
});
Webhook Notifications: Trigger a webhook on critical logs (e.g., failed payments):
class CriticalLogger extends Logger
{
public function log(array $data)
{
parent::log($data);
if (in_array($data['method'], ['POST']) && str_contains($data['path'], '/payments')) {
Http::post('https://your-webhook-url', ['event' => 'payment_attempt', 'data' => $data]);
}
}
}
How can I help you explore Laravel packages today?