D8 Messenger Logger Watchdog - pierregermain/MyDrupal GitHub Wiki

tldr

Watchdog

\Drupal::logger('my_module')->notice(t('New User %username inserted.'),
[
'%username' => $form_state->getValue('username'),
]);

Messenger

\Drupal::messenger()->addStatus(t('This is a successful message.'));
\Drupal::messenger()->addWarning(t('This is a warning message.'));
\Drupal::messenger()->addError(t('This is an error message.'));

Watchdog

  • En D7 se usaba watchdog(), ahora en D8 usamos el servicio 'logger.factory'.
\Drupal::logger($channel)->log($level, $message, $context)

donde:

  • $channel generalmente se corresponde con nuestro módulo.

Otros métodos disponibles en LoggerInterface: https://api.drupal.org/api/drupal/vendor!psr!log!Psr!Log!LoggerInterface.php/interface/LoggerInterface/8

  • emergency($message, $context)
  • alert($message, $context)
  • critical($message, $context)
  • error($message, $context)
  • warning($message, $context)
  • notice($message, $context)
  • info($message, $context)
  • debug($message, $context)

Concretamente el método log acepta también el parámetro #level que puede ser RfcLogLevel::NOTICE, RfcLogLevel::ALERT, RfcLogLevel::EMERGENCY, etc.)

Ejemplo con log

// Ejemplo log()
\Drupal::logger('php')->log($error['severity_level'], '%type:
@message in %function (line %line of %file) @backtrace_string.',
$error);

Inyección del logger

Ejemplo: /core/modules/image/scr/ImageEffectBase.php

use Psr\Log\LoggerInterface;

//...

  /**
   * A logger instance.
   *
   * @var \Psr\Log\LoggerInterface
   */
  protected $logger;

/...

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, LoggerInterface $logger) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);

    $this->setConfiguration($configuration);
    $this->logger = $logger;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('logger.factory')->get('image')
    );
  }
///...

$this->logger->notice('...');

//....
$container->get('logger.factory')->get('image')

Implementar un sistema de log personalizado

para no escribir en la tabla watchdog

services

services:
  logger.mymodule:
    class: Drupal\mymodule\Logger\MymoduleLog
    tags:
      - { name: logger }

clase /src/Logger/MymoduleLoggerLog

<?php

namespace Drupal\mymodule\Logger;

use Drupal\Core\Logger\RfcLoggerTrait;
use Psr\Log\LoggerInterface;

class MymoduleLog implements LoggerInterface {

  use RfcLoggerTrait;

  /**
   * {@inheritdoc}
   */
  public function log($level, $message, array $context = []) {
    // Custom log
  }

}

Para usar el servicio una vez inyectado

$this->logger->notice('Test message');

Para usar el servicio sin DI:

  \Drupal::service('logger.mymodule')->log(RfcLogLevel::NOTICE,"hello");

Más info sobre servicios y DI: https://github.com/pierregermain/MyDrupal/wiki/D8-Inyecci%C3%B3n-de-servicios-en-la-clase-controladora-(current-user)

Otro ejemplo completo: /core/modules/dblog/src/Logger/DbLog.php

  • Uso del RfcLoggerTrait
    • Sólo necesitas implementar el método Log()

Ejemplo de custom logger

Llamada desde un hook

    \Drupal::logger('logger.mymodule_logger')->notice("Si se han borrado registros");
    \Drupal::logger('logger.mymodule_logger')->notice("Registros borrados: ".$num);

Servicio:

services:
  logger.mymodule_logger:
    arguments: ['@config.factory', '@logger.log_message_parser', '@request_stack', '@current_user']
    class: Drupal\mymodule_logger\Logger\MymoduleLoggerLog
    tags:
      - { name: logger }

Clase Logger custom:

<?php

namespace Drupal\mymodule_logger\Logger;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\File\FileSystem;
use Drupal\Core\Logger\LogMessageParserInterface;
use Drupal\Core\Logger\RfcLoggerTrait;
use Drupal\Core\Session\AccountProxyInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\RequestStack;

class MymoduleLoggerLog implements LoggerInterface {

  use RfcLoggerTrait;

  /**
   * The message's placeholders parser.
   *
   * @var \Drupal\Core\Logger\LogMessageParserInterface
   */
  protected $parser;

  /**
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  private $config;

  /**
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  private $currentUser;

  /**
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  private $requestStack;

  /**
   * Constructs a MymoduleLoggerLog object.
   *
   * @param \Drupal\Core\Logger\LogMessageParserInterface $parser
   *   The parser to use when extracting message variables.
   */
  public function __construct(
    ConfigFactoryInterface $config_factory,
    LogMessageParserInterface $parser,
    RequestStack $request_stack,
    AccountProxyInterface $current_user
  ) {
    $this->config = $config_factory;
    $this->parser = $parser;
    $this->requestStack = $request_stack;
    $this->currentUser = $current_user;
  }

  /**
   * {@inheritdoc}
   */
  public function log($level, $message, array $context = []) {

    $type = mb_substr($context['channel'], 0, 64);

    if ($type == 'logger.mymodule_logger') {

      // Convert PSR3-style messages to \Drupal\Component\Render\FormattableMarkup
      // style, so they can be translated too in runtime.
      $message_placeholders = $this->parser->parseMessagePlaceholders($message, $context);

      $timestamp = $context['timestamp'];
      $ip = $this->requestStack->getCurrentRequest()->getClientIp();
      $uri = $this->requestStack->getCurrentRequest()->getUri();
      $uid = $context['uid'];
      $message_str = t($message, $message_placeholders);

      $mymessage = implode('|', [ $timestamp, $type, $ip, $uri, $uid, $message_str, ]);

      file_put_contents(drupal_realpath("private://log/drupal_example.log"),
        $mymessage . PHP_EOL, FILE_APPEND);

    }
  }

}