Usar un logger custom en Magento2

Log personalizado

Ayer escribí un poco sobre cómo hacer uso del logger en Magento2. Hoy vamos a ver cómo hacer que nuestro módulo genere su propio log, separado de los nativos de Magento.

Si prestamos atención, para instanciar el logger, lo que hacemos es inyectar \Psr\Log\LoggerInterface, que, claramente, es una interfase (lo pueden ver en /vendor/psr/log/Psr/Log/LoggerInterface.php).

Pero, por supuesto, no es esa interfase la que se instnacia. A través de una preferencia en /app/etc/di.xml, se reemplaza la Interface con Magento\Framework\Logger\Monolog.

Si seguimos recorriendo el camino de herencias e inyecciones, esa clase extiende de la clase Logger de Monolog.

Toda esta explicación es sólo para adelantarme a la posibilidad de opciones que tendremos, de aquí en más, para manejar nuestros logs. Ya sea los que desarrollemos para un módulo específico como el total de logs de la plataforma.

Antes de comenzar a imaginar salidas más complejas e interesantes para nuestros logs, veamos cómo, finalmente, podremos implementar nuestro básico e independiente archivo de log en nuestro módulo.

Comenzamos por crear, dentro del módulo, el archivo Logger/Sample.php.

<?php
 
namespace Barbanet\SampleModule\Logger;
 
use Monolog\Logger;
 
class Sample extends Logger {}

Lo siguiente será crear nuestro propio hanlder en Logger/Handler/Sample.php.

<?php
 
namespace Barbanet\SampleModule\Logger\Handler;
 
use Magento\Framework\Logger\Handler\Base;
use Monolog\Logger;
 
class Sample extends Base
{
 
    /**
     * @var string
     */
    protected $fileName = '/var/log/my-sample-log.log';
 
    /**
     * @var
     */
    protected $loggerType = Logger::DEBUG;
 
}

Es en el handler en donde estoy indicando en qué archivo de log se guardará la información en cuestión.

Luego llega el momento de agregar el logger y el handler. el archivo etc/di.xml será nuestro nuevo mejor amigo cuando se trate de dotar de funcionalidades a los módulos.

Lo editamos y agregamos:

<type name="Barbanet\SampleModule\Logger\Handler\Sample">
    <arguments>
        <argument name="filesystem" xsi:type="object">Magento\Framework\Filesystem\Driver\File</argument>
    </arguments>
</type>
<type name="Barbanet\SampleModule\Logger\Sample">
    <arguments>
        <argument name="name" xsi:type="string">BarbanetSammpleLogger</argument>
        <argument name="handlers" xsi:type="array">
            <item name="system" xsi:type="object">Barbanet\SampleModule\Logger\Handler\Sample</item>
        </argument>
    </arguments>
</type>

Primero hemos definido un handler y luego hemos definido nuestro logger y le hemos indicado que será nuestro handler el que se usará.

En el ejemplo de ayer había creado un comando de consola para testear el logger. Vamos a editar ese mismo archivo, y le vamos a inyectar también nuestro nuevo logger.

<?php
 
namespace Barbanet\SampleModule\Console;
 
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
 
/**
 * Class Logger
 * @package Barbanet\SampleModule\Console
 */
class Logger extends Command
{
 
    /**
     * @var
     */
    private $logger;
 
    /**
     * @var
     */
    private $logger_custom;
 
    /**
     * @param \Psr\Log\LoggerInterface $logger
     * @param \Barbanet\SampleModule\Logger\Sample $logger_custom
     * @param null $name
     */
    public function __construct(
        \Psr\Log\LoggerInterface $logger,
        \Barbanet\SampleModule\Logger\Sample $logger_custom,
        $name = null
    ) {
        $this->logger = $logger;
        $this->logger_custom = $logger_custom;
        parent::__construct($name);
    }
 
    protected function configure()
    {
        $this->setName('samplemodule:logger');
        $this->setDescription('Barbanet_SampleModule Logger test command');
    }
 
    /**
     * @param InputInterface $input
     * @param OutputInterface $output
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this->logger->alert('Mensaje Alerta');
        $this->logger->critical('Mensaje Crítico');
        $this->logger->debug('Mensaje Debug');
        $this->logger->emergency('Mensaje Emergencia');
        $this->logger->error('Mensaje Error');
        $this->logger->info('Mensaje Info');
        $this->logger->notice('Mensaje Notice');
        $this->logger->warning('Mensaje Warning');
 
        $this->logger->log(\Psr\Log\LogLevel::INFO, 'Mensaje Log');
 
        $this->logger_custom->info('Estoy probando mi logger custom');
 
    }
 
}

He inyectado el logger en el segundo parámetro del constructor y luego, al final del método execute, lo estoy invocando.

Para probar que todo esto tiene sentido, vamos a la consola y ejecutamos:

bin/magento samplemodule:logger

Al hacerlo, en el directorio var/log de nuestra instancia veremos que además de debug.log y system.log ahora tenemos el archivo my-sample-log.log y que su contenido debería ser:

[2017-06-28 02:10:25] BarbanetSammpleLogger.INFO: Estoy probando mi logger custom [] []

Como puede verse, se ha logueado mi mensaje, en mi archivo con mi logger.

Hasta acá todo funcionó como esperaba. Lo comentado en el post sobre el módulo Barbanet_SampleModule está disponible en GitHub bajo el tag 2.18.0.