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 相关文章推荐
图片存储与浏览一例(Linux+Apache+PHP+MySQL)
Oct 09 PHP
PHP HTML代码串 截取实现代码
Jun 29 PHP
PHP正则表达式之定界符和原子介绍
Oct 05 PHP
php文件上传的简单实例
Oct 19 PHP
PHP获取数组中重复最多的元素的实现方法
Nov 11 PHP
详谈PHP编码转换问题
Jul 28 PHP
PHP实现获取某个月份周次信息的方法
Aug 11 PHP
php基础设计模式大全(注册树模式、工厂模式、单列模式)
Aug 31 PHP
PHP explode()函数的几个应用和implode()函数有什么区别
Nov 05 PHP
PHP函数nl2br()与自定义函数nl2p()换行用法分析
Apr 02 PHP
PHP查询大量数据内存耗尽问题的解决方法
Oct 28 PHP
PHP调用微博接口实现微博登录的方法示例
Sep 22 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连接SQLServer2005方法及代码
2013/12/26 PHP
CI框架中zip类应用示例
2014/06/17 PHP
浅析php适配器模式(Adapter)
2014/11/25 PHP
ThinkPHP路由详解
2015/07/27 PHP
PHP 表单提交及处理表单数据详解及实例
2016/12/27 PHP
TP5框架实现上传多张图片的方法分析
2020/03/29 PHP
JQuery文本框高亮显示插件代码
2011/04/02 Javascript
JavaScript获取FCK编辑器信息的具体方法
2013/07/12 Javascript
jquery解析xml字符串示例分享
2014/03/25 Javascript
js 实现的可折叠留言板(附源码下载)
2014/07/01 Javascript
使用jQuery实现返回顶部
2015/01/26 Javascript
JavaScript正则替换HTML标签功能示例
2017/03/02 Javascript
BootStrap注意事项小结(五)表单
2017/03/10 Javascript
解决jQuery ajax动态新增节点无法触发点击事件的问题
2017/05/24 jQuery
对类Vue的MVVM前端库的实现代码
2018/09/07 Javascript
JavaScript函数的4种调用方法实例分析
2019/03/05 Javascript
基于ts的动态接口数据配置的详解
2019/12/18 Javascript
es6数组的flat(),flatMap()函数用法实例分析
2020/04/18 Javascript
在Vue中获取自定义属性方法:data-id的实例
2020/09/09 Javascript
vue 函数调用加括号与不加括号的区别
2020/10/29 Javascript
[47:20]DAC2018 4.4 淘汰赛 Optic vs Mineski 第一场
2018/04/05 DOTA
Python魔术方法详解
2015/02/14 Python
python实现telnet客户端的方法
2015/04/15 Python
python实现逆波兰计算表达式实例详解
2015/05/06 Python
将字典转换为DataFrame并进行频次统计的方法
2018/04/08 Python
python mysql 字段与关键字冲突的解决方式
2020/03/02 Python
Python新手学习raise用法
2020/06/03 Python
python os模块在系统管理中的应用
2020/06/22 Python
Python gevent协程切换实现详解
2020/09/14 Python
2014年圣诞节倒计时网页的制作过程
2014/12/05 HTML / CSS
外企财务年会演讲稿
2014/01/03 职场文书
四议两公开实施方案
2014/03/28 职场文书
房屋买卖授权委托书
2014/09/27 职场文书
2015年会计个人工作总结
2015/04/02 职场文书
初一年级组工作总结
2015/08/12 职场文书
比较node.js和Deno
2021/04/27 Javascript