前阵子看laravel-admin的demo,偶然发现一个好玩的东西。就是这个日志页:
之前开发后台过程中,总免不了会查看服务器上的log文件,但总觉得麻烦,看到这个就很方便啦!实际上通过log-viewer扩展来实现的。如果想在自己的后台系统也加上这么个模块,几步就可以了。
#安装log-viewer扩展
composer require laravel-admin-ext/log-viewer -vvv
#生成log-viewer模块
php artisan admin:import log-viewer
之后在浏览器中打开如下网址就可以了。
http://xx.xx.xx.xx:xx/admin/logs
我们知道log是以文件形式存在服务器中指定路径下的,log-viewer是做了什么处理让它以表格形式呈现的呢?下面来看下log-viewer源码:
public function fetch($seek = 0, $lines = 20, $buffer = 4096)
{
$f = fopen($this->filePath, 'rb'); //打开一个二进制文件,并返回文件指针
if ($seek) {
fseek($f, abs($seek)); //如果传入的偏移参数不为空,则跳到文件指定偏移位置
} else {
fseek($f, 0, SEEK_END); //否则跳转到文件最后一个字符后面的位置
}
if (fread($f, 1) != "\n") { //从文件偏移位置读取第一个字节
$lines -= 1;
}
fseek($f, -1, SEEK_CUR); //从当前位置往前偏移一位,也就是跳到最后一个字符那
// 从前往后读,上一页
if ($seek > 0) {
$output = '';
$this->pageOffset['start'] = ftell($f); //返回文件指针读/写的位置
while (!feof($f) && $lines >= 0) { //如果文件指针没到最后,且行数>0
$output = $output.($chunk = fread($f, $buffer)); //一次读取文件4096个字节并赋值给$output
$lines -= substr_count($chunk, "\n[20"); //计算日志条数,只统计最近的20条记录
}
$this->pageOffset['end'] = ftell($f); //返回文件指针读/写的位置
while ($lines++ < 0) {
$strpos = strrpos($output, "\n[20") + 1; //找到最新一条日志结束位置
$_ = mb_strlen($output, '8bit') - $strpos; //统计剩余日志的字节数,赋值给$_
$output = substr($output, 0, $strpos); //返回最新一条日志并赋值给$output
$this->pageOffset['end'] -= $_;
}
} else { // 从后往前读,下一页
... //方法大体类似于上面,此处省略
}
fclose($f); //关闭文件指针
return $this->parseLog($output);
}
fetch()方法是将日志文件内容读取到字符串$output中,然后再调用parseLog()方法将字符串解析并赋值给数组:
protected function parseLog($raw)
{
$logs = preg_split('/\[(\d{4}(?:-\d{2}){2} \d{2}(?::\d{2}){2})\] (\w+)\.(\w+):((?:(?!{"exception").)*)?/', trim($raw), -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
foreach ($logs as $index => $log) {
if (preg_match('/^\d{4}/', $log)) {
break;
} else {
unset($logs[$index]);
}
}
if (empty($logs)) {
return [];
}
$parsed = [];
foreach (array_chunk($logs, 5) as $log) {
$parsed[] = [
'time' => $log[0] ?? '',
'env' => $log[1] ?? '',
'level' => $log[2] ?? '',
'info' => $log[3] ?? '',
'trace' => trim($log[4] ?? ''),
];
}
unset($logs);
rsort($parsed);
return $parsed;
}
这里主要就是使用preg_split()方法通过正则表达式分隔字符串生成数组,并对数组做些处理最终返回。
综上,思路就是利用php的一些文件函数对日志文件进行处理,赋值到某个字符串中,然后通过preg_split()方法对字符串进行处理转化成数组形式传给view文件。