PHP滚动日志的代码实现


Posted in PHP onJune 10, 2015

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  #最新的日志在这个文件中

以上所述就是本文的全部内容了,希望大家能够喜欢。

PHP 相关文章推荐
不用iconv库的gb2312与utf-8的互换函数
Oct 09 PHP
一个用mysql_odbc和php写的serach数据库程序
Oct 09 PHP
PHP远程连接MYSQL数据库非常慢的解决方法
Jul 05 PHP
php 破解防盗链图片函数
Dec 09 PHP
PHP操作Memcache实例介绍
Jun 14 PHP
PHP写日志的实现方法
Nov 05 PHP
PHP.ini安全配置检测工具pcc简单介绍
Jul 02 PHP
WordPress主题中添加文章列表页页码导航的PHP代码实例
Dec 22 PHP
在Yii2中使用Pjax导致Yii2内联脚本载入失败的原因分析
Mar 06 PHP
PHP实现登陆并抓取微信列表中最新一组微信消息的方法
Jul 10 PHP
laravel 自定义常量的两种方案
Oct 14 PHP
PHP7 新增常量
Mar 09 PHP
简单谈谈favicon
Jun 10 #PHP
简单谈谈php中的unicode和utf8编码
Jun 10 #PHP
PHP中生成UUID自定义函数分享
Jun 10 #PHP
php使用for语句输出三角形的方法
Jun 09 #PHP
php生成图片验证码
Jun 09 #PHP
php判断用户是否手机访问代码
Jun 08 #PHP
浅谈PHP中Stream(流)
Jun 08 #PHP
You might like
PHP程序员常见的40个陋习,你中了几个?
2014/11/20 PHP
WordPress特定文章对搜索引擎隐藏或只允许搜索引擎查看
2015/12/31 PHP
php图片上传类 附调用方法
2016/05/15 PHP
Laravel框架查询构造器简单示例
2019/05/08 PHP
php连接sftp的作用以及实例代码
2019/09/23 PHP
动态改变textbox的宽高的js
2006/10/26 Javascript
JavaScript获取网页表单action属性的方法
2015/04/02 Javascript
js 获取元素在页面上的偏移量的方法汇总
2015/04/13 Javascript
js获取当前日期时间及其它操作汇总
2015/04/17 Javascript
JS选中checkbox后获取table内一行TD所有数据的方法
2015/07/01 Javascript
JavaScript中如何使用cookie实现记住密码功能及cookie相关函数介绍
2016/11/10 Javascript
nodejs和C语言插入mysql数据库乱码问题的解决方法
2017/04/14 NodeJs
ES6新特性七:数组的扩充详解
2017/04/21 Javascript
vue 实现通过手机发送短信验证码注册功能
2018/04/19 Javascript
zepto.js 实时监听输入框的方法
2018/12/04 Javascript
es6函数之尾递归用法实例分析
2020/04/25 Javascript
Vue自定义全局弹窗组件操作
2020/08/11 Javascript
[00:32]2018DOTA2亚洲邀请赛OpTic出场
2018/04/03 DOTA
Linux下编译安装MySQL-Python教程
2015/02/02 Python
Python爬取国外天气预报网站的方法
2015/07/10 Python
Python二分查找详解
2015/09/13 Python
利用Python开发微信支付的注意事项
2016/08/19 Python
python实现可下载音乐的音乐播放器
2020/02/25 Python
Python3 ffmpeg视频转换工具使用方法解析
2020/08/10 Python
Python datetime 如何处理时区信息
2020/09/02 Python
Python Pillow(PIL)库的用法详解
2020/09/19 Python
Canvas实现放大镜效果完整案例分析(附代码)
2020/11/26 HTML / CSS
new修饰符是起什么作用
2015/06/28 面试题
会计毕业自我鉴定
2014/02/05 职场文书
新疆民族团结演讲稿
2014/08/27 职场文书
运动会铅球比赛加油稿
2014/09/26 职场文书
检察院院长群众路线教育实践活动个人整改措施
2014/10/04 职场文书
先进个人推荐材料
2014/12/29 职场文书
班主任远程培训研修日志
2015/11/13 职场文书
2016年“六一儿童节”校园广播稿
2015/12/17 职场文书
职工趣味运动会开幕词
2016/03/04 职场文书