日志分析工具(二分法分段查找处理)

本文介绍了一款针对时间顺序日志文件的二分查找工具,通过PHP脚本实现快速定位及处理特定时间段的日志数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Author: selfimpr

Blog: http://blog.youkuaiyun.com/lgg201

Mail: lgg860911@yahoo.com.cn


需求:日志文件按照时间顺序记录,每次只需要按照时间分析其中某段的日志内容。当此条件下,使用sed,awk等工具是需要扫描全文件的,因此,有了这个小东西,按照文件内容二分查找。

该程序未经测试,有不合理,不正确,性能不佳需要改进的地方,请直言。。。

二分查找库程序:

#! /usr/bin/php
<?php
function binary_find_analysis($filename, $process_func, $compare_func) {
	if( !is_readable($filename) || !function_exists($process_func) || !function_exists($compare_func) ) return false;
	if( !($fp = fopen($filename, 'r')) ) return false;
	$file_size	= filesize($filename);
	$args		= func_get_args();
	$extra_args	= array_slice($args, 3);
	#将文件指针移动到符合条件的首行
	if( !goto_correct_line($fp, $file_size, 0, $file_size, $compare_func, $extra_args) ) return false;
	#读取其后所有匹配条件的行,调用处理函数
	while( ($line = fgets($fp)) && !call_user_func_array($compare_func, build_arguments($extra_args, $line)) ) 
		$process_func($line);
	fclose($fp);
	return true;
}
function build_arguments($extra_args) {
	$args		= func_get_args();
	$other_args	= array_slice($args, 1);
	return array_merge($other_args, $extra_args);
}
function goto_correct_line($fp, $file_size, $begin, $end, $compare_func, $extra_args) {
	#未查找到匹配条件记录
	if($begin >= $end) return false;
	$middle		= floor( ($begin + $end) / 2 );
	fseek($fp, $middle);
	goto_line_head($fp, $file_size);
	$original_pos	= ftell($fp);
	$line			= fgets($fp);
	$current_pos	= ftell($fp);
	$cmp_ret		= call_user_func_array($compare_func, build_arguments($extra_args, $line));
	if( $cmp_ret > 0 ) 
		return goto_correct_line($fp, $file_size, $begin, $original_pos - 1, $compare_func, $extra_args);
	else if( $cmp_ret < 0 ) 
		return goto_correct_line($fp, $file_size, $current_pos, $end, $compare_func, $extra_args);
	else 
		return goto_correct_head($fp, $file_size, $compare_func, $extra_args);
}
function goto_correct_head($fp, $file_size, $compare_func, $extra_args) {
	while( ($tmp_pos = ftell($fp)) && !call_user_func_array($compare_func, build_arguments($extra_args, $line = fgets($fp))) ) {
		fseek($fp, $tmp_pos);
		goto_prev_line_head($fp, $file_size);
	}
	return true;
}
function goto_prev_line_head($fp, $file_size) {
	goto_line_head($fp, $file_size);
	goto_nchar($fp, $file_size, -1);
	goto_line_head($fp, $file_size);
}
function goto_line_head($fp, $file_size) {
	goto_nchar($fp, $file_size, -1);
	while( ftell($fp) && PHP_EOL != fgetc($fp) ) goto_nchar($fp, $file_size, -2);
}
function goto_nchar($fp, $file_size, $n) {
	$offset	= ftell($fp) + $n;
	$offset	= min($file_size, max($offset, 0));
	fseek($fp, $offset);
}

我们的日志格式为:

时间(Y-m-d H:i:s) 日志级别 日志编号 日志内容

下面是根据自己的业务写的一个简单的调用处理

function log_process($data) {
	echo $data;
}
function timecmp($a, $b) {
	preg_match(LOG_PARSE_PATTERN, $a, $matches);
	return floor(strtotime($matches['time']) / 300) - floor($b / 300);
}
define('LOG_PARSE_PATTERN',						'/^(?P<time>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})(?>\s+)(?P<level>(?>\w+))(?>\s+)(?P<number>(?>\d+))(?>\s+)(?P<content>(?>.*))$/');
#为strtotime设置时区
date_default_timezone_set('Asia/Shanghai');
$time	= strtotime('2011-07-28 00:10:00');
binary_find_analysis('log_2011-07-28-00', 'log_process', 'timecmp', $time);


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值