Symfony create a custom logger file and understand behind the scene
Aug 9, 2023
Symfony
Sometimes we want to log specific data on specific log files, to do so add the following lines in your monolog configuration (https://symfony.com/doc/current/logging/channels_handlers.html) :
monolog: channels: ['my_channel'] handlers: myHandlerLogger: type: stream path: "%kernel.logs_dir%/abc_%kernel.environment%.log" channels: [my_channel] level: debug |
Here we are creating a custom handler with a custom channel named “my_channel”
Then we can use it on our controller or service like below :
private LoggerInterface $logger;
public function __construct( LoggerInterface $myChannelLogger ) { $this->logger = $myChannelLogger; }
#[Route('/', name: 'app_index')] public function index(): Response { $this->logger->info('test'); } |
To take advantage of autowiring (available since version 3.5 of monolog bundle) the injected service must be named <custom_channel_name>Logger => myChannelLogger.
Let us try to understand where is this naming rule inside the vendors
Go to this file : vendor/symfony/monolog-bundle/DependencyInjection/Compiler/LoggerChannelPass.php on line 86
I have commented the code below so we understand what is happening :
foreach ($container->getParameter('monolog.additional_channels') as $chan) { if ($chan === 'app') { continue; } //we generate an id for our new logger service $loggerId = sprintf('monolog.logger.%s', $chan); //we create the new logger service $this->createLogger($chan, $loggerId, $container); //we set the service to public $container->getDefinition($loggerId)->setPublic(true); } |
Let us see what is happening inside the createLogger method : see comments inside the code
protected function createLogger($channel, $loggerId, ContainerBuilder $container) { if (!in_array($channel, $this->channels)) { //we instantiate the logger service $logger = new ChildDefinition('monolog.logger_prototype'); //we replace the channel name argument of the logger base class with our custom channel name $logger->replaceArgument(0, $channel); //we register our service with the id 'monolog.logger.my_channel' $container->setDefinition($loggerId, $logger); $this->channels[] = $channel; }
// Allows only for Symfony 4.2+ if (\method_exists($container, 'registerAliasForArgument')) { $parameterName = $channel . 'Logger'; //we register an alias for argument named myChannelLogger i.e <custom_channel_name>Logger $container->registerAliasForArgument($loggerId, LoggerInterface::class, $parameterName); } } |