Magento 2 logging

magento-2_logging_with_monolog_library

In every development process you sometimes need to log variables or custom messages. Now, we will explain how to create a custom log. Magento 2 comes with built-in log facility which is based on Monolog library. You can find this package in the following location: “MAGENTO2_ROOT/vendor/monolog“.

The main Magento 2 log facility class is “Magento\Framework\Logger\Monolog, and this is defined in “MAGENTO2_ROOT/app/etc/di.xml” as:

<preference for="Psr\Log\LoggerInterface" type="Magento\Framework\Logger\Monolog" />

You can see that this class extends class “Monolog\Logger” from monolog package.

<?php
/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
 
namespace Magento\Framework\Logger;
 
use Monolog\Logger;
 
class Monolog extends Logger
{
}

In class “Monolog\Logger” there are a couple of interesting methods for creating logs.
These methods accept two arguments, the first argument is message (string) and the second one is optional array parameter (you can pass instance of object).

Some methods:

$this->_logger->addDebug($message); // log location: var/log/system.log
$this->_logger->addInfo($message); // log location: var/log/exception.log
$this->_logger->addNotice($message); // log location: var/log/exception.log
$this->_logger->addError($message); // log location: var/log/exception.log
$this->_logger->critical($e); // log location: var/log/exception.log

One useful example for logging php exception:

In Magento 1 we are using static method

Mage::logException($e);

In Magento 2 we are using an instance of “Magento\Framework\Logger\Monolog” and method “critical” for logging exception from try-catch

$this->_logger->critical($e);
// instance of $e will be converted to string (magic metod __toString() will be called).

Let’s start with an example of how to get instance of Magento\Framework\Logger\Monolog in your class.

Magento 2 uses dependency injection and all instances of classes come through class constructor.
If you want to use object “Magento\Framework\Logger\Monolog” then the instance should be passed through constructor of your class.

Example of this code is shown below:

<?php
namespace Inchoo\Test\Model;
 
class Example{
    protected $_logger;
    public function __construct(
        \Psr\Log\LoggerInterface $logger, //log injection
        array $data = []
    ) {
        $this->_logger = $logger;
        parent::__construct($data);
    }
    public function someExampleMethod() {
        /*
        some logic of method
        */
        //accessing to logger instance and calling log method
        $this->_logger->addDebug('some text or variable');
    }
}

You can see that we passed “\Psr\Log\LoggerInterface $logger” in class through constructor in order to be able to use log object in this class.
After that we can use instance “$this->_logger” in class “Inchoo\Test\Model\Example“.

If you want to write a log in your custom file name, in a custom location, then the process is not that simple :-), you will have to create a custom Log handler.

Main Magento 2 log class has three handlers which are defined in the same “MAGENTO2_ROOT/app/etc/di.xml” file. These handlers are: exception, system and debug.

<type name="Magento\Framework\Logger\Monolog">
        <arguments>
            <argument name="name" xsi:type="string">main</argument>
            <argument name="handlers"  xsi:type="array">
                <item name="exception" xsi:type="object">Magento\Framework\Logger\Handler\Critical</item>
                <item name="system" xsi:type="object">Magento\Framework\Logger\Handler\System</item>
                <item name="debug" xsi:type="object">Magento\Framework\Logger\Handler\Debug</item>
            </argument>
        </arguments>
</type>

In some classes we don’t need to pass log object through constructor, because the log object already exists.
For example, we have this situation on every html block class which extends “\Magento\Framework\View\Element\Template” or in model class which extends “\Magento\Framework\Model\AbstractModel“.

These “parent” classes have already property “$_logger” instance of: Magento\Framework\Logger.

And there you go – I hope you’ll find this quick overview of Magento 2 logging and some customization options around it useful.


About Domagoj Potkoc

Backend Developer

Domagoj is Magento Certified Developer who enjoys playing tennis after long hours in front of computer screen.

Read more posts by Domagoj / Visit Domagoj's profile

7 comments

  1. >>If you want to write a log in your custom file name, in a custom location, then the process is not that simple :-), you will have to create a custom Log handler.

    There is exist other way for doing this , for example you can just use StreamHandler and add it as handler for new instance in your helper ex. :

        /**
         * @var LoggerInterface
         */
        protected $_log;
    
    public function __construct(...,\Psr\Log\LoggerInterface $logLogger)
    {
            $this->_log = $logLogger;
            $this->_log->pushHandler( new \Monolog\Handler\StreamHandler( '/path/to/file.log'));
            $this->_log->debug('message');
    }
  2. Hi Domgoj, good article if you create a model type.
    What about if you want a logger inside an object where you don’t get the instance of logger in the construct passed as a param!?

  3. After testing arround I see that the _logger object is not available, if i extend \Magento\Framework\Model\AbstractModel, bacause its protected.

    So I have to pass the logger object through the constructor and save it in a local property?

  4. Hi Domagoj Potkoc,
    We changed some functionality in our logger. We remove Critical handler. Now all message with level from Alert to Info are writing to system.log file. Debug message are writing to debug.log. But we change some functionality in Magento\Framework\Logger\Handler\System, now if you sand Exception object to method alert, error, critical, notice, info, or any other method from Psr\Log\LoggerInterface except debug, your message will be write in exception.log.

    Please don’t use method “addDebug”. Better way use method “debug”, because Psr\Log\LoggerInterface doesn’t contain method “addDebug” and 3rd party developer can change Monolog\Logger for any other solution implements Psr\Log\LoggerInterface.

    Thanks for you article.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <blockquote cite=""> <code> <del datetime=""> <em> <s> <strike> <strong>. You may use following syntax for source code: <pre><code>$current = "Inchoo";</code></pre>.