143

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?

Amit Bera
  • 77,456
  • 20
  • 123
  • 237
Alana Storm
  • 44,345
  • 35
  • 168
  • 353

22 Answers22

186

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));
Manashvi Birla
  • 8,833
  • 9
  • 27
  • 53
  • 3
    @AlanStorm - Yes you can, check my updated answer.! – Manashvi Birla Dec 03 '15 at 11:05
  • 1
    @Manashvibirla I think what Alan Storm wanted to know is will the method automatically format when called as: $logger->info($someArrayOrObject); – MagePsycho Dec 09 '15 at 10:36
  • 2
    @Manashvibirla : PHP objects are not printing... – Amit Maurya Mar 01 '16 at 06:43
  • @Manashvibirla If you have to do log in windows then you have to change /(slash) like \var\log\test.log. Any way still I am using this logging method for my development purpose. thanks :) – Keyur Shah Nov 16 '16 at 09:11
  • 2
    @KeyurShah The solution was provided by keeping ubuntu in mind, as i was using ubuntu.! thanks for the feedback – Manashvi Birla Nov 16 '16 at 09:43
  • 2
    great for temp debug – Minesh Patel Feb 02 '17 at 12:58
  • 5
    Several of these answers have their place and use. Obviously this solution requires almost as much code as using DI to instantiate the standard logger -- but it's a simple in-place drop-in which lets you set your own log file.

    Sometimes it's rather annoying to search through the standard log files - which tend to get cluttered - to find your own logs. So this is a nice 'quick' solution for that.

    – Jeremy Rimpo Jul 06 '17 at 16:17
  • 1
    i was looking for something easy like this.. works great, thanks! – Kalpesh Jul 08 '17 at 18:19
  • 19
    It's king of embaressing how often I come here to copy and use this... <3 – Lez Oct 04 '19 at 19:15
  • 1
    So wrong, but sooooo good =) – medina May 03 '21 at 23:27
  • 1
    we can use as a quick solution for logging :) – amesh May 09 '21 at 11:20
  • seems like not useful in latest magento version. – Rizwan Khan Apr 08 '23 at 11:19
  • for M2.4+ use this answer: https://magento.stackexchange.com/a/355430/59493 for the modified code (or an update for this answer would be nice) – Lez Sep 08 '23 at 13:44
170
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

Sukumar Gorai
  • 10,823
  • 4
  • 19
  • 46
Pratik
  • 3,805
  • 6
  • 31
  • 49
  • 13
    +1 Thank you, that's a useful interface/class/type to know about -- but it's not clear from your answer where the information will be logged and how (if possible) to change that location. – Alana Storm Dec 03 '15 at 07:21
  • You check Manager.php for following class Magento\Framework\Event and add this line $this->logger->debug($eventName); than after refresh page and check debug.txt file you get all evant name for specific page. – Pratik Dec 03 '15 at 07:30
  • 4
    Technically, this is the 'correct' way to instantiate a logger in your own custom classes - particularly if you intend to keep it around rather than just some quick debug. However, there are several core classes - particularly Block classes - which automatically instantiate and store a _logger property. If you extend one of these core classes then there's no need to repeat the logic.

    Other answers dig into creating handlers to define your own log file, but the default logs are always /var/log/system.log or /var/log/debug.log. I believe the specific logging function determines which is used.

    – Jeremy Rimpo Jul 06 '17 at 16:11
  • 7
    For me, the "debug" level started to work only when I enabled "Log to file" in Configuration > Advanced > Developer > Debug. Using 2.2 – SlimDeluxe Nov 15 '17 at 09:45
  • Does it correspond to Magento 2.3 also? thanks in advance – Ahmed Chouihi May 18 '20 at 12:03
89
\Magento\Framework\App\ObjectManager::getInstance()
    ->get(\Psr\Log\LoggerInterface::class)->debug('message');
7ochem
  • 7,532
  • 14
  • 51
  • 80
Dmitrii Fediuk
  • 4,899
  • 2
  • 23
  • 19
  • 9
    +1 Thank you, that's a useful interface/class/type to know about -- but it's not clear from your answer where the information will be logged and how (if possible) to change that location. – Alana Storm Dec 03 '15 at 07:21
  • 1
    That's the correct answer. – medina May 23 '16 at 05:14
  • 5
    I would not advice to use the ObjectManager directly. Use DI instead – 7ochem Nov 04 '16 at 12:18
  • 16
    While I agree with @7ochem if you're creating a permanent logging function, it can be necessary to inject temporary logging into core (or third party) classes from time to time to debug issues. Going through the arduous process of adding a Logger class to the constructor is pointlessly over-complicated in these cases. For a simple, single-line debug function this is probably the best solution. However, you will have to deal with searching through the default log files to find your own debug output. – Jeremy Rimpo Jul 06 '17 at 16:02
  • Also keep in mind that there are several core classes - particularly Block classes - which have a _logger property you can access without instantiating a new copy. – Jeremy Rimpo Jul 06 '17 at 16:06
  • +1 As a Dev, I understand that I'm not to use the Obj Manager directly, but this piece of code also teaches me to get the resolved class from the interface – NathanielR Aug 05 '17 at 14:51
56

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-&gt;_logger-&gt;addDebug('Your Text Or Variables'); 

// To print array Output in system.log
$this-&gt;_logger-&gt;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));

Update: Latest Magento version:

Write logs using the Lamina library:

$writer = new \Laminas\Log\Writer\Stream(BP . '/var/log/logfile.log');
$logger = new \Laminas\Log\Logger();
$logger->addWriter($writer);
$logger->info('Simple Text Log'); // Simple Text Log
$logger->info('Array Log'.print_r($myArrayVar, true)); // Array Log
Marius
  • 197,939
  • 53
  • 422
  • 830
Prince Patel
  • 22,708
  • 10
  • 97
  • 119
14

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..

Himanshu
  • 1,761
  • 17
  • 34
14

Magento 2.4+

$writer = new \Zend_Log_Writer_Stream(BP . '/var/log/testlog.log');
$logger = new \Zend_Log();
$logger->addWriter($writer);
$logger->info('testt'); // Print string type data
$logger->info('Data::' . print_r($arrData, true)); // Print array type data
Dhara Bhatti
  • 769
  • 7
  • 22
akashmalik
  • 486
  • 3
  • 10
11

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

Petar Dzhambazov
  • 1,423
  • 13
  • 17
  • +1 Useful information, thank you! However, it's not clear how you use this logger context with the PSR-3 autoloader interface - i.e. if you're logging with $this->logger->info($message, $level); -- how do you say "use my context"? – Alana Storm Dec 03 '15 at 17:39
  • 2
    Well the thing is that all handlers that are available to Monolog are looped and first that can handle the level of record (DEBUG, INFO etc.) is used. So the only way I see to be absolutely sure that your handler is used, is to push it before you need it, so its at top of the stack and comes first in the loop. Another way would be to just SET it as handler, removing all others, but that won't be very friendly thing to do. – Petar Dzhambazov Dec 03 '15 at 18:42
  • If you try to introduce additional handlers in the 2.0.0 GA, or work with specifying the handlers in di.xml you may want to be aware of this issue https://github.com/magento/magento2/issues/2529

    I ran into this issue trying to get a custom logger to have a custom log file handle, and a custom handler that writes some entries to a database table.

    – mttjohnson Dec 07 '15 at 03:47
9

You can use this packages

composer require cleatsquad/logger

Examples

\CleatSquad\Logger::log('test', 'test.log');
\CleatSquad\Logger::log('test', 'test.log', \Monolog\Logger::WARNING);
\CleatSquad\Logger::log(['test' => 'is an array'], 'test.log');

Or you can use Laminas

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));

Mohamed El Mrabet
  • 1,522
  • 13
  • 23
7

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 ;)

Toan Nguyen
  • 3,049
  • 1
  • 24
  • 45
6

No, there is no direct equivalent. It's a bit complicated now.

See: Logging to a custom file in Magento 2

Ryan Hoerr
  • 12,271
  • 7
  • 47
  • 54
  • 2
    +1, thank you! However -- other answers make it sound like there may be a single logger, and the extend/create a handle approach is no longer necessary. Do you know if that's true? – Alana Storm Dec 03 '15 at 07:22
5

for magento 2.3.4 you can use :

$writer = new \Zend_Log_Writer_Stream(BP . '/var/log/custom.log');
$logger = new \Zend_Log();
$logger->addWriter($writer);
$logger->info('text message');
4

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");
  }

}
medmek
  • 594
  • 7
  • 20
chirag dodia
  • 2,122
  • 4
  • 25
  • 35
3
$writer = new \Zend\Log\Writer\Stream(BP . '/var/log/test.log');
$logger = new \Zend\Log\Logger();
$logger->addWriter($writer);
$logger->info('Your text message');
Puneet
  • 101
  • 6
3

You can use several formats.

Default logger

1: In Magento default format

protected $_logger;
public function __construct(
    ...
    \Psr\Log\LoggerInterface $logger
    ...
) {
    $this->_logger = $logger;
}

public function logExample() {

//To print string Output in debug.log
$this-&gt;_logger-&gt;addDebug('Your Text Or Variables'); 

// To print array Output in system.log
$this-&gt;_logger-&gt;log('600', print_r($yourArray, true));

}

Custom logger

2: This will work with the older version of Magento 2.4.3:

$writer = new \Zend\Log\Writer\Stream(BP . '/var/log/test.log');
$logger = new \Zend\Log\Logger();
$logger->addWriter($writer);
$logger->info('Your text message');
$logger->info('getAllowProducts'.print_r($subject->getAllowProducts(), true));

3: This will work with the newest Magento 2.4.3+:

$writer = new \Zend_Log_Writer_Stream(BP . '/var/log/custom.log');
$logger = new \Zend_Log();
$logger->addWriter($writer);
$logger->info('Your text message');
$logger->info('getAllowProducts'.print_r($subject->getAllowProducts(), true));
Baharuni Asif
  • 1,217
  • 9
  • 26
Rafiqul Islam
  • 471
  • 4
  • 8
3

Magento 2 ( 2.4.X ) - Magento 2 logs - Magento 2 default logs

$writer = new \Zend_Log_Writer_Stream(BP . '/var/log/testlog-thala-vkk.log');
$logger = new \Zend_Log();
$logger->addWriter($writer);
$logger->info('testt'); // Print string type data
$logger->info('Data::' . print_r($arrData, true)); // Print array type data
1
  1. Inject $logger class in constructor \Psr\Log\LoggerInterface $logger
    This is achieved by passing $logger as argument.

  2. Initialize $logger in constructor

    $this->logger = $logger
    
  3. In function within the class you want to log use the below line

    $this->logger->debug($message);
    $this->logger->log($level, $message);
    
7ochem
  • 7,532
  • 14
  • 51
  • 80
Oscprofessionals
  • 1,795
  • 9
  • 20
1

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'));
}
mshakeel
  • 528
  • 9
  • 12
1

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));
}
Yogesh Karodiya
  • 3,101
  • 4
  • 19
  • 42
  • 1
    thanks, and you can also use this instead of QUERY SQL: In the Magento admin panel, go to "Stores" -> "Configuration" -> "Advanced" -> "Developer" -> "Debug" -> "Log to File". Setting this to "Yes" will cause debug information to be logged to var/log/debug.log in your Magento application directory. – fudu Oct 31 '18 at 03:47
1

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());

Sudip Jeet
  • 41
  • 2
1

For me in M2.3.4, this is the one-liner that works and allows me to log into any file:

(new \Zend_Log())->addWriter(new \Zend_Log_Writer_Stream(BP . '/var/log/custom.log'))->info(print_r($foo, true));

Though I am not sure if the Zend_Log_Writer_Stream is coming from my environment or from Magento, so just try it out.

Louis B.
  • 1,111
  • 1
  • 11
  • 35
0

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);
0

1 line approach:

\Magento\Framework\App\ObjectManager::getInstance() ->get(\Psr\Log\LoggerInterface::class)->info('yourmessage');

Mukesh Pandit
  • 169
  • 1
  • 7