Installation Add the updated bridge to your Laravel project via Composer:
composer require symfony/monolog-bridge:^8.1
Ensure monolog/monolog is also installed (required dependency). Note the minimum version requirement now aligns with Symfony 8.1.
Basic Setup
Laravel’s built-in Monolog integration (laravel/log) remains compatible, but Symfony’s bridge now enforces stricter security defaults (e.g., server:log handler binds to localhost by default). No additional config is required unless using Symfony components like Mailer or HttpClient.
First Use Case: Logging HTTP Requests
Use the Symfony\Bridge\Monolog\Processor\SymfonyProcessor to log request data (e.g., in middleware or controllers). Example:
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bridge\Monolog\Processor\SymfonyProcessor;
$logger->pushProcessor(new SymfonyProcessor());
$logger->info('Processing request', [
'query' => $request->query->all(),
]);
Logging Symfony-Specific Events
SymfonyProcessor to auto-enrich logs with request/response data or CLI arguments.MailerHandler (now truncates long subjects safely):
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Bridge\Monolog\Logger;
$logger = new Logger('mailer');
$mailer = new Mailer(new Transport(), $logger);
CLI Logging with interactive_only
The ConsoleHandler now respects the interactive_only flag to prevent log propagation in non-interactive CLI contexts:
use Symfony\Bridge\Monolog\Handler\ConsoleHandler;
$handler = new ConsoleHandler(Logger::DEBUG, true, true, false); // interactive_only=false
$logger->pushHandler($handler);
Custom Handlers for Security
Leverage the default localhost-bound server:log handler (CVE-2026-45077 fix):
php artisan serve --log=debug
Logs will now bind securely to 127.0.0.1 by default.
Middleware for Request Logging Centralize logging in middleware with Symfony processors:
public function handle($request, Closure $next)
{
$logger->pushProcessor(new SymfonyProcessor());
return $next($request);
}
config/logging.php to route Symfony channels (e.g., mailer, http_client) to dedicated files.MaskProcessor:
$logger->pushProcessor(new \Monolog\Processor\MaskProcessor(['api_token']));
when() in AppServiceProvider:
if (app()->environment('local')) {
$logger->pushHandler(new ConsoleHandler());
}
Mailer Subject Truncation
MailerHandler now truncates long email subjects to prevent log bloat. Override with a custom formatter if needed:
use Symfony\Bridge\Monolog\Handler\MailerHandler;
$handler = new MailerHandler($mailer, Logger::ERROR);
$handler->setFormatter(new LineFormatter('%message% %context%'));
CLI Log Propagation
interactive_only in ConsoleHandler may suppress logs in non-interactive scripts (e.g., cron jobs). Explicitly set false if needed:
$handler = new ConsoleHandler(Logger::DEBUG, true, true, false); // Disables interactive_only
Server Log Binding
server:log handler now binds to localhost by default (CVE-2026-45077). For remote logging, configure a custom handler:
$handler = new \Monolog\Handler\StreamHandler(
'php://stdout',
Logger::DEBUG,
true, // Bubble
0644 // Permissions
);
$handler->setUri('tcp://log-server:514'); // Syslog example
Double Processor Warnings
SymfonyProcessor instances in middleware/controllers. Use a service provider to centralize:
public function boot()
{
if (!$this->app->bound('logger') || !$this->app['logger']->hasHandlersOfType(SymfonyProcessor::class)) {
$this->app['logger']->pushProcessor(new SymfonyProcessor());
}
}
dump($logger->getHandlers()) to debug.config/logging.php match Symfony’s defaults:
'channels' => [
'mailer' => ['driver' => 'single', 'path' => storage_path('logs/mailer.log')],
'http_client' => ['driver' => 'single', 'path' => storage_path('logs/http.log')],
],
php artisan --verbose to verify interactive_only behavior.Custom Mailer Formatter
Extend MailerHandler to log full email subjects:
use Symfony\Bridge\Monolog\Handler\MailerHandler;
class CustomMailerHandler extends MailerHandler
{
protected function getMessage(array $record): string
{
return sprintf('Email "%s" %s', $record['context']['subject'], parent::getMessage($record));
}
}
Decorated ConsoleHandler Add metadata to CLI logs:
$handler = new class extends ConsoleHandler {
public function write(array $record): void
{
$record['script'] = basename($_SERVER['argv'][0]);
parent::write($record);
}
};
Laravel Service Provider Centralize Monolog/Symfony integration:
public function register()
{
$this->app->extend('logger', function ($logger) {
$logger->pushProcessor(new SymfonyProcessor());
$logger->pushHandler(new ConsoleHandler(Logger::DEBUG, true, true, false));
return $logger;
});
}
How can I help you explore Laravel packages today?