PHP滚动日志的代码实现
程序员文章站
2022-03-23 16:54:44
php滚动日志类库
php记录日志,我之前接触过的有按照年月分文件夹,然后按照日分文件的日志记录方式,这种方式有利有弊,有他的使用场景,我今天要说的是另一种日志记录方式—...
php滚动日志类库
php记录日志,我之前接触过的有按照年月分文件夹,然后按照日分文件的日志记录方式,这种方式有利有弊,有他的使用场景,我今天要说的是另一种日志记录方式——文件滚动方式记录日志,当然了,这种滚动机制也可以加在前面那种日志记录方式中。
如何让日志滚动起来
滚动日志,顾名思义,记录一个模块的日志用一系列的日志文件,同一模块文件个数有限制,最多maxnum个,大小也有限制,最大maxsize字节,文件名有一定的命名方式,比如:testlog.log、testlog_1.log,testlog_2.log、、、、、、其中testlog.log是正在使用的日志文件,当testlog.log文件大小到达限制maxsize的时候就会向后滚动日志文件,就像下面这样:
复制代码 代码如下:
testlog_2.log -> testlog_3.log
testlog_1.log -> testlog_2.log
testlog.log -> testlog_1.log
testlog.log #0kb
当日志文件个数到达限制maxnum的时候就会启动淘汰机制,删除最老的日志,比如说maxnum设置为10,这个时候算上testlog.log一共最多有10个文件,当滚动的时候如果存在testlog_9.log就会从testlog_8.log开始滚动,覆盖掉testlog_9.log,这样就可以保证日志正常记录,而且不会出现很大很大的日志文件,保证日志系统的正常运行。
代码实现
<?php final class logs { private $level; private $maxfilenum; private $maxfilesize; private $logpath; private $file; //日志的级别debug,msg,err const logs_debug = 0; const logs_msg = 1; const logs_err = 2; private static $instance = null; private function __construct(){} public static function getinstance() { if(self::$instance == null) { self::$instance = new self(); } return self::$instance; } /** * @desc 初始化 * @param $level int 记录级别 * @param $maxnum int 最大日志文件数目 * @param $maxsize int 最大日志文件大小 * @param $logpath string 日志文件保存路径 * @param $file string 日志文件名称前缀 * @return boolean */ public function init($level, $maxnum, $maxsize, $logpath, $file) { $level = intval($level); $maxnum = intval($maxnum); $maxsize = intval($maxsize); !is_dir($logpath) && mkdir($logpath, 0777, true); if(!in_array($level, array(self::logs_debug, self::logs_msg, self::logs_err)) || $maxnum <= 0 || $maxsize <= 0 || !is_dir($logpath)) { return false; } $this->level = $level; $this->maxfilenum = $maxnum; $this->maxfilesize = $maxsize; $this->logpath = $logpath; $this->file = $file; return true; } /** * @desc 获取格式化时间串 */ public function formattime() { $ustime = explode ( " ", microtime () ); return "[" . date('y-m-d h:i:s', time()) .".". ($ustime[0] * 1000) . "]"; } /** * @desc 滚动方式记录日志文件 */ public function log($str) { $path = $this->logpath.directory_separator.$this->file.".log"; clearstatcache(); if(file_exists($path)) { if(filesize($path) >= $this->maxfilesize) { $index = 1; //获取最大的滚动日志数目 for(;$index < $this->maxfilenum; $index++) { if(!file_exists($this->logpath.directory_separator.$this->file."_".$index.".log")) { break; } } //已经存在maxfilenum个日志文件了 if($index == $this->maxfilenum) { $index--; } //滚动日志 for(;$index > 1; $index--) { $new = $this->logpath.directory_separator.$this->file."_".$index.".log"; $old = $this->logpath.directory_separator.$this->file."_".($index - 1).".log"; rename($old, $new); } $newfile = $this->logpath.directory_separator.$this->file."_1.log"; rename($path, $newfile); } } $fp = fopen($path, "a+b"); fwrite($fp, $str, strlen($str)); fclose($fp); return true; } /** * @desc 记录调试信息 * @param string 日志信息 * @param string 日志所在文件 * @param string 日志所在行 */ public function debug($msg, $file, $line) { if($this->level <= self::logs_debug) { $this->log($this->formattime()."[{$file}:{$line}]debug: ${msg}\n"); } } /** * @desc 记录信息 * @param string 日志信息 * @param string 日志所在文件 * @param string 日志所在行 */ public function msg($msg, $file, $line) { if($this->level <= self::logs_msg) { $this->log($this->formattime()."[{$file}:{$line}]msg: ${msg}\n"); } } /** * @desc 记录错误信息 * @param string 日志信息 * @param string 日志所在文件 * @param string 日志所在行 */ public function err($msg, $file, $line) { if($this->level <= self::logs_err) { $this->log($this->formattime()."[{$file}:{$line}]err: ${msg}\n"); } } }
看个例子
#例子中设置记录级别为msg(此时debug信息是不会纪录的),日志文件个数为5,大小为200个字节(测试方便),文件名称为testlog
$logs = logs::getinstance(); $logs->init(1, 5, 200, "./", 'testlog'); $logs->msg("yrt", __file__, __line__); $logs->debug("yrt", __file__, __line__);
当我们不停的运行这个例子的时候,会在代码所在文件夹下生成5个文件就像下面这样:
testlog_4.log testlog_3.log testlog_2.log testlog_1.log testlog.log #最新的日志在这个文件中
以上所述就是本文的全部内容了,希望大家能够喜欢。