You are here

filelog.module in File Log 6.2

Same filename and directory in other branches
  1. 8 filelog.module
  2. 6 filelog.module
  3. 7 filelog.module
  4. 2.0.x filelog.module

Writes logging messages into files.

File

filelog.module
View source
<?php

/**
 * @file
 * Writes logging messages into files.
 */

/**
 * Implementation of hook_watchdog().
 */
function filelog_watchdog($entry) {
  static $shutdown;
  if (!$shutdown) {
    register_shutdown_function('_filelog_shutdown');
    $shutdown = TRUE;
  }
  $f = _filelog_get_conf();
  if (!empty($f['type_levels']) && array_key_exists($entry['type'], $f['type_levels'])) {
    if ($entry['severity'] > $f['type_levels'][$entry['type']]) {
      return;
    }
  }
  else {
    if ($entry['severity'] > $f['log_level']) {
      return;
    }
  }
  if ($path = filelog_path($entry)) {
    $msg = ($f['with_ui'] ? _filelog_format_for_ui($entry) : theme('filelog_format', $entry)) . "\n";
    if ($f['buffer']) {
      _filelog_buffer($path, $msg);
    }
    else {
      if ($fp = _filelog_get_pointer($path)) {
        fwrite($fp, $msg);
      }
    }
  }
}

/**
 * Implementation of hook_theme().
 */
function filelog_theme() {
  return array(
    'filelog_format' => array(
      'arguments' => array(
        'entry' => NULL,
      ),
    ),
  );
}

/**
 * Implementation of hook_cron().
 */
function filelog_cron() {
  $f = _filelog_get_conf();
  if ($f['daily_files'] && ($days = $f['delete_files'])) {
    if ($files = file_scan_directory(filelog_directory(), '.+')) {
      $limit = format_date(time() - $days * 24 * 3600, 'custom', 'Ymd');
      foreach ($files as $filename => $info) {
        $parts = explode('.', $filename);
        array_shift($parts);
        if (array_shift($parts) < $limit) {
          file_delete($filename);
        }
      }
    }
  }
}

/**
 * Format a file log entry.
 *
 * @ingroup themeable
 */
function theme_filelog_format($entry) {
  global $base_url;
  $f = _filelog_get_conf();

  //shortcuts
  $sep =& $f['field_separator'];
  $prefix =& $f['field_prefix'];
  $suffix =& $f['field_suffix'];
  $message = '';
  if ($f['log_base_url']) {
    $message .= $prefix . $base_url . $suffix . $sep;
  }
  if ($f['date_format']) {
    if (in_array($f['date_format'], array(
      'small',
      'large',
      'medium',
    ))) {
      $entry['timestamp'] = format_date($entry['timestamp'], $f['date_format'], '', NULL, 'en');
    }
    else {
      $entry['timestamp'] = format_date($entry['timestamp'], 'custom', $f['date_format'], NULL, 'en');
    }
  }
  $message .= $prefix . $entry['timestamp'] . $suffix;

  //Add severity to the message, when it isn't in or it is groupped in the file name, only.
  if ($f['group_severity_in_name'] || !$f['severity_in_name']) {
    $message .= $sep . $prefix . ($f['decode_severity'] ? _filelog_decode_severity($entry['severity']) : $entry['severity']) . $suffix;
  }
  if (!$f['type_in_name']) {
    $message .= $sep . $prefix . $entry['type'] . $suffix;
  }
  if ($f['log_username']) {
    $message .= $sep . $prefix . ($entry['user']->uid ? $entry['user']->name : variable_get('anonymous', t('Anonymous'))) . $suffix;
  }
  else {
    $message .= $sep . $prefix . $entry['user']->uid . $suffix;
  }
  $message .= $sep . $prefix . $entry['ip'] . $suffix;
  $message .= $sep . $prefix . $entry['request_uri'] . $suffix;
  $message .= $sep . $prefix . $entry['referer'] . $suffix;
  $message .= $sep . $prefix . ($f['skip_strip_tags'] ? $entry['link'] : strip_tags($entry['link'])) . $suffix;
  if (is_object($entry['variables'])) {
    $entry['variables'] = (array) $entry['variables'];
  }
  else {
    if (!is_array($entry['variables'])) {
      $entry['variables'] = array();
    }
  }
  if (!$f['wrap_message']) {
    $prefix = $suffix = '';
  }
  $text = is_null($entry['variables']) ? $entry['message'] : strtr($entry['message'], $entry['variables']);
  $message .= $sep . $prefix . ($f['skip_strip_tags'] ? $text : strip_tags($text)) . $suffix;
  return $message;
}
function filelog_directory($check = TRUE, $refresh = FALSE) {
  static $dir;
  if (is_null($dir) || $refresh) {
    $f = _filelog_get_conf();
    if (is_string($f['dir'])) {
      $dir = $f['dir'];
    }
    else {
      $dir = conf_path() . '/logs';
    }
    if ($check && !file_check_directory($dir, FILE_MODIFY_PERMISSIONS)) {
      $dir = FALSE;
    }
  }
  return $dir;
}
function filelog_path($entry) {
  static $path;
  if (!is_null($path)) {
    return $path;
  }
  if (!($dir = filelog_directory())) {
    $path = FALSE;
    return FALSE;
  }
  $f = _filelog_get_conf();
  $name = array();
  $cache = TRUE;
  if ($f['site_in_name']) {
    $name[] = $f['site_in_name'] === TRUE ? array_pop(explode('/', conf_path())) : $f['site_in_name'];
  }
  if ($f['type_in_name']) {
    $name[] = preg_replace('|\\s+|', '_', $entry['type']);
    $cache = FALSE;
  }
  else {
    if (!$f['site_in_name']) {
      $name[] = 'watchdog';
    }
  }
  if ($f['daily_files']) {
    $name[] = format_date(time(), 'custom', 'Ymd');
  }
  if ($f['severity_in_name']) {
    if ($f['group_severity_in_name']) {
      switch ($entry['severity']) {
        case WATCHDOG_DEBUG:
          $name[] = 'debug';
          break;
        case WATCHDOG_INFO:
        case WATCHDOG_NOTICE:
        case WATCHDOG_WARNING:
          $name[] = 'info';
          break;
        case WATCHDOG_ERROR:
        case WATCHDOG_CRITICAL:
        case WATCHDOG_ALERT:
        case WATCHDOG_EMERG:
          $name[] = 'error';
          break;
      }
    }
    else {
      $name[] = _filelog_decode_severity($entry['severity']);
    }
    $cache = FALSE;
  }
  $name[] = $f['with_ui'] ? 'ui-log' : 'log';
  $file = $dir . '/' . implode('.', $name);
  if (!file_exists($file)) {
    if (touch($file)) {
      if ($f['chmod']) {
        chmod($file, $f['chmod']);
      }

      //realpath() should be used, because apache changes the working directory during shutdown,

      //which breaks logging when buffer is on.
      $file = realpath($file);
    }
    else {
      $cache = FALSE;
    }
  }
  if ($cache) {
    $path = $file;
  }
  return $file;
}
function _filelog_format_for_ui($entry) {
  global $base_url;
  $f = _filelog_get_conf();
  $message = '';
  if ($f['log_base_url']) {
    $message .= $base_url . '|';
  }
  $message .= $entry['timestamp'];
  $message .= '|' . $entry['severity'];
  $message .= '|' . $entry['type'];
  $message .= '|' . $entry['user']->uid;
  $message .= '|' . $entry['ip'];
  $message .= '|' . base64_encode($entry['request_uri']);
  $message .= '|' . base64_encode($entry['referer']);
  $message .= '|' . base64_encode($entry['link']);
  $message .= '|' . base64_encode($entry['message']);
  if (is_object($entry['variables'])) {
    $entry['variables'] = (array) $entry['variables'];
  }
  if (is_array($entry['variables']) && !empty($entry['variables'])) {
    foreach ($entry['variables'] as $key => $value) {
      $entry['variables'][$key] = base64_encode($value);
    }
    $message .= '|' . serialize($entry['variables']);
  }
  return $message;
}
function _filelog_get_conf() {
  global $conf;
  static $f;
  if (is_null($f)) {
    $f = !array_key_exists('filelog', $conf) || !is_array($conf['filelog']) ? array() : $conf['filelog'];
    $f += array(
      'dir' => FALSE,
      'log_level' => WATCHDOG_DEBUG,
      'type_levels' => array(),
      'buffer' => TRUE,
      'site_in_name' => FALSE,
      'type_in_name' => FALSE,
      'severity_in_name' => FALSE,
      'group_severity_in_name' => FALSE,
      'daily_files' => FALSE,
      'delete_files' => FALSE,
      'field_separator' => '|',
      'field_prefix' => '',
      'field_suffix' => '',
      'wrap_message' => FALSE,
      'log_base_url' => FALSE,
      'log_username' => FALSE,
      'date_format' => FALSE,
      'decode_severity' => FALSE,
      'skip_strip_tags' => FALSE,
      'chmod' => FALSE,
      'with_ui' => FALSE,
    );

    //legacy suuport fro DEPRECATED grouped_severity_in_name directive
    if (array_key_exists('grouped_severity_in_name', $f)) {
      $f['group_severity_in_name'] = $f['grouped_severity_in_name'];
      unset($f['grouped_severity_in_name']);
    }
  }
  return $f;
}
function _filelog_decode_severity($severity) {
  switch ($severity) {
    case WATCHDOG_DEBUG:
      return 'debug';
    case WATCHDOG_INFO:
      return 'info';
    case WATCHDOG_NOTICE:
      return 'notice';
    case WATCHDOG_WARNING:
      return 'warning';
    case WATCHDOG_ERROR:
      return 'error';
    case WATCHDOG_CRITICAL:
      return 'critical';
    case WATCHDOG_ALERT:
      return 'alert';
    case WATCHDOG_EMERG:
      return 'emergency';
    default:
      return 'unknown';
  }
}
function _filelog_get_pointer($path, $cache = TRUE) {
  static $pointers = array();
  if (is_null($path)) {
    return $pointers;
  }
  if ($cache && isset($pointers[$path])) {
    return $pointers[$path];
  }
  $retry = 0;
  while ($retry < 3) {
    if ($fp = fopen($path, 'ab')) {
      stream_set_blocking($fp, 0);
      break;
    }
    $retry++;
    usleep(250);
  }
  if ($fp && $cache) {
    $pointers[$path] = $fp;
  }
  return $fp;
}
function _filelog_buffer($path, $msg) {
  static $buffer = array();
  if (is_null($path) || is_null($msg)) {
    return $buffer;
  }
  if (!isset($buffer[$path])) {
    $buffer[$path] = array();
  }
  $buffer[$path][] = $msg;
}
function _filelog_shutdown() {
  if ($buffer = _filelog_buffer(NULL, NULL)) {
    foreach ((array) $buffer as $path => $entries) {
      if (count($entries) && ($fp = _filelog_get_pointer($path, FALSE))) {
        foreach ($entries as $msg) {
          fwrite($fp, $msg);
        }
        fclose($fp);
      }
    }
  }
  if ($pointers = _filelog_get_pointer(NULL)) {
    foreach ((array) $pointers as $fp) {
      fclose($fp);
    }
  }
}