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. 东大OJ-1430-PrimeNumbers

    题目描述 I'll give you a number , please tell me how many different prime factors in this number. 输入 The ...

  2. 如何解决xml在eclipse下的拼写报错

    进入preferences——键入“spelling”——看到勾选框:Enable spelling check,去掉勾选框,可消除eclipse下的拼写错误

  3. java 常用的一些关键字

    1.关键字extends 1.继承作用 优化代码,减少代码的重复使用. 2.继承使用时机 两个类之间必须要满足is a的关系 ,才能够拥有继承关系,不是任 何 情况下都允许继承 3.继承的使用注意事项 ...

  4. void与void之间没有隐式转换(纯属恶搞,请勿在意)

    强大的vs弹出了这个提示:.有没有觉得强大的vs不应该出现该提示. 但就是出现了. 看客,您知道怎么让vs弹出这个提示吗^~^

  5. 个人阅读作业——M1/M2总结

    ~ http://www.cnblogs.com/wx1306/p/4831950.html 在这篇博客中,我提出来一些关于软件工程的问题,但随着这一个学期的即将结束,以及我对软件开发的了解的深入,我 ...

  6. 9.29判断变量x是奇数还是偶数

    方法一: package qqq; public class Jiou { public static void main(String[] args) { // TODO Auto-generate ...

  7. SVM与LR的区别以及SVM的优缺点

    对于异常数据,SVM比LR更好 SVM的优缺点: 优点:1.提供非常精确的分类器 2.更少的过拟合(因为有L2正则化项0.5||w||2),对噪声数据更加鲁棒(因为损失函数的原因) 缺点:1.SVM是 ...

  8. Get it,你离几何达人不远了!

    对于爱学几何的人,是否存在这样的困扰:没有标准的尺规工具,图形画的不标准,理解上总是出错......整天在纸上画图,浪费大把大把的时间......几何图形画的不美观,在别人面前都拿不出手,公开课上都没 ...

  9. 在ORACLE触发器里调用JAVA程序

    因为项目需要,有一个已经写好的Java程序,想要在Oracle某个表的触发器中调用,以使得每次数据更新时,调用这个JAVA程序,来修改后台某个数据. 现将过程记录如下: 1.编写JAVA程序 publ ...

  10. 如何使用maven建一个web3.0的项目

    使用eclipse手动建一个maven的web project可能会有版本不合适的情况,例如使用spring的websocket需要web3.0什么的,不全面的修改可能会出现各种红叉,甚是苦恼.我从我 ...