10
votes

I want to log into a different file than the usual dev.log or prod.log

I know that this can be done with different channels and I used it in several services, but I'm not very clear about switching the Monolog channel in a controller.

In a service you just define the channel via the tags attribute in the service definition, but how can I do this in a controller or even better in a specific action?

I know that a possible solution would be this: Symfony 2 : Log into a specific file

But it seems overkill to define two new services just for logging to a custom file.

3

3 Answers

28
votes

The only way to do this is to define your controller as a service and inject a custom logger with a custom channel.

Since the channels are created automatically there is currently no other way, but it's an interesting request and you're not the first, so I created an issue on MonologBundle to allow the definition of channels at the bundle configuration level. That way you could just fetch the proper logger from the controller using $this->get('monolog.logger.mychannel') (which you can already do if the channel exists, but not if you want a custom channel for the controller that nothing else uses).

Update:

As of symfony/monolog-bundle 2.4.0 you can define additional channels as:

monolog:
    channels: ["foo", "bar"]

Then you can retrieve it as $this->get('monolog.logger.mychannel')

6
votes

I know that this is an older post, but I ran into a similar need using symfony/monolog-bundle 2.1.x. I couldn't seem to find exactly what I needed in other threads, so I'm documenting my solution here, which was to create a logger container that used a custom channel.

In config.yml

monolog:
    handlers:
        user_actions:
            type: stream 
            path:  "%kernel.logs_dir%/%kernel.environment%-user-actions.log"
            level: info 
            channels: [user_actions]

In my bundle's services.yml

acme.logger.user_actions:
    class: Acme\MyBundle\Monolog\UserActionsLogger
    arguments: ['@logger']
    tags:
        - { name: monolog.logger, channel: user_actions }

In src/Acme/MyBundle/Monolog/UserActionsLogger.php

<?php

namespace Acme\MyBundle\Monolog;

class UserActionsLogger
{
    public $logger;

    public function __construct($logger)
    {
        $this->logger = $logger;
    }
}

Then you can either inject the logger container into another service with:

acme.user.authenticationhandler:
    class: %acme.user.authenticationhandler.class%
    public: false
    arguments:  ['@router', '@security.context', '@acme.logger.user_actions']

Or, you could selectively use the logger container as a service in any controller:

$userActionsLogger = $this->get('acme.logger.user_actions');

Then you can access the actual logger by:

$userActionsLogger->logger->info('A thing happened!')
3
votes

I am currently using symfony/monolog-bundle 2.3.0 and the following code works.

Configuration in config.yml

monolog:
    handlers:
        main:
            type:  stream
            path:  %kernel.logs_dir%/%kernel.environment%.log
            level: info
        doctrine:
            type:  stream
            path:  %kernel.logs_dir%/doctrine_%kernel.environment%.log
            level: debug
            channels: doctrine

On Controllers

$doctrineLogger = $this->get('monolog.logger.doctrine');

Hope it helps.