如何在Magento 2中创建自定义日志文件?


57

在Magento 1中,通常将日志分为不同的文件(将付款方式的日志分开等)。就像更改的$file参数一样简单Mage::log

Magento 2已更改为使用Monolog。

看来Monolog(或它的Magento2的实现)按严重性将整个框架的所有日志细分为处理程序。有一些写入文件的处理程序:

\Magento\Framework\Logger\Handler\Debug\Magento\Framework\Logger\Handler\Exception\Magento\Framework\Logger\Handler\System

像Magento 1一样登录到var / log中的相应文件。

我可以为特定的严重性添加处理程序(即,向发送通知var/log/notice.log)。扩展\Magento\Framework\Logger\Handler\Base并在中注册处理程序di.xml

本文大致介绍了该过程:http : //semaphoresoftware.kinja.com/how-to-create-a-custom-log-in-magento-2-1704130912

但是,如何将一个类(不是Magento的全部)的所有日志(不仅是一种严重性)写入我选择的文件中?

看来我必须创建自己的版本Magento\Framework\Logger\Monolog,但是如何使所有这些组合在一起才能真正起作用?

如果这是Magento 2中的大禁忌,那么有什么选择?我需要一些用于分隔此扩展名的日志,以便在必要时在客户端站点上对其进行调试。将该信息写入system.log,exception.log等并与其他模块的日志混杂在一起是不切实际的。

Answers:


99

您不需要自定义或尝试扩展Magento2的日志记录。就像您说的那样,它使用的是Monolog,仅进行了少量定制。编写您自己的扩展Monolog的记录器就足够了。

假设您的模块在YourNamespace/YourModule

1)在Logger/Logger.php以下位置编写Logger类:

<?php
namespace YourNamespace\YourModule\Logger;

class Logger extends \Monolog\Logger
{
}

2)在Logger/Handler.php以下位置编写Handler类:

<?php
namespace YourNamespace\YourModule\Logger;

use Monolog\Logger;

class Handler extends \Magento\Framework\Logger\Handler\Base
{
    /**
     * Logging level
     * @var int
     */
    protected $loggerType = Logger::INFO;

    /**
     * File name
     * @var string
     */
    protected $fileName = '/var/log/myfilename.log';
}

注意:这是使用Magento代码的唯一步骤。\Magento\Framework\Logger\Handler\Base扩展Monolog的内容StreamHandler,例如,在$ fileName属性前添加Magento基本路径。

3)依赖注入中的注册记录器etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
    <type name="YourNamespace\YourModule\Logger\Handler">
        <arguments>
            <argument name="filesystem" xsi:type="object">Magento\Framework\Filesystem\Driver\File</argument>
        </arguments>
    </type>
    <type name="YourNamespace\YourModule\Logger\Logger">
        <arguments>
            <argument name="name" xsi:type="string">myLoggerName</argument>
            <argument name="handlers"  xsi:type="array">
                <item name="system" xsi:type="object">YourNamespace\YourModule\Logger\Handler</item>
            </argument>
        </arguments>
    </type>
</config>

注意:这不是严格要求,但允许DI将特定的参数传递给构造函数。如果不执行此步骤,则需要调整构造函数以设置处理程序。

4)在您的Magento类中使用记录器:

这是通过依赖注入完成的。在下面,您将找到一个仅写入日志条目的虚拟类:

<?php
namespace YourNamespace\YourModule\Model;

class MyModel
{
    /**
     * Logging instance
     * @var \YourNamespace\YourModule\Logger\Logger
     */
    protected $_logger;

    /**
     * Constructor
     * @param \YourNamespace\YourModule\Logger\Logger $logger
     */
    public function __construct(
        \YourNamespace\YourModule\Logger\Logger $logger
    ) {
        $this->_logger = $logger;
    }

    public function doSomething()
    {
        $this->_logger->info('I did something');
    }
}

2
前几天我在问与一位建筑师相似的东西,所以谢谢这个例子!我想知道是否基于类名添加支持,以便DI框架可以将“正确的”记录器注入到不同的类中,并在Admin中进行切换以打开/关闭标志,而无需更改代码。这种功能对人们有多大用处?
艾伦·肯特

1
Manoj,如果您引用的模板具有带有logger的块类,则您可以编写一个公共方法,然后将消息传递给logger。您的示例无法正常运行,因为_logger受到保护(如果存在的话)
2015年

3
我认为,当前的方法比M1的方法有所退步。日志记录也应该是开发人员工具,它不仅用于监视实时应用程序。我可以看到如何创建一个可选的多功能简化库,以供开发使用,以覆盖当前实现,然后替换为生产使用
barbazul 2015年

2
@AlanKent我在这里同意barbazul的功能-能够轻松记录到您想要记录的任何文件的能力,快速指定M1中的级别非常棒。这不是那么灵活(动态),这是一个耻辱。将文件名作为默认记录器调用的参数会很好。感谢您的回答!
罗比·阿夫里尔

2
对我来说,它总是使用/var/log/system.log,为什么?
MagePsycho

20

我们可以像这样将数据记录在文件中。

$writer = new \Zend\Log\Writer\Stream(BP . '/var/log/templog.log');
$logger = new \Zend\Log\Logger();
$logger->addWriter($writer);

$logger->info("Info". $product->getSku() . "----- Id  ". $product->getId() );
$logger->info("preorder qty ". $product->getPreorderQty());

2
这是快速且容易的
PMB

9

最简单的方法:

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

6

除了Halk和Pradeep Kumar的答案之外:如果确实只需要登录到其他文件,则还有一种更简单的方法。特别是如果要将其合并到多个模块中,或者要在模块中使用不同的日志文件,则尤其如此。使用这种方法,您不必创建自定义处理程序。

假设您的模块已MyNamespace/MyModule插入,并且您要登录到自定义文件的类称为MyClass。如果该类的构造函数已经注入,请\Psr\Log\LoggerInterface跳至步骤2)。否则,您需要将其注入构造函数中:

1)在您的课程中注入LoggerInterface MyClass.php

<?php

namespace MyNamespace\MyModule;

use Psr\Log\LoggerInterface;

class MyClass
{
    /**
     * @var \Psr\Log\LoggerInterface
     */
    protected $logger;

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

如果您扩展了一个已经包含记录器的类(例如\Magento\Framework\App\Helper\AbstractHelper),则最好覆盖该成员(通常是$_logger),而不要使用单独的成员。只需$this->_logger = $logger 父构造器指令之后添加即可。

<?php

namespace MyNamespace\MyModule;

use Magento\Framework\App\Helper\Context;
use Psr\Log\LoggerInterface;

class MyClass extends \Magento\Framework\App\Helper\AbstractHelper
{
    public function __construct(
        Context $context,
        LoggerInterface $logger
    ) {
        parent::__construct(
            $context
        );

        $this->_logger = $logger;
    }
}

2)通过依赖注入配置记录器etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <virtualType name="MyNamespace\MyModule\Logger\Handler" type="Magento\Framework\Logger\Handler\Base">
        <arguments>
            <argument name="filesystem" xsi:type="object">Magento\Framework\Filesystem\Driver\File</argument>
            <argument name="fileName" xsi:type="string">/var/log/mymodule.log</argument>
        </arguments>
    </virtualType>
    <virtualType name="MyNamespace\MyModule\Logger\Logger" type="Magento\Framework\Logger\Monolog">
        <arguments>
            <argument name="name" xsi:type="string">MyModule Logger</argument>
            <argument name="handlers" xsi:type="array">
                <item name="system" xsi:type="object">MyNamespace\MyModule\Logger\Handler</item>
            </argument>
        </arguments>
    </virtualType>

    <type name="MyNamespace\MyModule\MyClass">
        <arguments>
            <argument name="logger" xsi:type="object">MyNamespace\MyModule\Logger\Logger</argument>
        </arguments>
    </type>
</config>

这会将所有内容记录到/var/log/mymodule.log

如果您需要为不同的类登录到其他文件,则只需使用另一个虚拟处理程序创建另一个虚拟记录器,然后将其注入该类即可。


5

如果仅在单个班级中需要它:

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

pushHandler没有在接口上公开方法,并且实现似乎不起作用...
George

您的Magento版本?
mshakeel

Magento CE 2.2.0
乔治

我将在CE 2.2.0上试用它,然后再回头。我在2.1
mshakeel

2

试试“ praxigento / mage2_ext_logging ”模块。该模块为Magento 2添加了“ Monolog Cascade”支持。“ Monolog Cascade”使您可以使用单个配置文件来配置日志输出。您可以将日志打印到其他文件,数据库,发送电子邮件警报等,而无需修改自己的代码。

这是配置文件的示例(默认为“ var / log / logging.yaml”):

disable_existing_loggers: true
formatters:
    dashed:
        class: Monolog\Formatter\LineFormatter
        format: "%datetime%-%channel%.%level_name% - %message%\n"
handlers:
    debug:
        class: Monolog\Handler\StreamHandler
        level: DEBUG
        formatter: dashed
        stream: /.../var/log/cascade_debug.log
    system:
        class: Monolog\Handler\StreamHandler
        level: INFO
        formatter: dashed
        stream: /.../var/log/cascade_system.log
    exception:
        class: Monolog\Handler\StreamHandler
        level: EMERGENCY
        formatter: dashed
        stream: /.../log/cascade_exception.log
processors:
    web_processor:
        class: Monolog\Processor\WebProcessor
loggers:
    main:
        handlers: [debug, system, exception]
        processors: [web_processor]

1

如果没有逻辑更改,仅需要更改自定义日志文件名,则无需创建自定义记录器类,也只需遵循以下步骤

1.在di.xml中

 <type name="Magento\Framework\Logger\Monolog">
        <arguments>
            <argument name="name" xsi:type="string">test</argument>
            <argument name="handlers"  xsi:type="array">
                <item name="test" xsi:type="object">NAME_SPACE\Test\Model\Logger\Handler\Debug</item>
            </argument>
        </arguments>
    </type>

2.处理程序

<?php
/**
 * Copyright © 2017 Alshaya, LLC. All rights reserved.
 * See LICENSE.txt for license details.
 *
 */
namespace NAME_SPACE\Test\Model\Logger\Handler;

use Magento\Framework\Logger\Handler\Base;

/**
 * Log handler for reports
 */
class Debug extends Base
{
    /**
     * @var string
     */
    protected $fileName = '/var/log/test.log';
}

您需要记录数据的位置需要调用默认PSR日志
,即

<?php
/**
 *
 * Copyright © 2013-2017 Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace NAME_SPACE\Test\Controller\Index;

use Psr\Log\LoggerInterface;
class Index extends \Magento\Framework\App\Action\Action
{


    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * Show Contact Us page
     *
     * @return void
     */


    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        LoggerInterface $logger
    ) {
        parent::__construct($context);
        $this->logger = $logger;
    }


    public function execute()
    {
        $this->logger->critical((string) 'Test');
        $this->_view->loadLayout();
        $this->_view->renderLayout();
    }
}

因此,如果需要更改系统,则上面的示例会将所有调试数据记录到test.log中,也可以在di.xml中添加以下行


0

我在第三方模块中的记录器目标代码下面尝试了此操作,我想在该模块中获取日志信息,然后将其放入custom.log文件中,检查此代码,您肯定会将日志放入自定义日志文件中。

$writer = new \Zend\Log\Writer\Stream(BP . '/var/log/custom.log');
$logger = new \Zend\Log\Logger();
$logger->addWriter($writer);
$logger->info('Your log details: ' .$variable);

如果您需要更多信息,请在这里评论,我会回复。谢谢。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.