reko_3 发表于 2015-8-27 09:06:04

PHP

对xdebug不感冒,还是喜欢查看error.log来定位问题。

想找个工具来监视error.log的最新修改,无果。

还是自己动手吧,先到htdocs下建目录log:


log/index.php
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    <title>error.log digest</title>
    <style>
      body {}{
            font: 10pt helvetica;
            padding: 20px;
      }
      table {}{
            border: none;
            border-collapse: collapse;
            width: 900px;
            margin: 0 auto;
      }
      th, td {}{
            font: 10pt helvetica;
            border: 1px solid #ccc;
            padding: 10px;
      }
      th {}{
            font-weight: bold;
            font-size: 11pt;
      }
      tr.latest td {}{
            background-color: #ffffe1;
      }
      tr.hint td {}{
            background-color: #eee;
      }
      td.log-time, td.log-type {}{
            text-align: center;
      }
      td.log-text {}{
            text-align: left;
      }
    </style>
</head>

<body>
<?php
    /*
   * Configurations
   */
    require_once 'conf.php';
    $CONFIGS = fetchConfigs();

    /*
   * 'Constants'
   */
    $MONTHS = array(
      'Jan' => '01',
      'Feb' => '02',
      'Mar' => '03',
      'Apr' => '04',
      'May' => '05',
      'Jun' => '06',
      'Jul' => '07',
      'Aug' => '08',
      'Sep' => '09',
      'Oct' => '10',
      'Nov' => '11',
      'Dec' => '12'
    );
    $NOW = new DateTime();

    /*
   * main()
   * In reverse order, i.e, latest on top
   */
    {
      require_once 'revfile.inc';
      $file = new RevFile($CONFIGS['log_file']);
      renderBegin();
      $limit = isset($CONFIGS['limit_entries']) ? $CONFIGS['limit_entries'] : -1;
      // Read limited count of entries, default is 100.
      // This is reasonable as we are only interested in the last couple of lines.
      // As a side effect, performance improved in this way.
      if ($limit > -1) {
            while (!$file->sof() && $limit-- > 0) {
                $line = $file->getLine();
                $parts = extractLine($line);
                if (count($parts) > 0) {
                  renderLine($parts);
                }
            }
      }
      // No limit, read all entries
      // Either not set in the config file or set to -1.
      else {
            while (!$file->sof()) {
                $line = $file->getLine();
                $parts = extractLine($line);
                if (count($parts) > 0) {
                  renderLine($parts);
                }
            }
      }
      renderEnd();
    }

    /**
   * Extract each part of a line via RegExp: month, day, time, year, type, text
   *
   * @sample
   * PHP Parse error:parse error in E:\\apache\\httpd\\htdocs\\log\\index.php on line 135
   */
    function extractLine($line) {
      global $MONTHS;
      $rv = array();

      // if '' contained in the line, ignore it
      $ignore = '/\/i';
      if (preg_match($ignore, $line)) {
            return $rv;
      }

      // this is what we are interested
      $interested = '/^\[.+({3}) ({2}) ({2}:{2}:{2}) ({4})\] \[(+)\] \[.+\] (.+)$/i';
      $matches = array();
      if (preg_match($interested, $line, $matches)) {
            $rv = array(
                'month' => $MONTHS[$matches],
                'day' => $matches,
                'time' => $matches,
                'year' => $matches,
                'type' => $matches,
                'text' => $matches
            );
      }
      return $rv;
    }

    function renderBegin() {
      global $NOW, $CONFIGS;
      $html = '<table><tody>';
      $html .= '<tr><th colspan="3">'.$CONFIGS['log_file'].' ('.$NOW->format('Y-m-d H:i:s').')</th></tr>';
      $html .= '<tr><th style="width:130px;">Time</th><th>Type</th><th>Text</th></tr>';
      echo $html;
    }

    function renderEnd() {
      global $CONFIGS;
      $html = '';
      if (count($CONFIGS)) {
            $html .= '<tr class="hint"><td colspan="3">Configurations (Edit file <a href="log.conf">log.conf</a> to change)</td></tr>';
            foreach ($CONFIGS as $key => $value) {
                $html .= "<tr class=\"hint\"><td colspan=\"2\">$key</td><td>$value</td></tr>";
            }
      }
      $html .= '</tbody></table>';
      echo $html;
    }

    function renderLine($parts) {
      $timeStamp = $parts['year'].'-'.$parts['month'].'-'.$parts['day'].' '.$parts['time'];
      $trTag = '<tr>';
      $logTime = new DateTime($timeStamp);
      // latest: the entry is logged AND [<= 10 minutes]
      if (isLatest($logTime)) {
            $trTag = '<tr class="latest">';
      }
      $html = $trTag.'<td class="log-time">'.$timeStamp.'</td><td class="log-type">'.$parts['type'].'</td><td class="log-text">'.$parts['text'].'</td>';
      echo $html;
    }

    function isLatest($logTime) {
      global $NOW, $CONFIGS;
      $rv = false;
      $threshold = $CONFIGS['threshold_mark_latest'];
      if ($threshold < 60) {
            $rv = ($NOW->format('Y-m-d') == $logTime->format('Y-m-d') &&
                $NOW->format('H') == $logTime->format('H') &&
                ($NOW->format('i') - $logTime->format('i')) < $threshold);
      }
      return $rv;
    }
?>
</body>
</html>


log/revfile.inc
<?php
/*****************************************************
** Title: RevFile Class
** Version.: 1.00
** Author..: Steve Weet <sweet@weet.demon.co.uk>
** Filename: class.RevFile.php
** Last changed..: 30th Jan 2004
** Purpose.: Allows the display of a file in
** ..: In reverse order
******************************************************/

// Example Usage
/*
    $file = new RevFile("/etc/passwd");

    while (!$file->sof()) {
      echo $file->getLine() ;
    }
*/

class RevFile
{
    protected $_fileName;
    protected $_fileHandle;
    protected $_filePos;

    function __construct($filename)
    {
      $this->_fileName = $filename;
      
      $this->_fileHandle = @fopen($filename, "r") or die("Could not open file $filename\n");

      // Find EOF
      if (!(fseek($this->_fileHandle, 0, SEEK_END) == 0)) {
            die ("Could not find end of file in $filename\n");
      }

      // Store file position
      $this->_filePos = ftell($this->_fileHandle);

      // Check that file is not empty or doesn;t contain a single newline
      if ($this->_filePos < 2) {
            die ("File is empty\n");
      }

      // Position file pointer just before final newline
      // i.e. Skip EOF
      $this->_filePos -= 1;
    }

    function getLine()
    {
      $pos = $this->_filePos -1;
      $ch=" ";
      $line = "";

      while ($ch != "\n" && $pos >= 0) {
            fseek($this->_fileHandle, $pos);
            $ch = fgetc($this->_fileHandle);

            // Decrement out pointer and prepend to the line
            // if we have not hit the new line
            if ($ch != "\n") {
                $pos = $pos -1;
                $line = $ch . $line;
            }
      }
      $this->_filePos = $pos ;
      return $line . "\n";
    }

    function sof()
    {
      return ($this->_filePos <= 0);
    }
}

?>


log/conf.php
<?php
/**
* Simple config file loading
* @author sol
* @example
* $CONFIGS = fetchConfigs();
* foreach ($CONFIGS as $key => $value) {
*   echo "$key = $value<br>";
* }
*/

function fetchConfigs() {
    $rv = array();
    $lines = file('log.conf');
    if ($lines) {
      $comment = '/^#/';
      $config = '/^(+) *=? *"?([^"]+)"?$/i';
      $matches = array();
      foreach ($lines as $line) {
            $line = trim($line);
            // ignore comment, empty line
            if (strlen($line) && !preg_match($comment, $line)) {
                if (preg_match($config, $line, $matches)) {
                  $key = $matches;
                  $value = $matches;
                  $rv[$key] = $value;
                }
            }
      }
    }
    else {
      die('Could not parse config file: "log.conf"');
    }
    return $rv;
}
?>


log/log.conf
#
# Path to the log file.
#
log_file = "e:\apache\httpd\logs\error.log"

#
# How many log entries to fetch (one line one entry).
# Keep in mind that we read log file in reverse order.
# -1 means no limit.
# DEFAULT = 100
#
limit_entries = 20

#
# A time threshold setting, in minutes.
# Comparing page-visit-time with log-entry-time, those entries earlier
# than when this program runs, say, 10 mins, shall be marked as the latest.
# There are visual difference between Latest and Normal entries.
# Ranges from 1 to 59 (minutes).
# DEFAULT = 10
#
threshold_mark_latest = 10

打包下载:log.rar
页: [1]
查看完整版本: PHP