/** * 取得日志分析类装载期 * * @return Zend_Loader_PluginLoader */ public static function getLogLoader() { if (null === self::$_loader) { self::$_loader = new Zend_Loader_PluginLoader(array('ZtChart_Model_Monitor_Log_' => realpath(__DIR__ . '/Log'))); } return self::$_loader; }
/** * 取得所有的日志分类统计数据 * * @param array $logPaths * @param string $pattern * @return array */ public function getCategory($logPaths, $pattern) { $stats = array(); foreach ($this->getObjectFiles($logPaths, $pattern) as $objectFile) { fprintf(STDOUT, "读取文件:%s (%d Byte)...", $objectFile, filesize($objectFile)); $sedFile = $this->_sed($objectFile); fprintf(STDOUT, "过滤后文件:%s (%d Byte)...", $sedFile, filesize($sedFile)); foreach (file($sedFile) as $no => $rawline) { try { $mlog = new ZtChart_Model_Monitor_Log($rawline); if (false !== ($lines = $mlog->category())) { foreach ($lines as $identifier => $entry) { if (!array_key_exists($identifier, $stats)) { $stats[$identifier] = array(); } foreach ($entry as $key => $value) { if (!array_key_exists($key, $stats[$identifier])) { $stats[$identifier][$key] = 0; } $stats[$identifier][$key] += $value; } } } } catch (ZtChart_Model_Monitor_Log_Exception $e) { $this->_logger->warn("日志处理错误({$no}):" . iconv('GBK', 'UTF-8', $rawline)); } } @unlink($sedFile); fprintf(STDOUT, " 完毕\n"); } return $stats; }
/** * 监控日志文件 * * @param array $logPaths * @return void * @throws ZtChart_Model_Monitor_Exception */ public function tail($logPaths) { if (($inotify = inotify_init()) === false) { throw new ZtChart_Model_Monitor_Daemon_Exception('Failed to obtain an inotify instance.'); } $watchFiles = $watchDirs = array(); foreach ($logPaths as $file) { if (($watch = inotify_add_watch($inotify, $file, IN_CREATE | IN_MODIFY)) === false) { throw new ZtChart_Model_Monitor_Daemon_Exception("Failed to watch file '{$file}'."); } if (is_file($file)) { if (false === ($fd = fopen($file, "r"))) { throw new ZtChart_Model_Monitor_Daemon_Exception("File '{$file}' is not readable."); } $this->_ffseek($fd); $watchFiles[$watch] = $fd; } else { if (is_dir($file)) { $watchFiles[$watch] = array(); $watchDirs[$watch] = $file; } } } while (($events = inotify_read($inotify)) !== false) { foreach ($events as $event) { if ($event['mask'] & IN_Q_OVERFLOW) { throw new ZtChart_Model_Monitor_Daemon_Exception("The number of inotify queued events reaches upper limit."); } if (!$this->accept($event['name'])) { continue; } if ($event['mask'] & (IN_CREATE | IN_MODIFY)) { if (!($event['mask'] & IN_ISDIR)) { if (!array_key_exists($event['name'], $watchFiles[$event['wd']])) { $fn = $fd = null; foreach ($watchFiles[$event['wd']] as $wfn => $wfd) { if (strncasecmp($wfn, $event['name'], strpos($wfn, '.')) == 0) { $fn = $wfn; $fd = $wfd; break; } } // 判断当前创建或修改的日志文件是否最新 if (strcasecmp($fn, $event['name']) < 0) { if (is_resource($fd) && fclose($fd)) { unset($watchFiles[$event['wd']][$fn]); } $filename = $watchDirs[$event['wd']] . DIRECTORY_SEPARATOR . $event['name']; if (false === ($fd = fopen($filename, "r"))) { $this->_logger->err("File '{$filename}' is not readable\n"); continue; } if ($event['mask'] & IN_MODIFY) { $this->_ffseek($fd); } $watchFiles[$event['wd']][$event['name']] = $fd; } else { // 如果不是最新的日志文件(重写的上一个小时的日志文件),则不处理。 continue; } } else { $fd = $watchFiles[$event['wd']][$event['name']]; } } else { continue; // $fd = $watchFiles[$event['wd']]; } // 读取日志并分析 $raw = ''; $lines = 0; while (true) { $raw .= $block = fread($fd, 4096); if (false !== ($pos = strpos($raw, "\n"))) { $rawline = substr($raw, 0, $pos + 1); try { $mlog = new ZtChart_Model_Monitor_Log($rawline); $line = $mlog->transform(); if (!empty($line)) { $this->_shmWrite($mlog->getShmIdentifier(), $line); $lines++; } } catch (ZtChart_Model_Monitor_Log_Exception $e) { $this->_logger->warn("日志处理错误:" . iconv('GBK', 'UTF-8', $rawline)); } $raw = substr($raw, $pos + 1); } else { if (($offset = strlen($block)) > 0) { fseek($fd, -$offset, SEEK_CUR); } break; } } if (0 != $lines) { $this->_logger->info(sprintf("%4s行有效数据已处理:%s", $lines, $watchDirs[$event['wd']] . '/' . $event['name'])); } } } } foreach ($watchFiles as $watch => $fd) { if (is_resource($fd)) { $fd = (array) $fd; } array_walk($fd, 'fclose'); inotify_rm_watch($inotify, $watch); } fclose($inotify); }