Change record status: 
Project: 
Introduced in branch: 
8.x
Introduced in version: 
8.x
Description: 

In Drupal 8 watchdog has been refactored to an OO, PSR-3 compatible framework.

In the paragraphs below, a "channel" refers to what used to be the $type argument to watchdog(). For logging you would have done with simple watchdog() statements in Drupal 7, look at the example for injecting a specific channel.

The switch to PSR-3 logging has resulted in the following API changes:

  1. hook_watchdog() is gone. For a module to implement a logger, it has to register a service tagged as logger in the module's services.yml file. eg:
    services:
    
      logger.mylog:
        class: Drupal\mylog\Logger\MyLog
        tags:
          - { name: logger }

    This class must implement \Psr\Log\LoggerInterface. like this:

    namespace Drupal\mylog\Logger;
    
    use Drupal\Core\Logger\RfcLoggerTrait;
    use Psr\Log\LoggerInterface;
    
    class MyLog implements LoggerInterface {
      use RfcLoggerTrait;
    
      /**
       * {@inheritdoc}
       */
      public function log($level, $message, array $context = array()) {
        // Do stuff
      }
    
    }
    
  2. watchdog($type, $message, $variables, $severity, $link) has been removed in favor of \Drupal::logger($type)->log($severity, $message, $variables)

    D7

    // Logs a notice
    watchdog('my_module', $message, array());
    // Logs an error
    watchdog('my_module', $message, array(), WATCHDOG_ERROR);
    

    D8 - procedural

    // Logs a notice
    \Drupal::logger('my_module')->notice($message);
    // Logs an error
    \Drupal::logger('my_module')->error($message);
    

    D8 - injecting the whole factory

    services:
      myservice_that_needs_to_log_to_multiple_channels:
        class: Drupal\mymodule\MyService
        arguments: ['@logger.factory']
    
    use Drupal\Core\Logger\LoggerChannelFactoryInterface;
    
    class MyService {
    
      /**
       * The logger factory.
       *
       * @var \Drupal\Core\Logger\LoggerChannelFactoryInterface
       */
      protected $loggerFactory;
    
      /**
       * Constructs a MyService object.
       *
       * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $loggerFactory
       *   The logger factory.
       */
      public function __construct(LoggerChannelFactoryInterface $loggerFactory) {
        $this->loggerFactory = $loggerFactory;
      }
    
      public function doStuff() {
        // Logs a notice to "my_module" channel.
        $this->loggerFactory->get('my_module')->notice($message);
         // Logs an error to "my_other_module" channel.
        $this->loggerFactory->get('my_other_module')->error($message);
      }
    
    }
    

    D8 - injecting a specific channel
    Drupal core registers only one channel in core.services.yml for "system" channel.
    There might be cases where you don't want to inject the whole factory to your class, but just a specific channel.
    In that case you can easily register this channel with something like this:

    services:
      logger.channel.mymodule:
        parent: logger.channel_base
        arguments: ['mymodule']
    

    And then inject logger.channel.mymodule to your services.

    services:
      myservice_that_needs_specific_channel:
        class: Drupal\mymodule\MyService
        arguments: ['@logger.channel.mymodule']
    
    class MyService {
      public function __construct($logger) {
        $this->logger = $logger;
      }
    
      public function doStuff() {
        // Logs a notice.
        $this->logger->notice($message);
         // Logs an error.
        $this->logger->error($message);
      }
    }
    
  3. WATCHDOG_* constants and watchdog_severity_levels() are removed
    D7
    $severity = WATCHDOG_EMERGENCY;
    $severity = WATCHDOG_ALERT;
    $severity = WATCHDOG_CRITICAL;
    $severity = WATCHDOG_ERROR;
    $severity = WATCHDOG_WARNING;
    $severity = WATCHDOG_NOTICE;
    $severity = WATCHDOG_INFO;
    $severity = WATCHDOG_DEBUG;
    $levels = watchdog_severity_levels();
    

    D8

    use Drupal\Core\Logger\RfcLogLevel;
    $severity = RfcLogLevel::EMERGENCY;
    $severity = RfcLogLevel::ALERT;
    $severity = RfcLogLevel::CRITICAL;
    $severity = RfcLogLevel::ERROR;
    $severity = RfcLogLevel::WARNING;
    $severity = RfcLogLevel::NOTICE;
    $severity = RfcLogLevel::INFO;
    $severity = RfcLogLevel::DEBUG;
    $levels = RfcLogLevel::getLevels();
    
Impacts: 
Module developers
Updates Done (doc team, etc.)
Online documentation: 
Not done
Theming guide: 
Not done
Module developer documentation: 
Not done
Examples project: 
Not done
Coder Review: 
Not done
Coder Upgrade: 
Not done
Other: 
Other updates done