Skip to content
dblog.module 10.5 KiB
Newer Older
Dries Buytaert's avatar
 
Dries Buytaert committed
<?php
Dries Buytaert's avatar
Dries Buytaert committed

Dries Buytaert's avatar
 
Dries Buytaert committed
/**
 * @file
 * System monitoring and logging for administrators.
 *
 * The dblog module monitors your site and keeps a list of
Dries Buytaert's avatar
 
Dries Buytaert committed
 * recorded events containing usage and performance data, errors,
 * warnings, and similar operational information.
 *
 * @see watchdog().
 */

/**
 * Implementation of hook_help().
 */
Dries Buytaert's avatar
 
Dries Buytaert committed
  switch ($section) {
    case 'admin/help#dblog':
      $output = '<p>'. t('The dblog module monitors your system, capturing system events in a log to be reviewed by an authorized individual at a later time. This is useful for site administrators who want a quick overview of activities on their site. The logs also record the sequence of events, so it can be useful for debugging site errors.') .'</p>';
      $output .= '<p>'. t('The dblog log is simply a list of recorded events containing usage data, performance data, errors, warnings and operational information. Administrators should check the dblog report on a regular basis to ensure their site is working properly.') .'</p>';
      $output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="@dblog">Dblog page</a>.', array('@dblog' => 'http://drupal.org/handbook/modules/dblog/')) .'</p>';
      return '<p>'. t('The dblog module monitors your website, capturing system events in a log to be reviewed by an authorized individual at a later time. The dblog log is simply a list of recorded events containing usage data, performance data, errors, warnings and operational information. It is vital to check the dblog report on a regular basis as it is often the only way to tell what is going on.') .'</p>';
Dries Buytaert's avatar
 
Dries Buytaert committed
  }
Dries Buytaert's avatar
 
Dries Buytaert committed
/**
Dries Buytaert's avatar
 
Dries Buytaert committed
 * Implementation of hook_menu().
Dries Buytaert's avatar
 
Dries Buytaert committed
 */
function dblog_menu() {
  $items['admin/settings/logging/dblog'] = array(
    'title' => t('Database logging'),
    'description' => t('Settings for logging to the Drupal database logs. This is the most common method for small to medium sites on shared hosting. The logs are viewable from the admin pages.'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array('dblog_admin_settings'),
  );

  $items['admin/logs/dblog'] = array(
    'title' => t('Recent log entries'),
    'description' => t('View events that have recently been logged.'),
    'weight' => -1,
  );
  $items['admin/logs/page-not-found'] = array(
    'title' => t("Top 'page not found' errors"),
    'description' => t("View 'page not found' errors (404s)."),
    'page arguments' => array('page not found'),
  );
  $items['admin/logs/access-denied'] = array(
      'title' => t("Top 'access denied' errors"),
    'description' => t("View 'access denied' errors (403s)."),
    'page arguments' => array('access denied'),
  );
  $items['admin/logs/event/%'] = array(
    'title' => t('Details'),
    'page arguments' => array(3),
    'type' => MENU_CALLBACK,
  );
  return $items;
}
Dries Buytaert's avatar
 
Dries Buytaert committed

  if (arg(0) == 'admin' && arg(1) == 'logs') {
    // Add the CSS for this module
    drupal_add_css(drupal_get_path('module', 'dblog') .'/dblog.css', 'module', 'all', FALSE);
Dries Buytaert's avatar
 
Dries Buytaert committed
}

function dblog_admin_settings() {
  $form['dblog_row_limit'] = array(
    '#type' => 'select',
    '#title' => t('Discard log entries above the following row limit'),
    '#default_value' => variable_get('dblog_row_limit', 1000),
    '#options' => drupal_map_assoc(array(100, 1000, 10000, 100000, 1000000)),
    '#description' => t('The maximum number of rows to keep in the database log. Older entries will be automatically discarded. Requires crontab.')
  );

  return system_settings_form($form);
}

/**
 * Implementation of hook_cron().
 *
Dries Buytaert's avatar
 
Dries Buytaert committed
 * Remove expired log messages and flood control events.
function dblog_cron() {
  // Cleanup the watchdog table
  $min = db_result(db_query('SELECT MIN(wid) FROM {watchdog}'));
  if ($min) {
    $max = db_result(db_query('SELECT MAX(wid) FROM {watchdog}'));
    if ($max) {
      if (($max - $min) > variable_get('dblog_row_limit', 1000)) {
        db_query('DELETE FROM {watchdog} WHERE wid < %d', $max - $min);
      }
    }
  }
Dries Buytaert's avatar
 
Dries Buytaert committed
}
Dries Buytaert's avatar
Dries Buytaert committed

function dblog_user($op, &$edit, &$user) {
Steven Wittens's avatar
Steven Wittens committed
    db_query('UPDATE {watchdog} SET uid = 0 WHERE uid = %d', $user->uid);
  foreach (_dblog_get_message_types() as $type) {
    $names[$type] = t('!type messages', array('!type' => t($type)));
  if (empty($_SESSION['dblog_overview_filter'])) {
    $_SESSION['dblog_overview_filter'] = 'all';
  $form['filter'] = array(
    '#type' => 'select',
    '#title' => t('Filter by message type'),
    '#options' => $names,
    '#default_value' => $_SESSION['dblog_overview_filter']
  $form['submit'] = array('#type' => 'submit', '#value' => t('Filter'));
  $form['#redirect'] = FALSE;

  return $form;
}
/**
 * Menu callback; displays a listing of log messages.
 */
  $icons = array(WATCHDOG_NOTICE  => '',
                 WATCHDOG_WARNING => theme('image', 'misc/watchdog-warning.png', t('warning'), t('warning')),
                 WATCHDOG_ERROR   => theme('image', 'misc/watchdog-error.png', t('error'), t('error')));
  $classes = array(WATCHDOG_NOTICE => 'dblog-notice', WATCHDOG_WARNING => 'dblog-warning', WATCHDOG_ERROR => 'dblog-error');
  $output = drupal_get_form('dblog_form_overview');
Dries Buytaert's avatar
 
Dries Buytaert committed
  $header = array(
    array('data' => t('Type'), 'field' => 'w.type'),
    array('data' => t('Date'), 'field' => 'w.wid', 'sort' => 'desc'),
Dries Buytaert's avatar
 
Dries Buytaert committed
    array('data' => t('Message'), 'field' => 'w.message'),
    array('data' => t('User'), 'field' => 'u.name'),
Dries Buytaert's avatar
 
Dries Buytaert committed
  );
  $sql = "SELECT w.wid, w.uid, w.severity, w.type, w.timestamp, w.message, w.link, u.name FROM {watchdog} w INNER JOIN {users} u ON w.uid = u.uid";
  $tablesort = tablesort_sql($header);
  $type = $_SESSION['dblog_overview_filter'];
  if ($type != 'all') {
    $result = pager_query($sql ." WHERE w.type = '%s'". $tablesort, 50, 0, NULL, $type);
  }
  else {
    $result = pager_query($sql . $tablesort, 50);
  }
Dries Buytaert's avatar
 
Dries Buytaert committed

  while ($dblog = db_fetch_object($result)) {
        $icons[$dblog->severity],
        t($dblog->type),
        format_date($dblog->timestamp, 'small'),
        l(truncate_utf8($dblog->message, 56, TRUE, TRUE), 'admin/logs/event/'. $dblog->wid, array('html' => TRUE)),
        theme('username', $dblog),
        $dblog->link,
      'class' => "dblog-". preg_replace('/[^a-z]/i', '-', $dblog->type) .' '. $classes[$dblog->severity]
Dries Buytaert's avatar
 
Dries Buytaert committed
    );
Dries Buytaert's avatar
Dries Buytaert committed
  }
Dries Buytaert's avatar
 
Dries Buytaert committed

Dries Buytaert's avatar
 
Dries Buytaert committed
  if (!$rows) {
    $rows[] = array(array('data' => t('No log messages available.'), 'colspan' => 6));
Dries Buytaert's avatar
 
Dries Buytaert committed
  }
Dries Buytaert's avatar
 
Dries Buytaert committed

  $output .= theme('table', $header, $rows);
  return $output;
}

/**
 * Menu callback; generic function to display a page of the most frequent

  $header = array(
    array('data' => t('Count'), 'field' => 'count', 'sort' => 'desc'),
    array('data' => t('Message'), 'field' => 'message')
  );

  $result = pager_query("SELECT COUNT(wid) AS count, message FROM {watchdog} WHERE type = '%s' GROUP BY message ". tablesort_sql($header), 30, 0, "SELECT COUNT(DISTINCT(message)) FROM {watchdog} WHERE type = '%s'", $type);

  while ($dblog = db_fetch_object($result)) {
    $rows[] = array($dblog->count, truncate_utf8($dblog->message, 56, TRUE, TRUE));
    $rows[] = array(array('data' => t('No log messages available.'), 'colspan' => 2));
  }

  $output  = theme('table', $header, $rows);
  $output .= theme('pager', NULL, 30, 0);

Dries Buytaert's avatar
 
Dries Buytaert committed
  return $output;
Dries Buytaert's avatar
Dries Buytaert committed
}

function theme_dblog_form_overview($form) {
  return '<div class="container-inline">'. drupal_render($form) .'</div>';
function dblog_form_overview_submit($form_id, $form_values) {
  $_SESSION['dblog_overview_filter'] = $form_values['filter'];
/**
 * Menu callback; displays details about a log message.
 */
  $severity = array(WATCHDOG_NOTICE => t('notice'), WATCHDOG_WARNING => t('warning'), WATCHDOG_ERROR => t('error'));
  $output = '';
  $result = db_query('SELECT w.*, u.name, u.uid FROM {watchdog} w INNER JOIN {users} u ON w.uid = u.uid WHERE w.wid = %d', $id);
    $rows = array(
      array(
        array('data' => t('Type'), 'header' => TRUE),
      ),
      array(
        array('data' => t('Date'), 'header' => TRUE),
      ),
      array(
        array('data' => t('User'), 'header' => TRUE),
      ),
      array(
        array('data' => t('Location'), 'header' => TRUE),
      ),
      array(
        array('data' => t('Referrer'), 'header' => TRUE),
      ),
      array(
        array('data' => t('Message'), 'header' => TRUE),
      ),
      array(
        array('data' => t('Severity'), 'header' => TRUE),
      ),
      array(
        array('data' => t('Hostname'), 'header' => TRUE),
      array(
        array('data' => t('Operations'), 'header' => TRUE),
    $attributes = array('class' => 'dblog-event');
    $output = theme('table', array(), $rows, $attributes);
Dries Buytaert's avatar
 
Dries Buytaert committed
  $types = array();

  $result = db_query('SELECT DISTINCT(type) FROM {watchdog} ORDER BY type');
Dries Buytaert's avatar
 
Dries Buytaert committed
  while ($object = db_fetch_object($result)) {
    $types[] = $object->type;
  }

  return $types;
}

function dblog_watchdog($log = array()) {
  $current_db = db_set_active();
  db_query("INSERT INTO {watchdog}
    (uid, type, message, severity, link, location, referer, hostname, timestamp)
    VALUES
    (%d, '%s', '%s', %d, '%s', '%s', '%s', '%s', %d)",
    $log['user']->uid,
    $log['type'],
    $log['message'],
    $log['severity'],
    $log['link'],
    $log['request_uri'],
    $log['referer'],
    $log['ip'],
    $log['timestamp']);

  if ($current_db) {
    db_set_active($current_db);
  }
}