Magento 2: ¿Reemplazo para el método Mage :: log?

105

En Magento 1, si quisiera enviar un mensaje a los registros, utilizaría un método estático en la Mageclase global .

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

¿Hay un equivalente en Magento 2? He buscado en Google el sitio de documentos de desarrollo y no he visto nada obvio que salga a la luz. Existe este artículo de Inchoo , pero es de hace casi un año y mucho ha cambiado desde entonces.

Como desarrollador de módulos de Magento 2, si quiero reemplazar un código como el siguiente en Magento 1

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

¿Qué es lo mínimo que necesito hacer?

Alan Storm
fuente

Respuestas:

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

Utiliza depuración, excepción, sistema para PSR Logger, por ejemplo:

$this->logger->info($message);
$this->logger->debug($message);
Pratik
fuente
99
+1 Gracias, esa es una interfaz / clase / tipo útil para conocer, pero no está claro en su respuesta dónde se registrará la información y cómo (si es posible) cambiar esa ubicación.
Alan Storm
Verifica Manager.php para la siguiente clase Magento \ Framework \ Event y agrega esta línea $ this-> logger-> debug ($ eventName); que después de actualizar la página y verificar el archivo debug.txt, obtienes todos los nombres de evant para una página específica.
Pratik
2
Técnicamente, esta es la forma 'correcta' de crear instancias de un registrador en sus propias clases personalizadas, especialmente si tiene la intención de mantenerlo en lugar de solo una depuración rápida. Sin embargo, hay varias clases principales, particularmente clases de Bloque, que crean instancias y almacenan automáticamente una propiedad _logger. Si extiende una de estas clases principales, entonces no hay necesidad de repetir la lógica. Otras respuestas profundizan en la creación de controladores para definir su propio archivo de registro, pero los registros predeterminados son siempre /var/log/system.log o /var/log/debug.log. Creo que la función de registro específica determina cuál se utiliza.
Jeremy Rimpo
77
Para mí, el nivel de "depuración" comenzó a funcionar solo cuando habilité "Iniciar sesión en el archivo" en Configuración> Avanzado> Desarrollador> Depurar. Uso de 2.2
Omer Sabic
122

En magento2, también puede escribir en los registros utilizando la Zendbiblioteca como se muestra a continuación:

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

Editado

También puede imprimir objetos PHP y matrices como a continuación:

$logger->info(print_r($yourArray, true));
Manashvi Birla
fuente
77
+1 Útil: ¿sabe si Zend logger formateará automáticamente matrices / objetos PHP, etc.?
Alan Storm
1
@AlanStorm: sí, puedes consultar mi respuesta actualizada.
Manashvi Birla
2
@Manashvibirla: PHP objectsno están imprimiendo ...
zed Blackbeard
3
Varias de estas respuestas tienen su lugar y uso. Obviamente, esta solución requiere casi tanto código como usar DI para crear una instancia del registrador estándar, pero es un simple drop-in que le permite configurar su propio archivo de registro. A veces es bastante molesto buscar en los archivos de registro estándar, que tienden a estar desordenados, para encontrar sus propios registros. Así que esta es una buena solución 'rápida' para eso.
Jeremy Rimpo
2
Es el rey de la vergüenza con qué frecuencia vengo aquí para copiar y usar esto ... <3
Lez
56
\Magento\Framework\App\ObjectManager::getInstance()
    ->get(\Psr\Log\LoggerInterface::class)->debug('message');
Mage2.PRO
fuente
66
+1 Gracias, esa es una interfaz / clase / tipo útil para conocer, pero no está claro en su respuesta dónde se registrará la información y cómo (si es posible) cambiar esa ubicación.
Alan Storm
1
Esa es la respuesta correcta.
medina
44
No recomendaría usar ObjectManager directamente. Utilice DI en su lugar
7ochem
12
Si bien estoy de acuerdo con @ 7ochem si está creando una función de registro permanente, puede ser necesario inyectar el registro temporal en las clases principales (o de terceros) de vez en cuando para solucionar problemas. Pasar por el arduo proceso de agregar una clase Logger al constructor es innecesariamente demasiado complicado en estos casos. Para una función simple de depuración de una sola línea, esta es probablemente la mejor solución. Sin embargo, tendrá que lidiar con la búsqueda a través de los archivos de registro predeterminados para encontrar su propia salida de depuración.
Jeremy Rimpo
También tenga en cuenta que hay varias clases principales, particularmente clases de bloque, que tienen una propiedad _logger a la que puede acceder sin crear una nueva copia.
Jeremy Rimpo
28

Registro de impresión temporal con nuevo archivo

$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

Método de la fábrica

Es necesario inyectar \ Psr \ Log \ LoggerInterface clase en el constructor para llamar objeto registrador

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

}

O utiliza directamente este código en el archivo phtml:

Para imprimir la salida de cadena en debug.log

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

Para imprimir la salida de la matriz en 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));
Príncipe Patel
fuente
10

Si desea utilizar el registrador predeterminado pero el archivo personalizado para el registro (u otra lógica personalizada), debe usar el controlador de registrador personalizado:

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

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

Luego agréguelo como controlador en algún lugar dentro de su código:

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

Un paso atrás en conveniencia IMO

Petar Dzhambazov
fuente
+1 Información útil, gracias! Sin embargo, no está claro cómo usa este contexto de registrador con la interfaz del cargador automático PSR-3, es decir, si está iniciando sesión $this->logger->info($message, $level);, ¿cómo dice "usar mi contexto"?
Alan Storm
2
Bueno, la cosa es que todos los controladores que están disponibles para Monolog están en bucle y primero se puede usar el nivel de registro (DEBUG, INFO, etc.). Entonces, la única forma en que veo que estoy absolutamente seguro de que se usa su controlador es presionarlo antes de que lo necesite, por lo que está en la parte superior de la pila y viene primero en el bucle. Otra forma sería simplemente CONFIGURARLO como controlador, eliminando todos los demás, pero eso no será algo muy amigable.
Petar Dzhambazov
Si intenta introducir controladores adicionales en el 2.0.0 GA, o trabaja con la especificación de los controladores en di.xml, es posible que desee conocer este problema github.com/magento/magento2/issues/2529 Me encontré con este problema intentando para obtener un registrador personalizado para tener un identificador de archivo de registro personalizado y un controlador personalizado que escribe algunas entradas en una tabla de base de datos.
mttjohnson
9

De una manera simple, si no desea crear una inyección de dependencia o cualquier otra cosa que use el código siguiente, almacenará el system.logarchivo de registro

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

Eso es todo..

Himanshu
fuente
5

No, no hay equivalente directo. Es un poco complicado ahora.

Ver: Iniciar sesión en un archivo personalizado en Magento 2

Ryan Hoerr
fuente
1
+1, gracias! Sin embargo, otras respuestas hacen que parezca que puede haber un solo registrador, y el enfoque de extender / crear un identificador ya no es necesario. ¿Sabes si eso es verdad?
Alan Storm
4

Incluya la clase psr logger en su archivo usando use y luego llame al addDebug()método. Esto imprimirá el mensaje de registro en el var/log/debug.logarchivo

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

}
Chirag Dodia
fuente
2
no deberías usar addDebug ya que no es compatible con psr logger. use solo depuración en su lugar.
Maciej Paprocki
4

ACTUALIZADO: 19/08/2019

Si está buscando un elegante controlador de registro personalizado, le recomiendo que use Tipos virtuales (que no necesita agregar ningún código PHP)

Inspirado en la respuesta de Petar Dzhambazov y Halk , señoras y caballeros que te presenté una manera mejor y más corto en lugar del código de registro personalizado duplicado todo el tiempo.

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>

USO

Proveedor \ Algo \ Modelo \ 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>

Eso es todo, no hay archivos o líneas PHP adicionales: ¡use las ventajas de Magento 2: Tipos virtuales!

Espero que esto ayude ;)

Toan Nguyen
fuente
3
¿Este código está implementando PSI? (Inyección de declaraciones políticas): P
7ochem
1
@ 7ochem Oh sí, lo es: v
Toan Nguyen
2

Hay una actualización para el registrador en 2.2. Puede habilitar el registrador para el modo de producción ejecutando SQL:

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

Luego puede usar \Psr\Log\LoggerInterface para imprimir el registro al igual que las respuestas anteriores:

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
fuente
gracias, y también puede usar esto en lugar de 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. Inyectar $loggerclase en el constructor \Psr\Log\LoggerInterface $logger
    Esto se logra pasando $ logger como argumento.

  2. Inicializar $loggeren constructor

    $this->logger = $logger
  3. En la función dentro de la clase que desea registrar, use la línea a continuación

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

Si lo necesita dentro de su clase individual con un archivo de registro personalizado:

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
fuente
0

Coloque el código del registrador PSR en su constructor:

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

entonces puedes usar en tu función como:

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

fuente