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滚动日志的更多相关文章

  1. C/S系统实现两数求和(非阻塞+epoll+心跳包检测用户在线状况+滚动日志+配置文件.)

    C/S系统实现两数求和 任务要求: 实现配置文件 实现日志滚动 设置非阻塞套接字,EPOLL实现 检测客户端的连接,设置心跳检测 主线程 + 心跳检测线程 + EPOLL的ET模式处理事务线程 注意事 ...

  2. 在windows实现nginx滚动日志

    nginx自身并不能够切分或滚动日志,因此只能用一个bat脚本按天切割日志,并删除三天前的日志 @echo off rem nginx滚动日志 rem nginx工作目录 set workspace= ...

  3. logrus 剖析之滚动日志

    在实际开发过程中,为了节省磁盘,日志需要按照时间或者大小维度进行切割分成多分,归档过期的日志,删除久远的日志.这个就是在日常开发中经常遇见的日志滚动(log rotation) 那么在 logrus ...

  4. Python selenium chrome打包exe后禁用控制台输出滚动日志

    Python selenium chrome打包exe后,在运行的过程中,如果遇到需要input()输入时,会发现被不断滚动刷新的日志把命令行输入快速顶掉了,通过查阅资料不断实践,发现以下方法有效: ...

  5. Django多进程滚动日志的问题

    使用RotatingFileHandler控制日志文件的大小 # settings.py LOGGING = { ... 'handlers': { ... 'file': { 'level': 'I ...

  6. log4go的日志滚动处理——适应生产环境的需要

    日志处理有三类使用环境,开发环境DE,测试环境TE,生产环境PE. 前两类可以看成是一类,重要的是屏幕显示--termlog.生产环境中主要用的是socklog 和 filelog,即网络传输日志和文 ...

  7. 滚动 docker 中的 nginx 日志

    Nginx 自己没有处理日志的滚动问题,它把这个球踢给了使用者.一般情况下,你可以使用 logrotate 工具来完成这个任务,或者如果你愿意,你可以写各式各样的脚本完成同样的任务.本文笔者介绍如何滚 ...

  8. 使用Linux自带日志滚动工具logrotate滚动redis日志示例

    截至到redis-5.0版本,redis仍然不会自动滚动日志文件,如果不处理则日志文件日积月累越来越大,最终将导致磁盘满告警: # ls -lh total 12G -rw-r--r-- 1 redi ...

  9. Nginx插件之openresty反向代理和日志滚动配置案例

    Nginx插件之openresty反向代理和日志滚动配置案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.openresty介绍 1>.Nginx介绍 Nginx是一款 ...

随机推荐

  1. struts2和spring3.2的整合 详细演示

    1.首先我们新建一个Web工程,如下: 2.导入Spring和Struts2的jar包. 其中,struts2-spring-plugin-2.1.8.jar是struts2.spring整合的关键. ...

  2. matlab jet color mapping C / C++ / VC 实现

    在matlab中调用imagesc()将一幅灰阶图像以彩色显示时,默认使用的color mapping是Jet,其color bar 为: Jet的color mapping图为: Color map ...

  3. 移动端调试利器 JSConsole 介绍

    先看这篇文章 Web应用调试:现在是Weinre和JSConsole,最终会是WebKit的远程调试协议. 我们先不看未来,从此文可见,当下的移动端调试还是 Weinre 和 JSConsole 的天 ...

  4. 各种主流 SQLServer 迁移到 MySQL 工具对比

          我之所以会写这篇对比文章,是因为公司新产品研发真实经历过这个痛苦过程(传统基于SQL Server开发的C/S产品转为MySQL云产品).首次需要数据转换是测试环节,当时为了快速验证新研发 ...

  5. C++学习准则

    C++学习准则  1.把C++当成一门新的语言学习(和C没啥关系!真的): 2.看<Thinking In C++>,不要看<C++变成死相>(C++编程思想,翻译的非常差): ...

  6. 备忘:hibernate, logback, slf4j实际应用一例

    用hibernate写一些简单的数据库的Java应用.主要是温习一下.之前弄过的一些都忘了.发现还是得记下来,不然很快就忘. 1. Eclipse版本,用Juno, J2EE版本.最好下载zip版本的 ...

  7. 使textarea支持tab缩进

    //textarea支持tab缩进 $("textarea").on( 'keydown', function(e) { if (e.keyCode == 9) { e.preve ...

  8. 东大OJ-1391-Big big Power

    题目描述 Calculate the power num a^(b^c) mod 1e9+7 输入 Multiple test cases,each case has three integers a ...

  9. python 英文字串首字母改为大写

    #英文字串首字母改为大写 st = "string" St = st[0].upper() + st[1:] 2016-10-22 后来了解到 python 内部有相关实现,感觉  ...

  10. python环境搭建-Linux系统下python2.6.6升级python3.5.2步骤

    [root@template ~]# python -v # /usr/lib64/python2.6/encodings/utf_8.pyc matches /usr/lib64/python2.6 ...