Skip to content
  • About
    • What is Symfony?
    • Community
    • News
    • Contributing
    • Support
  • Documentation
    • Symfony Docs
    • Symfony Book
    • Screencasts
    • Symfony Bundles
    • Symfony Cloud
    • Training
  • Services
    • SensioLabs Professional services to help you with Symfony
    • Platform.sh for Symfony Best platform to deploy Symfony apps
    • SymfonyInsight Automatic quality checks for your apps
    • Symfony Certification Prove your knowledge and boost your career
    • Blackfire Profile and monitor performance of your apps
  • Other
  • Blog
  • Download
sponsored by SensioLabs
  1. Home
  2. Documentation
  3. Logging with Monolog
  • Documentation
  • Book
  • Reference
  • Bundles
  • Cloud

Table of Contents

  • Logging a Message
  • Where Logs are Stored
  • Handlers: Writing Logs to different Locations
    • Handlers that Modify Log Entries
  • All Built-in Handlers
  • How to Rotate your Log Files
  • Using a Logger inside a Service
  • Adding extra Data to each Log (e.g. a unique request token)
  • Learn more

Logging with Monolog

Edit this page

Warning: You are browsing the documentation for Symfony 2.7, which is no longer maintained.

Read the updated version of this page for Symfony 6.2 (the current stable version).

Logging with Monolog

Symfony comes with an outside library - called Monolog - that allows you to create logs that can be stored in a variety of different places.

Logging a Message

To log a message, fetch the logger service from the container in your controller:

1
2
3
4
5
6
7
8
9
10
11
12
13
public function indexAction()
{
    $logger = $this->get('logger');
    $logger->info('I just got the logger');
    $logger->error('An error occurred');

    $logger->critical('I left the oven on!', array(
        // include extra "context" info in your logs
        'cause' => 'in_hurry',
    ));

    // ...
}

The logger service has different methods for different logging levels/priorities. You can configure the logger to do different things based on the level of a message (e.g. send an email when an error occurs).

See LoggerInterface for a list of all of the methods on the logger.

Where Logs are Stored

The configuration for where logs are stored lives in the specific environment configuration files: config_dev.yml and config_prod.yml.

By default, log entries are written to the app/logs/dev.log file when you're in the dev environment. In the prod environment, logs are written to app/logs/prod.log, but only during a request where an error or high-priority log entry was made (i.e. error() , critical(), alert() or emergency()).

To control this, you'll configure different handlers that handle log entries, sometimes modify them, and ultimately store them.

Handlers: Writing Logs to different Locations

The logger has a stack of handlers, and each can be used to write the log entries to different locations (e.g. files, database, Slack, etc).

Tip

You can also configure logging "channels", which are like categories. Each channel can have its own handlers, which means you can store different log messages in different places. See How to Log Messages to different Files.

Symfony pre-configures some basic handlers in the config_dev.yml and config_prod.yml files. Check these out for some real-world examples.

This example uses two handlers: stream (to write to a file) and syslog to write logs using the syslog function:

  • YAML
  • XML
  • PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# app/config/config.yml
monolog:
    handlers:
        # this "file_log" key could be anything
        file_log:
            type: stream
            # log to app/logs/(environment).log
            path: "%kernel.logs_dir%/%kernel.environment%.log"
            # log *all* messages (debug is lowest level)
            level: debug

        syslog_handler:
            type: syslog
            # log error-level messages and higher
            level: error
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:monolog="http://symfony.com/schema/dic/monolog"
    xsi:schemaLocation="http://symfony.com/schema/dic/services
        http://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/monolog
        http://symfony.com/schema/dic/monolog/monolog-1.0.xsd">

    <monolog:config>
        <monolog:handler
            name="file_log"
            type="stream"
            path="%kernel.logs_dir%/%kernel.environment%.log"
            level="debug"
        />
        <monolog:handler
            name="syslog_handler"
            type="syslog"
            level="error"
        />
    </monolog:config>
</container>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// app/config/config.php
$container->loadFromExtension('monolog', array(
    'handlers' => array(
        'file_log' => array(
            'type'  => 'stream',
            'path'  => '%kernel.logs_dir%/%kernel.environment%.log',
            'level' => 'debug',
        ),
        'syslog_handler' => array(
            'type'  => 'syslog',
            'level' => 'error',
        ),
    ),
));

This defines a stack of handlers and each handler is called in the order that it's defined.

Handlers that Modify Log Entries

Instead of writing log files somewhere, some handlers are used to filter or modify log entries before sending them to other handlers. One powerful, built-in handler called fingers_crossed is used in the prod environment by default. It stores all log messages during a request but only passes them to a second handler if one of the messages reaches an action_level. Take this example:

  • YAML
  • XML
  • PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# app/config/config.yml
monolog:
    handlers:
        filter_for_errors:
            type: fingers_crossed
            # if *one* log is error or higher, pass *all* to file_log
            action_level: error
            handler: file_log

        # now passed *all* logs, but only if one log is error or higher
        file_log:
            type: stream
            path: "%kernel.logs_dir%/%kernel.environment%.log"

        # still passed *all* logs, and still only logs error or higher
        syslog_handler:
            type: syslog
            level: error
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:monolog="http://symfony.com/schema/dic/monolog"
    xsi:schemaLocation="http://symfony.com/schema/dic/services
        http://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/monolog
        http://symfony.com/schema/dic/monolog/monolog-1.0.xsd">

    <monolog:config>
        <monolog:handler
            name="filter_for_errors"
            type="fingers_crossed"
            action-level="error"
            handler="file_log"
        />
        <monolog:handler
            name="file_log"
            type="stream"
            path="%kernel.logs_dir%/%kernel.environment%.log"
            level="debug"
        />
        <monolog:handler
            name="syslog_handler"
            type="syslog"
            level="error"
        />
    </monolog:config>
</container>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// app/config/config.php
$container->loadFromExtension('monolog', array(
    'handlers' => array(
        'filter_for_errors' => array(
            'type'         => 'fingers_crossed',
            'action_level' => 'error',
            'handler'      => 'file_log',
        ),
        'file_log' => array(
            'type'  => 'stream',
            'path'  => '%kernel.logs_dir%/%kernel.environment%.log',
            'level' => 'debug',
        ),
        'syslog_handler' => array(
            'type'  => 'syslog',
            'level' => 'error',
        ),
    ),
));

Now, if even one log entry has an error level or higher, then all log entries for that request are saved to a file via the file_log handler. That means that your log file will contain all the details about the problematic request - making debugging much easier!

Tip

The handler named "file_log" will not be included in the stack itself as it is used as a nested handler of the fingers_crossed handler.

Note

If you want to override the monolog configuration via another config file, you will need to redefine the entire handlers stack. The configuration from the two files cannot be merged because the order matters and a merge does not allow to control the order.

All Built-in Handlers

Monolog comes with many built-in handlers for emailing logs, sending them to Loggly, or notifying you in Slack. These are documented inside of MonologBundle itself. For a full list, see Monolog Configuration.

How to Rotate your Log Files

Over time, log files can grow to be huge, both while developing and on production. One best-practice solution is to use a tool like the logrotate Linux command to rotate log files before they become too large.

Another option is to have Monolog rotate the files for you by using the rotating_file handler. This handler creates a new log file every day and can also remove old files automatically. To use it, just set the type option of your handler to rotating_file:

  • YAML
  • XML
  • PHP
1
2
3
4
5
6
7
8
9
10
# app/config/config_dev.yml
monolog:
    handlers:
        main:
            type:  rotating_file
            path:  '%kernel.logs_dir%/%kernel.environment%.log'
            level: debug
            # max number of log files to keep
            # defaults to zero, which means infinite files
            max_files: 10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- app/config/config_dev.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:monolog="http://symfony.com/schema/dic/monolog"
    xsi:schemaLocation="http://symfony.com/schema/dic/services
        http://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/monolog
        http://symfony.com/schema/dic/monolog/monolog-1.0.xsd">

    <monolog:config>
        <!-- "max_files": max number of log files to keep
             defaults to zero, which means infinite files -->
        <monolog:handler name="main"
            type="rotating_file"
            path="%kernel.logs_dir%/%kernel.environment%.log"
            level="debug"
            max-files="10"
        />
    </monolog:config>
</container>
1
2
3
4
5
6
7
8
9
10
11
12
13
// app/config/config_dev.php
$container->loadFromExtension('monolog', array(
    'handlers' => array(
        'main' => array(
            'type'  => 'rotating_file',
            'path'  => '%kernel.logs_dir%/%kernel.environment%.log',
            'level' => 'debug',
            // max number of log files to keep
            // defaults to zero, which means infinite files
            'max_files' => 10,
        ),
    ),
));

Using a Logger inside a Service

To use a logger in your own services, add the @logger service as an argument of those services. If you want to use a pre-configured logger which uses a specific channel (app by default), use the monolog.logger tag with the channel property as explained in the Dependency Injection reference.

Adding extra Data to each Log (e.g. a unique request token)

Monolog also supports processors: functions that can dynamically add extra information to your log entries.

See How to Add extra Data to Log Messages via a Processor for details.

Learn more

  • How to Log Messages to different Files
  • How to Disable Microseconds Precision (for a Performance Boost)
  • How to Define a Custom Logging Formatter
  • How to Configure Monolog to Display Console Messages
  • How to Configure Monolog to Email Errors
  • How to Configure Monolog to Exclude 404 Errors from the Log
  • How to Add extra Data to Log Messages via a Processor
This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.
TOC
    Version
    We stand with Ukraine.
    Version:
    Make sure your project is risk free

    Make sure your project is risk free

    Measure & Improve Symfony Code Performance

    Measure & Improve Symfony Code Performance

    Symfony footer

    ↓ Our footer now uses the colors of the Ukrainian flag because Symfony stands with the people of Ukraine.

    Avatar of david-binda, a Symfony contributor

    Thanks david-binda for being a Symfony contributor

    2 commits • 2 lines changed

    View all contributors that help us make Symfony

    Become a Symfony contributor

    Be an active part of the community and contribute ideas, code and bug fixes. Both experts and newcomers are welcome.

    Learn how to contribute

    Symfony™ is a trademark of Symfony SAS. All rights reserved.

    • What is Symfony?

      • Symfony at a Glance
      • Symfony Components
      • Case Studies
      • Symfony Releases
      • Security Policy
      • Logo & Screenshots
      • Trademark & Licenses
      • symfony1 Legacy
    • Learn Symfony

      • Symfony Docs
      • Symfony Book
      • Reference
      • Bundles
      • Best Practices
      • Training
      • eLearning Platform
      • Certification
    • Screencasts

      • Learn Symfony
      • Learn PHP
      • Learn JavaScript
      • Learn Drupal
      • Learn RESTful APIs
    • Community

      • SymfonyConnect
      • Support
      • How to be Involved
      • Code of Conduct
      • Events & Meetups
      • Projects using Symfony
      • Downloads Stats
      • Contributors
      • Backers
    • Blog

      • Events & Meetups
      • A week of symfony
      • Case studies
      • Cloud
      • Community
      • Conferences
      • Diversity
      • Documentation
      • Living on the edge
      • Releases
      • Security Advisories
      • SymfonyInsight
      • Twig
      • SensioLabs
    • Services

      • SensioLabs services
      • Train developers
      • Manage your project quality
      • Improve your project performance
      • Host Symfony projects

      Deployed on

    Follow Symfony

    Search by Algolia