Magento 2: Replacement for Mage::log method?
-
14-04-2021 - |
Question
In Magento 1, if you wanted to send a message to the logs, you'd use a static method on the global Mage
class.
Mage::log($message, Zend_Log::DEBUG, "my-log-file.log");
Is there an equivalent in Magento 2? I've googled through the dev docs site and haven't seen anything obvious that pops out. There's this Inchoo article, but it's from almost a year ago and so much has changed since then.
As a Magento 2 module developer, if I want to replace code like the following in Magento 1
Mage::log($message, Zend_Log::DEBUG, "my-log-file.log");
What's the bare minimum I need to do?
Solution
protected $logger;
public function __construct(\Psr\Log\LoggerInterface $logger)
{
$this->logger = $logger;
}
You use debug, exception, system for PSR Logger for example:
$this->logger->info($message);
$this->logger->debug($message);
HINT:
Don't forget to run php bin/magento setup:di:compile
OTHER TIPS
In magento2, You can also write to the logs using the Zend
library like below :
$writer = new \Zend\Log\Writer\Stream(BP . '/var/log/test.log');
$logger = new \Zend\Log\Logger();
$logger->addWriter($writer);
$logger->info('Your text message');
Edited
You can also print PHP objects and arrays like below :
$logger->info(print_r($yourArray, true));
\Magento\Framework\App\ObjectManager::getInstance()
->get(\Psr\Log\LoggerInterface::class)->debug('message');
Read about QUICK WAY to print Log in any PHP file
Read More at: blog.mageprince.com
Temporary print log with new file
$writer = new \Zend\Log\Writer\Stream(BP . '/var/log/logfile.log');
$logger = new \Zend\Log\Logger();
$logger->addWriter($writer);
$logger->info('Simple Text Log'); // Simple Text Log
$logger->info('Array Log'.print_r($myArrayVar, true)); // Array Log
Factory Method
You need to inject \Psr\Log\LoggerInterface class into constructor to call logger object
protected $_logger;
public function __construct(
...
\Psr\Log\LoggerInterface $logger
...
) {
$this->_logger = $logger;
}
public function logExample() {
//To print string Output in debug.log
$this->_logger->addDebug('Your Text Or Variables');
// To print array Output in system.log
$this->_logger->log('600', print_r($yourArray, true));
}
Or you directly use this code in phtml file:
To print string Output in debug.log
\Magento\Framework\App\ObjectManager::getInstance()
->get('Psr\Log\LoggerInterface')->debug('Your Message');
To print array Output in system.log
$myArray = array('test1'=>'123', 'test2'=>'123', 'test3'=>'123');
$level = '100'; // use one of: 100, 200, 250, 300, 400, 500, 550, 600
\Magento\Framework\App\ObjectManager::getInstance()
->get('Psr\Log\LoggerInterface')
->log($level, print_r($myArray, true));
If you want to use default logger but custom file for logging (or other custom logic) you need to use custom logger handler:
class Logger extends Magento\Framework\Logger\Handler\Base
{
/**
* @var string
*/
protected $fileName = '/var/log/my-log-file.log';
/**
* @var int
*/
protected $loggerType = MonologLogger::DEBUG;
}
Then add it as handler somewhere within your code:
protected function addCustomLogHandler()
{
$logger = Data::getCustomLogger();
if(isset($this->_logger)){
$this->_logger->pushHandler($logger);
}
}
A step back in convenience IMO
In a simple way if you don't want to create dependency injection or anything else use below code it will store log in system.log
file
$logger = \Magento\Framework\App\ObjectManager::getInstance()->get(\Psr\Log\LoggerInterface::class);
$logger->info('message');
That's all..
No, there is no direct equivalent. It's a bit complicated now.
After magento 2.3.5 we replace Zend By Laminas
You can also write to the logs using the Lamina library like below :
$writer = new \Laminas\Log\Writer\Stream(BP . '/var/log/test.log');
$logger = new \Laminas\Log\Logger();
$logger->addWriter($writer);
$logger->info('Your text message');
$data = ["test" => "testing"];
$logger->debug(var_export($data, true));
Include psr logger class in your file using use and then call addDebug()
method. This will print log message in var/log/debug.log
file
use Psr\Log\LoggerInterface;
class demo {
function demo()
{
//EDIT: Using debug instead of addDebug for PSR compatiblity
$this->_objectManager->get('Psr\Log\LoggerInterface')->debug("your message goes here");
}
}
UPDATED: 19/08/2019
If you are looking for elegant custom log handler, I recommend you to use Virtual Types (which doesn't need to add any PHP code)
Inspired from the answer of Petar Dzhambazov and halk, ladies and gentlemen I introduced you a better and shorter way instead of duplicated custom log code all the time.
StackOverflow\Example\etc\di.xml
<!-- Custom log file for StackOverflow ; Duplicate it as much as you want separate log file -->
<virtualType name="StackOverflow\Example\Model\Logger\VirtualDebug" type="Magento\Framework\Logger\Handler\Base">
<arguments>
<argument name="fileName" xsi:type="string">/var/log/stackoverflow/donald_trump.log</argument>
</arguments>
</virtualType>
<virtualType name="StackOverflow\Example\Model\Logger\VirtualLogger" type="Magento\Framework\Logger\Monolog">
<arguments>
<argument name="name" xsi:type="string">DonaldTrump</argument>
<argument name="handlers" xsi:type="array">
<item name="debug" xsi:type="object"> StackOverflow\Example\Model\Logger\VirtualDebug</item>
</argument>
</arguments>
</virtualType>
USAGE
Vendor\Something\Model\DonaldTrump.php
<?php
/**
* Copyright © 2016 Toan Nguyen <https://nntoan.github.io>. All rights reserved.
* See COPYING.txt for license details.
*
* This is the file you want to inject your custom logger.
* Of course, your logger must be an instance of \Psr\Log\LoggerInterface.
*/
namespace Vendor\Something\Model;
/**
* DonaldTrump business logic file
*
* @package Vendor\Something\Model
* @author Toan Nguyen <https://github.com/nntoan>
*/
class DonaldTrump
{
/**
* @var \Psr\Log\LoggerInterface
*/
private $logger;
/**
* DonaldTrump constructor.
*
* @param \Psr\Log\LoggerInterface $logger
*/
public function __construct(
\Psr\Log\LoggerInterface $logger,
) {
$this->logger = $logger;
}
// 1 billion lines of code after this line
}
StackOverflow\Example\etc\frontend\di.xml
<type name="Vendor\Something\Model\DonaldTrump">
<arguments>
<argument name="logger" xsi:type="object">StackOverflow\Example\Model\Logger\VirtualLogger</argument>
</arguments>
</type>
That's all, no extra PHP files or lines - use the advantages of Magento 2: Virtual Types!!!
Hope this helps ;)
There is one update for logger in 2.2. You can enable logger for production mode by run SQL:
"INSERT INTO core_config_data (scope, scope_id, path, value) VALUES ('default', '0', 'dev/debug/debug_logging', '1');"
Then you can use \Psr\Log\LoggerInterface
for print log just like above answers:
protected $logger;
public function __construct(
\Psr\Log\LoggerInterface $logger
) {
$this->logger = $logger;
}
public function yourFunction() {
$data = ["test" => "testing"];
$this->logger->debug(var_export($data, true));
}
Inject
$logger
class in constructor\Psr\Log\LoggerInterface $logger
This is achieved by passing $logger as argument.Initialize
$logger
in constructor$this->logger = $logger
In function within the class you want to log use the below line
$this->logger->debug($message); $this->logger->log($level, $message);
If you need it within your single class with custom log file:
public function __construct(\Psr\Log\LoggerInterface $logger, \Magento\Framework\App\Filesystem\DirectoryList $dir)
{
$this->logger = $logger;
$this->dir = $dir;
$this->logger->pushHandler(new \Monolog\Handler\StreamHandler($this->dir->getRoot().'/var/log/custom.log'));
}
1 line approach:
\Magento\Framework\App\ObjectManager::getInstance() ->get(\Psr\Log\LoggerInterface::class)->info('yourmessage');
magento 2 logs
you can try it...
$writer = new \Zend\Log\Writer\Stream(BP . '/var/log/test.log');
$logger = new \Zend\Log\Logger();
$logger->addWriter($writer);
$logger->info($category->getData());
Place PSR logger code in your constructor:
protected $logger;
public function __construct(\Psr\Log\LoggerInterface $logger)
{
$this->logger = $logger;
}
then you can use in your function like:
$this->logger->info($message);