57

Normally you just get logger service, and logs go to:

%kernel.root_dir%/%kernel.environment%.log

I would like to log messages form SOAP services ONLY to:

%kernel.root_dir%/%kernel.environment%.soap.log

not to main logfile.

I've read the cookbook, but I don't understand how to configure monolog.

Any help, clues?

Peyman Mohamadpour
  • 17,954
  • 24
  • 89
  • 100
canni
  • 5,737
  • 9
  • 46
  • 68
  • I'm very interested by the answer. I asked a similar question few weeks ago: http://stackoverflow.com/questions/7714790/custom-monolog-logging-channel-in-symfony2-command – Reuven Nov 17 '11 at 15:23

3 Answers3

80

The MonologBundle logs everything using the same handlers for the whole framework. That means if one of your services needs to log to different handlers, you should create your own Logger/Handler and inject that in your service.

This could be an example config (in yaml):

services:
    my_logger:
        class: Symfony\Bridge\Monolog\Logger
        arguments: [soap]
        calls:
            - [pushHandler, [@my_handler]]

    my_handler:
        class: Monolog\Handler\StreamHandler
        # 200 = INFO, see Monolog::Logger for the values of log levels
        arguments: [%kernel.root_dir%/%kernel.environment%.soap.log, 200]

    soap_service:
        class: Your\Soap\Client
        arguments: [@my_logger]

I hope this clarifies it.

Update: as of symfony 2.1, you can also configure which channels receive which handlers, so you could alternatively do something like this:

services:
     soap_service:
         class: Your\Soap\Client
         arguments: [@logger]
         tags:
             - { name: monolog.logger, channel: soap }

Which creates a new soap channel (i.e. logger instance receiving all handlers), then to configure different handlers for this channel:

monolog:
    handlers:
        main:
            type: stream
            path: %kernel.root_dir%/%kernel.environment%.log
            level: error
            channels: [!soap]
        soap:
            type: stream
            path: %kernel.root_dir%/%kernel.environment%.soap.log
            level: info
            channels: [soap]

This means the main handler will receive everything but the soap channel, and the soap handler will receive only the soap channel. You could also remove the channels key on the main handler if you want your main log file to have everything, but also have a copy of only the soap logs separately. This brings a lot of flexibility, and as you see the channels is an array so you can list channels you want, or use the blacklist !name notation to exclude some and include everything else.

Seldaek
  • 40,986
  • 9
  • 97
  • 77
32

I had a similar problem and I chose to use the Monolog library directly instead of the Monolog service.

Monolog uses Monolog\Handler\StreamHandler to write to files. The github page has a simple example:

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

// create a log channel
$log = new Logger('name');
$log->pushHandler(new StreamHandler('path/to/your.log', Logger::WARNING));

// add records to the log
$log->addWarning('Foo');
$log->addError('Bar');

It may be possible to still use the service and simply push a new handler (and pop it once you're done - otherwise you might inadvertently write more than you wanted to to your custom log) but I haven't tested this. Honestly it seemed easier just to use the library directly.

Steven Mercatante
  • 24,757
  • 9
  • 65
  • 109
  • 2
    The bundle just doesn't support other ways of creating different logs than based on the level of the logging. Your solution is nice, but probably it is worth registering this logger and its handler inside the DIC, so you can inject it wherever in your model. – Aldo Stracquadanio Nov 17 '11 at 16:06
  • 1
    It would indeed be possible to just push the handler and pop it after the execution of the soap stuff, but in that case be careful, the handler you push should have `$bubble = false` passed to its constructor, otherwise the previous handlers will still be called. You can also push a NullHandler first to suppress everything, then your own handler to catch only the levels you're interested in. – Seldaek Nov 21 '11 at 11:18
  • 1
    This is still working in 2.8. Just remember that the log is being written at the root of the symfony folder by default. So either hard code the path to the correct location or retrieve the environment variable to push it to the correct location. – thoroc Feb 10 '16 at 12:25
8

I solved the same issue by creating custom channels in config.yml as explained in this link How to Log Messages to different Files.

monolog:
    channels: ['my_logger']

    handlers:
        my_logger:
            level:    debug
            type:     stream
            path:     '%kernel.logs_dir%/my_logger.log'
            channels: [my_logger]

After this, I can access my looger with a dynamically created service named monolog.logger.my_logger

Genoud Magloire
  • 555
  • 6
  • 15