Logging in Magento 2

Logging in Magento 2 has changed since the days of Magento 1.

In earlier versions of Magento, to log data to a file, you had to use the static log() or logException() method of the Mage.php class, which would either write data to the system.log, exception.log, or custom log files defined as an argument within the method.

Mage::log($someData, null, 'logfile.log', true);

This has now changed in Magento 2. One of the logger classes available is Magento\Framework\Logger\Monolog.

This class extends the Monolog\Logger class and contains methods for adding log information.

/**
 * Adds a log record at the DEBUG level.
 *
 * @param  string  $message The log message
 * @param  array   $context The log context
 * @return Boolean Whether the record has been processed
 */
public function addDebug($message, array $context = array())
{
    return $this->addRecord(static::DEBUG, $message, $context);
}

/**
 * Adds a log record at the INFO level.
 *
 * @param  string  $message The log message
 * @param  array   $context The log context
 * @return Boolean Whether the record has been processed
 */
public function addInfo($message, array $context = array())
{
    return $this->addRecord(static::INFO, $message, $context);
}

Magento 2 complies with the PSR-3 standard, and therefore to start working with a logger you need to pass in the class as an argument to the __construct() magic method of your given class.

For example, the below code passes in the Psr\Logger\LoggerInterface class.

<?php
namespace Siphor\Test\Model;

use Psr\Log\LoggerInterface;
 
class Example {
    protected $_logger;
    public function __construct(
        LoggerInterface $logger,
        array $data = []
    ) {
        $this->_logger = $logger;
        parent::__construct($data);
    }
    public function someMethod() {
        $this->_logger->addDebug('Some debug text or variable');
    }
}

There are other log levels in addition to addInfo() and addDebug().

protected static $levels = array(
    100 => 'DEBUG',
    200 => 'INFO',
    250 => 'NOTICE',
    300 => 'WARNING',
    400 => 'ERROR',
    500 => 'CRITICAL',
    550 => 'ALERT',
    600 => 'EMERGENCY',
);

Should you need to temporarily debug an existing Magento class, you can use the logger instance within these classes.

Helper classes that extend the Magento\Framework\App\Helper\AbstractHelper class will have access to a logger instance, which can be accessed straight away using $this->_logger.

<?php
namespace Magento\Framework\App\Helper;

/**
 * Abstract helper
 *
 * @SuppressWarnings(PHPMD.NumberOfChildren)
 */
abstract class AbstractHelper
{
    ....

    /**
     * @var \Psr\Log\LoggerInterface
     */
    protected $_logger;

    ....

    /**
     * @param Context $context
     */
    public function __construct(Context $context)
    {
        $this->_moduleManager = $context->getModuleManager();
        $this->_logger = $context->getLogger();
        $this->_request = $context->getRequest();
        $this->_urlBuilder = $context->getUrlBuilder();
        $this->_httpHeader = $context->getHttpHeader();
        $this->_eventManager = $context->getEventManager();
        $this->_remoteAddress = $context->getRemoteAddress();
        $this->_cacheConfig = $context->getCacheConfig();
        $this->urlEncoder = $context->getUrlEncoder();
        $this->urlDecoder = $context->getUrlDecoder();
        $this->scopeConfig = $context->getScopeConfig();
    }

    ....

}

Unlike Magento 1, logging in Magento 2 does not provide you with the ability to alter the names of the system and exception log files within the admin area.

Instead, Magento 2 provides three default logger handler classes.

  • Magento\Framework\Logger\Handler\Debug.php – when you use the debug level, logs will be written to /var/log/debug.log.
  • Magento\Framework\Logger\Handler\Exception.php – when you use the exception level, logs will be written to /var/log/exception.log.
  • Magento\Framework\Logger\Handler\System.php – when you use the system level, logs will be written to /var/log/system.log.

Other Magento classes will also pass in a logger instance within their __construct() method, such as the Onepage model class below.

<?php
namespace Magento\Checkout\Model\Type;

....

class Onepage
{
    ....
    public function __construct(
        \Magento\Framework\Event\ManagerInterface $eventManager,
        \Magento\Checkout\Helper\Data $helper,
        \Magento\Customer\Model\Url $customerUrl,
        \Psr\Log\LoggerInterface $logger,
        \Magento\Checkout\Model\Session $checkoutSession,
        \Magento\Customer\Model\Session $customerSession,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\App\RequestInterface $request,
        \Magento\Customer\Model\AddressFactory $customrAddrFactory,
        \Magento\Customer\Model\FormFactory $customerFormFactory,
        \Magento\Customer\Model\CustomerFactory $customerFactory,
        \Magento\Sales\Model\OrderFactory $orderFactory,
        \Magento\Framework\DataObject\Copy $objectCopyService,
        \Magento\Framework\Message\ManagerInterface $messageManager,
        \Magento\Customer\Model\Metadata\FormFactory $formFactory,
        CustomerDataFactory $customerDataFactory,
        \Magento\Framework\Math\Random $mathRandom,
        \Magento\Framework\Encryption\EncryptorInterface $encryptor,
        AddressRepositoryInterface $addressRepository,
        AccountManagementInterface $accountManagement,
        OrderSender $orderSender,
        CustomerRepositoryInterface $customerRepository,
        \Magento\Quote\Api\CartRepositoryInterface $quoteRepository,
        \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter,
        \Magento\Quote\Api\CartManagementInterface $quoteManagement,
        \Magento\Framework\Api\DataObjectHelper $dataObjectHelper,
        \Magento\Quote\Model\Quote\TotalsCollector $totalsCollector
    ) {
        $this->_eventManager = $eventManager;
        $this->_customerUrl = $customerUrl;
        $this->_helper = $helper;
        $this->_checkoutSession = $checkoutSession;
        $this->_customerSession = $customerSession;
        $this->_logger = $logger;
        $this->_storeManager = $storeManager;
        $this->_request = $request;
        $this->_customrAddrFactory = $customrAddrFactory;
        $this->_customerFormFactory = $customerFormFactory;
        $this->_customerFactory = $customerFactory;
        $this->_orderFactory = $orderFactory;
        $this->_objectCopyService = $objectCopyService;
        $this->messageManager = $messageManager;
        $this->_formFactory = $formFactory;
        $this->customerDataFactory = $customerDataFactory;
        $this->mathRandom = $mathRandom;
        $this->_encryptor = $encryptor;
        $this->addressRepository = $addressRepository;
        $this->accountManagement = $accountManagement;
        $this->orderSender = $orderSender;
        $this->customerRepository = $customerRepository;
        $this->quoteRepository = $quoteRepository;
        $this->extensibleDataObjectConverter = $extensibleDataObjectConverter;
        $this->quoteManagement = $quoteManagement;
        $this->dataObjectHelper = $dataObjectHelper;
        $this->totalsCollector = $totalsCollector;
    }
    ....
}

So if you extend any of these in-built classes that inject the Logger class, you do not have to pass it in yourself and logging in Magento 2 can be achieved easily.

Note: This article is based on Magento Community/Open Source version 2.1.