How to write log to custom files in Magento 2

Likes (2)   Dislikes (0)  
  (2 reviews)

Logging is a very important aspect of any programming language. Logs help us debug our code and finally identify issues in it. We do write logs to keep track of things, to debug our code and to report errors in any programming language. Magento 2 provided us a great logging library from PSR. But this logging system is limited to write logs to predefined files. Finding important log information in predefined files is little bit difficult as they grow in size quite fast. The solution is to create our own custom logger instances and to create custom log files of our choice. With this approach our logs will be scattered in different files with easily identifiable file names.

Using PSR logging library we can do all different types of logging as mentioned below.

  • Emergency Logging (System is unusable)
  • Alert Logging (Action must be taken immediately)
  • Critical Logging (Critical condition)
  • Error Logging (Runtime errors that should not be taken care immediately but should typically be logged and monitored)
  • Warning Logging (Exceptional occurrences that are not errors)
  • Notice Logging (Normal but yet significant events)
  • Info Logging (Interesting events)
  • Debug Logging (Detailed debug information)

Monolog is another PHP logging library based on top of the PSR logger interface. Monolog has provided a variety of different log handlers to be able to log into different systems or locations. Below is a list of built in handlers.

  • Redis Handler
  • System Log UDP Handler
  • System Log Handler
  • Process Handler
  • PHP Console Handler
  • Loggly Handler
  • Stream Handler
  • and the list goes on

For the full list of Log Handlers by Monolog refer to this page.

That is enough theory and history on Monolog. Let’s come to the point “How can we log into our own custom files?

Define a Custom Logger using Magento 2 Virtual Type

Magento 2 core uses this method to create custom logger whenever required. If you look into the Magento 2.4.5 Adobe Ims module you will find the core Magento 2 example. Have not used virtual type before in Magento 2 or don’t have proper idea on Magento 2 Virtual Types? See this article get idea on Magento 2 Virtual Type.

Steps to create a custom logger with a custom log file.

  1. Define a log handler, a virtual type of class Magento\Framework\Logger\Handler\Base, and set the filename argument.
  2. Create a custom logger class file that extends base logger class from Monolog.
  3. Attach the newly created virtual log handler to the custom logger class.
  4. Use your custom logger wherever required with constructor injection.
  5. Run Magento 2 compilation command to generate everything.

Required XML Configuration

Let’s define the virtual type for the class Magento\Framework\Logger\Handler\Base. The Base log handler class constructor require a filename argument of type string. This argument we can provide in the arguments section of the virtual type declaration.

company/module/etc/di.xml
<virtualType name="TrainingCoreLogHandler" type="Magento\Framework\Logger\Handler\Base">
    <arguments>
        <argument name="fileName" xsi:type="string">/var/log/training_core.log</argument>
    </arguments>
</virtualType>
<type name="Training\Core\Logger\ExampleTrainingLogger">
    <arguments>
        <argument name="name" xsi:type="string">example_training_logger</argument>
        <argument name="handlers" xsi:type="array">
            <item name="training_core_logger" xsi:type="object">TrainingCoreLogHandler</item>
        </argument>
    </arguments>
</type>

The main logger class requires a name argument of type string and a handlers argument of type array. For the name argument we can give anything that we think is meaningful. And for the handlers we have to add an item and link the previously defined virtual type.

Custom Logger Class Definition

Our custom logger class has to extend \Monolog\Logger. That’s all least requirement for our custom logger class. If we check the base class \Monolog\Logger and it’s constructor arguments, we will notice the 2 arguments that we have declared in the di.xml configuration file.

PHP
<?php

namespace Training\Core\Logger;

use Monolog\Logger;

class ExampleTrainingLogger extends Logger
{
}

We are now done with the coding of our own custom logger class that will log into a specific filename that we have decided. Now let’s use this new logger class with constructor dependency injection.

PHP
<?php

namespace Training\Core\Model\Quote\Address\Total;

use Magento\Quote\Model\Quote\Address\Total\AbstractTotal;
use Training\Core\Logger\ExampleTrainingLogger;

class FragileCare extends AbstractTotal
{
    private ExampleTrainingLogger $logger;

    public function __construct(
        ExampleTrainingLogger $logger
    )
    {
        $this->logger = $logger;
    }

    /**
     * Collect Fragile Care Fee For Quote
     *
     * @param \Magento\Quote\Model\Quote $quote
     * @param \Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment
     * @param Address\Total $total
     * @return $this
     */
    public function collect(
        \Magento\Quote\Model\Quote $quote,
        \Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment,
        \Magento\Quote\Model\Quote\Address\Total $total
    ) {
        parent::collect($quote, $shippingAssignment, $total);

        $code = 'fragile_care';
        $amount = 3.7;

        $this->logger->info(__METHOD__, ['code' => $code, 'amount' => $amount]);
        $this->logger->debug(__METHOD__, ['code' => $code, 'amount' => $amount]);

        $total->setTotalAmount($code, $amount);
        $total->setBaseTotalAmount($code, $amount);

        return $this;
    }
}

After everything is done in coding part, we have to run bin/magento setup:di:compile to generate the things that we have defined in the di.xml file.

Conclusion

Using this technique we can define our own custom log handler that we can use with our custom logger class. The handlers argument is an array but I think we should set only one log handler in the logger class. Cause I don’t know how the logger class will decide which log handler to use for a log command. Happy logging! and share your thought in the comment section below.

Leave a Comment

Share via
Copy link
Powered by Social Snap