Magento 2:替换为Mage :: log方法?


105

在Magento 1中,如果要将消息发送到日志,则可以在全局Mage类上使用静态方法。

Mage::log($message, Zend_Log::DEBUG, "my-log-file.log");

Magento 2中有等同功能吗?我已经在开发文档网站上搜索了Google,却没有发现任何明显的弹出信息。有此Inchoo文章,但这是从一年前开始的,此后发生了很大变化。

作为Magento 2模块开发人员,如果我想替换Magento 1中的以下代码

Mage::log($message, Zend_Log::DEBUG, "my-log-file.log");

我需要做的最低限度是什么?

Answers:


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

您可以将调试,异常,系统用于PSR Logger,例如:

$this->logger->info($message);
$this->logger->debug($message);

9
+1谢谢,这是一个有用的界面/类/类型,但是您的答案尚不清楚该信息将记录在哪里以及如何(如果可能)更改该位置。
艾伦·风暴

您检查Manager.php中是否包含以下类Magento \ Framework \ Event,并添加以下行$ this-> logger-> debug($ eventName); 然后刷新页面并检查debug.txt文件,即可获得特定页面的所有有效名称。
Pratik

2
从技术上讲,这是在您自己的自定义类中实例化记录器的“正确”方法-特别是如果您打算保留它而不是仅仅进行一些快速调试。但是,有几个核心类(尤其是Block类)可以自动实例化并存储_logger属性。如果扩展这些核心类之一,则无需重复逻辑。其他答案涉及创建处理程序以定义您自己的日志文件,但是默认日志始终为/var/log/system.log或/var/log/debug.log。我相信特定的日志记录功能会确定使用哪个。
杰里米·林波'17

7
对我来说,只有在配置>高级>开发人员>调试中启用“登录到文件”时,“调试”级别才开始起作用。使用2.2
Omer Sabic

121

在magento2中,您还可以使用以下Zend库来写入日志:

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

已编辑

您还可以打印PHP对象和数组,如下所示:

$logger->info(print_r($yourArray, true));

7
+1有用-您知道Zend logger是否会自动格式化PHP数组/对象等吗?
艾伦·风暴

1
@AlanStorm-是的,可以,检查我的最新答案。
Manashvi Birla

2
@Manashvibirla:PHP objects不打印...
zed Blackbeard

1
@KeyurShah该解决方案是通过牢记ubuntu来提供的,就像我在使用ubuntu一样。感谢您的反馈
Manashvi Birla

3
这些答案中的几个都有其位置和用途。显然,此解决方案所需的代码几乎与使用DI实例化标准记录器所需的代码相同-但这是一个简单的就地插入方式,可让您设置自己的日志文件。有时,搜索标准日志文件(通常会很混乱)以查找自己的日志会很烦人。因此,这是一个不错的“快速”解决方案。
杰里米·林波'17

56
\Magento\Framework\App\ObjectManager::getInstance()
    ->get(\Psr\Log\LoggerInterface::class)->debug('message');

6
+1谢谢,这是一个有用的界面/类/类型,但是您的答案尚不清楚该信息将记录在哪里以及如何(如果可能)更改该位置。
艾伦·风暴

1
那是正确的答案。
麦地那

4
我不建议直接使用ObjectManager。改为使用DI
7ochem '16

12
我同意@ 7ochem,如果您要创建永久日志记录功能,则可能需要不时地将临时日志记录注入核心(或第三方)类中,以调试问题。在这些情况下,经历繁琐的将Logger类添加到构造函数的过程毫无意义地过于复杂。对于简单的单行调试功能,这可能是最佳解决方案。但是,您将不得不搜索默认的日志文件以查找自己的调试输出。
杰里米·林波'17

还请记住,有几个核心类(尤其是Block类)具有_logger属性,您可以在不实例化新副本的情况下对其进行访问。
杰里米·林波'17

28

带有新文件的临时打印日志

$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

工厂方法

您需要将\ Psr \ Log \ LoggerInterface类注入构造函数以调用logger对象

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

}

或者您直接在phtml文件中使用此代码:

在debug.log中打印字符串Output

\Magento\Framework\App\ObjectManager::getInstance()
   ->get('Psr\Log\LoggerInterface')->debug('Your Message');

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

10

如果要使用默认记录器,但要使用自定义文件进行记录(或其他自定义逻辑),则需要使用自定义记录器处理程序:

class Logger extends Magento\Framework\Logger\Handler\Base
{
  /**
   * @var string
   */
  protected $fileName = '/var/log/my-log-file.log';

  /**
   * @var int
   */
  protected $loggerType = MonologLogger::DEBUG;
}

然后将其添加为代码中的处理程序:

protected function addCustomLogHandler()
{
    $logger = Data::getCustomLogger();
    if(isset($this->_logger)){
        $this->_logger->pushHandler($logger);
    }
}

IMO便利性退后一步


+1有用的信息,谢谢!但是,尚不清楚如何在PSR-3自动加载器界面上使用此记录器上下文-即,如果要使用它进行记录$this->logger->info($message, $level);-怎么说“使用我的上下文”?
艾伦·风暴

2
事实是,Monolog可用的所有处理程序都是循环的,并且首先使用可以处理记录级别(DEBUG,INFO等)的处理程序。因此,我认为唯一可以确定使用处理程序的唯一方法是在需要它之前将其推送,因此它位于堆栈的顶部,并且在循环中排在首位。另一种方法是将其设置为处理程序,删除所有其他处理程序,但这并不是一件很友好的事情。
Petar Dzhambazov

如果您尝试在2.0.0 GA中引入其他处理程序,或者在di.xml中指定处理程序,则可能需要了解此问题github.com/magento/magento2/issues/2529 我在尝试中遇到了此问题使自定义记录器具有自定义日志文件句柄,以及使某些条目写入数据库表的自定义处理程序。
mttjohnson

9

如果您不想创建依赖项注入或其他任何使用下面的代码的简单方法,它将日志存储在system.log文件中

$logger = \Magento\Framework\App\ObjectManager::getInstance()->get(\Psr\Log\LoggerInterface::class);
$logger->info('message');

就这样..



4

使用然后在调用addDebug()方法中将psr记录器类包括在文件中。这将在var/log/debug.log文件中打印日志消息

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

}

2
您不应该ujse addDebug,因为它与psr logger不兼容。使用调试来代替。
Maciej Paprocki '16

4

更新:19/08/2019

如果您正在寻找优雅的自定义日志处理程序,则建议您使用虚拟类型(不需要添加任何PHP代码)

女士们,先生们,从Petar Dzhambazovhalk的答案中得到启发,我向您介绍了一种更好,更短的方法,而不是一直重复自定义日志代码。

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>

用法

供应商\ 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>

就是这样,没有多余的PHP文件或线-发挥Magento 2的优势:虚拟类型!!!

希望这可以帮助 ;)


3
这段代码是否实现了PSI?(政治声明注入):P
7ochem '17

1
@ 7ochem哦,是的,它是:v
Toan Nguyen

2

2.2中的记录器有一个更新。您可以通过运行SQL为生产模式启用记录器:

 "INSERT INTO core_config_data (scope, scope_id, path, value) VALUES ('default', '0', 'dev/debug/debug_logging', '1');"

然后,您可以\Psr\Log\LoggerInterface 像上面的答案一样使用打印日志:

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

谢谢,您也可以使用它代替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

1
  1. $logger在构造函数中注入类\Psr\Log\LoggerInterface $logger
    这是通过传递$ logger作为参数来实现的。

  2. $logger在构造函数中初始化

    $this->logger = $logger
  3. 在要记录的类中的函数中,使用以下行

    $this->logger->debug($message);
    $this->logger->log($level, $message);

1

如果您需要在带有自定义日志文件的单个类中使用它:

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

0

将PSR记录器代码放入构造函数中:

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

那么您可以在函数中使用如下代码:

$this->logger->info($message);
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.