You are here

function raven_watchdog in Raven: Sentry Integration 7.3

Same name and namespace in other branches
  1. 7.4 raven.module \raven_watchdog()
  2. 7 raven.module \raven_watchdog()
  3. 7.2 raven.module \raven_watchdog()

Implements hook_watchdog().

File

./raven.module, line 138
Allows to track errors to Sentry server.

Code

function raven_watchdog($log_entry) {
  if (!variable_get('raven_enabled', FALSE)) {
    return;
  }
  $client = raven_get_client();
  if (!$client) {
    return;
  }
  $watchdog_levels = variable_get('raven_watchdog_levels', array());
  $levels_map = array(
    WATCHDOG_EMERGENCY => Raven_Client::FATAL,
    WATCHDOG_ALERT => Raven_Client::FATAL,
    WATCHDOG_CRITICAL => Raven_Client::FATAL,
    WATCHDOG_ERROR => Raven_Client::ERROR,
    WATCHDOG_WARNING => Raven_Client::WARNING,
    WATCHDOG_NOTICE => Raven_Client::INFO,
    WATCHDOG_INFO => Raven_Client::INFO,
    WATCHDOG_DEBUG => Raven_Client::DEBUG,
  );
  $variables = $log_entry['variables'];
  if (!$variables) {
    $variables = array();
  }
  if (!function_exists('truncate_utf8')) {
    require_once DRUPAL_ROOT . '/includes/unicode.inc';
    unicode_check();
  }
  $message = truncate_utf8(html_entity_decode(strip_tags(strtr($log_entry['message'], $variables)), ENT_QUOTES, 'UTF-8'), variable_get('raven_message_limit', 2048), FALSE, TRUE);
  $data = array(
    'level' => $levels_map[$log_entry['severity']],
    'sentry.interfaces.Message' => array(
      'message' => $log_entry['message'],
      'params' => $log_entry['variables'],
      'formatted' => $message,
    ),
    'extra' => array(
      'link' => $log_entry['link'],
      'request_uri' => $log_entry['request_uri'],
      'referer' => $log_entry['referer'],
    ),
    'logger' => $log_entry['type'],
    'user' => array(
      'id' => $log_entry['uid'],
      'ip_address' => $log_entry['ip'],
    ),
  );
  if ($log_entry['user']) {
    $data['user']['roles'] = implode(', ', $log_entry['user']->roles);
    if ($log_entry['uid']) {
      $data['user']['name'] = $log_entry['user']->name;
      $data['user']['email'] = $log_entry['user']->mail;
    }
  }
  $filter = array(
    'process' => !empty($watchdog_levels[$log_entry['severity'] + 1]),
    'log_entry' => $log_entry,
    'data' => &$data,
  );
  $ignored_types = array_map('trim', preg_split('/\\R/', variable_get('raven_ignored_types', ''), -1, PREG_SPLIT_NO_EMPTY));
  if (in_array($log_entry['type'], $ignored_types)) {
    $filter['process'] = FALSE;
  }
  drupal_alter('raven_watchdog_filter', $filter);
  if ($filter['process']) {

    // Save memory by not copying the object for each frame.
    $stack = debug_backtrace(0);

    // Ignore error handling and logging frames.
    if (empty($stack[0]['class']) && isset($stack[0]['function']) && $stack[0]['function'] == 'raven_watchdog') {
      array_shift($stack);
    }
    if (empty($stack[0]['class']) && isset($stack[0]['function']) && $stack[0]['function'] == 'call_user_func_array') {
      array_shift($stack);
    }
    if (empty($stack[0]['class']) && isset($stack[0]['function']) && ($stack[0]['function'] == 'module_invoke_all' || $stack[0]['function'] == 'module_invoke')) {
      array_shift($stack);
    }
    if (empty($stack[0]['class']) && isset($stack[0]['function']) && $stack[0]['function'] == 'watchdog' && empty($stack[1]['class']) && isset($stack[1]['function']) && $stack[1]['function'] == 'watchdog_exception') {
      array_shift($stack);
    }
    elseif (empty($stack[0]['class']) && isset($stack[0]['function']) && $stack[0]['function'] == 'watchdog' && empty($stack[1]['class']) && isset($stack[1]['function']) && $stack[1]['function'] == '_drupal_log_error') {
      array_shift($stack);
      array_shift($stack);
    }
    if (empty($stack[0]['class']) && isset($stack[0]['function']) && $stack[0]['function'] == '_drupal_error_handler_real') {
      array_shift($stack);
    }
    if (empty($stack[0]['class']) && isset($stack[0]['function']) && $stack[0]['function'] == '_drupal_error_handler' && empty($stack[0]['line'])) {
      array_shift($stack);
    }
    if (empty($stack[0]['class']) && isset($stack[0]['function']) && ($stack[0]['function'] == 'watchdog_exception' || $stack[0]['function'] == '_drupal_exception_handler')) {
      $arg = array(
        'watchdog_exception' => 1,
        '_drupal_exception_handler' => 0,
      );

      // Use the exception backtrace for (usually) easier debugging.
      $exception = $stack[0]['args'][$arg[$stack[0]['function']]];
      $stack = $exception
        ->getTrace();

      // Copy logic from _drupal_decode_exception().
      array_unshift($stack, array(
        'line' => $exception
          ->getLine(),
        'file' => $exception
          ->getFile(),
      ));
      if ($exception instanceof PDOException) {
        $db_functions = array(
          'db_query',
          'db_query_range',
        );
        while (!empty($stack[1]) && ($caller = $stack[1]) && (isset($caller['class']) && (strpos($caller['class'], 'Query') !== FALSE || strpos($caller['class'], 'Database') !== FALSE || strpos($caller['class'], 'PDO') !== FALSE) || in_array($caller['function'], $db_functions))) {
          array_shift($stack);
        }
      }
    }

    // By default, disable reflection tracing for user watchdog entries.
    if ($data['logger'] === 'user' && $client->trace && !variable_get('raven_trace_user', FALSE)) {
      $client->trace = FALSE;
      $client
        ->capture($data, $client->auto_log_stacks ? $stack : FALSE);
      $client->trace = TRUE;
    }
    else {
      $client
        ->capture($data, $client->auto_log_stacks ? $stack : FALSE);
    }
  }

  // Record a breadcrumb.
  $breadcrumb = array(
    'log_entry' => $log_entry,
    'process' => TRUE,
    'breadcrumb' => array(
      'category' => $log_entry['type'],
      'message' => $message,
      'level' => $data['level'],
    ),
  );
  foreach (array(
    '%line',
    '%file',
    '%type',
    '%function',
  ) as $key) {
    if (isset($log_entry['variables'][$key])) {
      $breadcrumb['breadcrumb']['data'][substr($key, 1)] = $log_entry['variables'][$key];
    }
  }
  drupal_alter('raven_breadcrumb', $breadcrumb);
  if (!empty($breadcrumb['process'])) {
    $client->breadcrumbs
      ->record($breadcrumb['breadcrumb']);
  }
}