日志对象
转载来源
class Logger
{
private $FileName, $When, $Size, $BackupCount;
private $SuffixFormat = [
'H' => 'Y-m-d_H',
'D' => 'Y-m-d',
'W' => 'Y-m-d',
'M' => 'Y-m'
];
/**
* 获取日志类对象
* @param string $fileName 日志文件名,可以带路径,不存在的目录将被创建
* @return object
*/
public static function getLogger($fileName)
{
return new Logger($fileName);
}
/**
* 获取按时间分割的日志类对象
* @param string $fileName 日志文件名,可以带路径,不存在的目录将被创建
* @param string $when 分割的时间单位 H 每小时, D 每天, W 每周, M 每月
* @param integer $backupCount 文件备份数量,默认全部,超出将会删除旧的文件
* @return object
*/
public static function getTimedRotatingLogger($fileName, $when = 'D', $backupCount = 0)
{
$logger = new Logger($fileName);
$logger->setTimedRotating($when, abs(intval($backupCount)));
return $logger;
}
/**
* 获取按文件大小分割的日志类对象
* @param string $fileName 日志文件名,可以带路径,不存在的目录将被创建
* @param integer $size 分割的文件大小,单位(kb)
* @param integer $backupCount 文件备份数量,默认全部,超出将会删除旧的文件
* @return object
*/
public static function getSizedRotatingLogger($fileName, $size = 1024, $backupCount = 0)
{
$logger = new Logger($fileName);
$logger->setSizedRotating(abs(intval($size)), abs(intval($backupCount)));
return $logger;
}
private function setTimedRotating($when, $backupCount)
{
$this->When = $when;
$this->BackupCount = $backupCount;
}
private function setSizedRotating($size, $backupCount)
{
$this->Size = $size;
$this->BackupCount = $backupCount;
}
/**
* 初始化配置
* @param string $fileName 日志文件名
*/
public function __construct($fileName)
{
$this->FileName = $fileName;
}
/**
* 写入信息日志
* @param String $msg 日志消息
* @return Boolean
*/
public function info($msg)
{
return $this->write('INFO', $msg);
}
/**
* 写入警告日志
* @param String $msg 日志消息
* @return Boolean
*/
public function warn($msg)
{
return $this->write('WARN', $msg);
}
/**
* 写入警告日志
* @param String $msg 日志消息
* @return Boolean
*/
public function debug($msg)
{
return $this->write('DEBUG', $msg);
}
/**
* 写入错误日志
* @param String $msg 日志消息
* @return Boolean
*/
public function error($msg)
{
return $this->write('ERROR', $msg);
}
/**
* 写入日志
* @param String $type 日志类型
* @param String $msg 日志消息
* @return Boolean
*/
private function write($type, $msg)
{
$fileName = $this->FileName;
// 设置日志文件名
$this->When && $fileName = $this->getTimedFileName();
$this->Size && $fileName = $this->getSizedFileName();
// 清理备份日志
$this->BackupCount && $this->clearLogFile();
// 创建日志目录
$isCreate = $this->createLogPath();
echo $msg."\n";
// 日志内容
$msg = sprintf('[%s] %-5s %s : %s' . PHP_EOL, date('Y-m-d H:i:s'), $type, get_current_user(), $msg);
// 写入日志文件
if ($isCreate) {
return file_put_contents($fileName, $msg, FILE_APPEND);
}
return false;
}
/**
* 清理超出备份数量的旧日志文件
* @return boolean 清理结果
*/
private function clearLogFile()
{
$files = $this->getAsortFileByTime();
$fileCnt = count($files);
if ($fileCnt <= $this->BackupCount) {
return true;
}
$cnt = 0;
$result = true;
foreach ($files as $file) {
$result &= unlink($file['name']);
if (++$cnt == $fileCnt - $this->BackupCount) {
break;
}
}
return $result;
}
/**
* 获取根据修改时间升序排序的文件
* @return array
*/
private function getAsortFileByTime()
{
$name = explode('.', basename($this->FileName))[0];
$fold = dirname($this->FileName);
$result = glob("$fold/$name*");
$files = [];
foreach ($result as $i => $file) {
$files[$i]['name'] = $file;
$files[$i]['time'] = filemtime($file);
}
uasort($files, function ($f1, $f2) {
return $f1['time'] - $f2['time'];
});
return $files;
}
/**
* 获取按时间分割的文件名
* @return string
*/
private function getTimedFileName()
{
$name = basename($this->FileName);
$pos = strrpos($name, '.');
!isset($this->SuffixFormat[$this->When]) && $this->When = 'D';
$suffix = date($this->SuffixFormat[$this->When]);
$files = $this->getAsortFileByTime();
$lastFile = end($files);
$newFileName = dirname($this->FileName) . '/' . ($pos ? substr($name, 0, $pos) . $suffix . substr($name, $pos) : $name . $suffix);
return $this->When == 'W' && $lastFile && time() - $lastFile['time'] > 7 * 24 * 3600 || $this->When != 'W' ? $newFileName : $lastFile['name'];
}
/**
* 获取按文件大小分割的文件名
* @return string
*/
private function getSizedFileName()
{
$files = $this->getAsortFileByTime();
$lastFile = end($files);
$fileName = $this->FileName;
if ($lastFile && filesize($lastFile['name']) > 1024 * $this->Size) {
$this->When = 'S';
$this->SuffixFormat['S'] = 'Y-m-d_H-i-s';
$fileName = $this->getTimedFileName();
} else if ($lastFile) {
$fileName = $lastFile['name'];
}
return $fileName;
}
/**
* 创建日志目录
* @return Boolean
*/
private function createLogPath()
{
$path = dirname($this->FileName);
if (!is_dir($path)) {
return mkdir($path, 0777, true);
}
return true;
}
}
获取日志对象
$fileName = 'logging/test.log';
$logger = Logger::getLogger($fileName); // 普通日志
$sizedLogger = Logger::getSizedRotatingLogger($fileName, 5, 3); // 按文件大小分割的日志,超过5KB分割,保留最新的三个日志文件
$timedLogger = Logger::getTimedRotatingLogger($fileName, 'H'); // 按时间分割的日志,按小时分割,保留所有日志
普通日志测试
// 普通日志测试
for ($i = 0;$i < 10;$i++) {
$logger->info('test info');
$logger->warn('test warn');
$logger->error('test error');
$logger->debug('test debug');
}
按文件大小分割的日志测试
// 按文件大小分割的日志测试
for ($i = 0;$i < 600;$i++) {
$sizedLogger->info('test info');
$i % 100 == 0 && sleep(1);
}
按时间分割的日志测试
// 按时间分割的日志测试
for ($i = 0;$i < 100;$i++) {
$timedLogger->info('test info');
}