PHP 롤링 로그

WBOY
WBOY원래의
2016-08-08 09:24:231382검색

PHP 롤링 로그 라이브러리

PHP는 로그를 기록하는 방법에 대해 폴더를 연도, 월별로 나누고, 파일을 날짜별로 나누는 방법에 대해 알아봤습니다. 이 방법에는 장단점이 있으며 사용 시나리오도 있습니다. 오늘날은 또 다른 방법입니다. 로그를 기록하는 파일 롤링 방법입니다. 물론 이 롤링 메커니즘은 이전 로깅 방법에 추가될 수도 있습니다.

로그 스크롤 방법

롤링 로그는 이름에서 알 수 있듯이 일련의 로그 파일을 사용하여 모듈의 로그를 기록합니다. 동일한 모듈에 있는 파일 수는 최대 maxNum으로 제한되며 크기도 최대 maxSize로 제한됩니다. 파일 이름에는 testlog.log, testlog_1.log, testlog_2.log,,,,,와 같은 특정 명명 방법이 있습니다. 여기서 testlog.log는 testlog.log 파일 크기에 도달할 때 사용되는 로그 파일입니다. maxSize 제한을 초과하면 로그 파일이 다음과 같이 역방향으로 롤백됩니다.

<code>testlog_2.log 	-> testlog_3.log
testlog_1.log 	-> testlog_2.log
testlog.log 	-> testlog_1.log
testlog.log #0kb</code>

로그 파일 수가 maxNum 제한에 도달하면 제거 메커니즘이 시작되고 가장 오래된 로그가 삭제됩니다. 예를 들어 maxNum이 10으로 설정된 경우 testlog.log를 포함하여 최대 10개의 파일이 있습니다. 이때 스크롤할 때 testlog_9.log가 있으면 testlog_8.log에서 롤링을 시작하고 testlog_9.log를 덮어씁니다. 이렇게 하면 정상적인 로그 기록이 보장되고 매우 큰 로그 파일이 나타나지 않아 로그 시스템이 정상적으로 작동합니다.

코드 구현

<code><?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");
		}
	}
}</code>

예시 보기

<code>#例子中设置记录级别为msg(此时debug信息是不会纪录的),日志文件个数为5,大小为200个字节(测试方便),文件名称为testlog
$logs = LOGS::getInstance();
$logs->init(1, 5, 200, "./", 'testlog');

$logs->msg("YRT", __FILE__, __LINE__);
$logs->debug("YRT", __FILE__, __LINE__);</code>

이 예제를 계속 실행하면 코드가 위치한 폴더에 다음과 같이 5개의 파일이 생성됩니다.

<code>testlog_4.log
testlog_3.log
testlog_2.log
testlog_1.log
testlog.log			#最新的日志在这个文件中</code>

위의 내용은 PHP 롤링 로그를 소개하며, PHP 튜토리얼에 관심이 있는 친구들에게 도움이 되기를 바랍니다.

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.