php 日志按照 文件大小 按照时间 切割

作者: cayman 分类: 未分类 发布时间: 2022-03-25 11:15

可以直接使用 composer 包 composer require drcayman/custom_logs

abstract class AbstractConsumer
{
    /**
     * 发送一条消息, 返回true为send成功。
     * @param string $message 发送的消息体
     * @return bool
     */
    public abstract function send($message);

    /**
     * 立即发送所有未发出的数据。
     * @return bool
     */
    public function flush()
    {
        return true;
    }

    /**
     * 关闭 Consumer 并释放资源。
     * @return bool
     */
    public abstract function close();
}

/**
 * 批量实时写本地文件,文件以天为分隔 不支持多线程
 */
class FileConsumer extends AbstractConsumer
{
    private $fileHandler;
    private $fileName;
    private $fileDirectory;
    private $filePrefix;
    private $fileSize;
    private $rotateHourly;

    /**
     * 创建指定文件保存目录和指定单个日志文件大小的 FileConsumer
     * 默认是按天切分,无默认大小切分
     * @param string $file_directory 日志文件保存目录. 默认为当前目录
     * @param int $file_size 单个日志文件大小. 单位 MB, 无默认大小
     * @param bool $rotate_hourly 是否按小时切分文件
     * @param string $file_prefix 生成的日志文件前缀
     */
    function __construct($file_directory = '.', $file_size = 0, $rotate_hourly = false, $file_prefix = '')
    {
        $this->fileDirectory = $file_directory;
        if (!is_dir($file_directory)) {
            mkdir($file_directory, 0777, true);
        }
        $this->fileSize = $file_size;
        $this->rotateHourly = $rotate_hourly;
        $this->filePrefix = $file_prefix;
        $this->fileName = $this->getFileName();
    }

    /**
     * 消费数据,将数据追加到本地日志文件
     * @param $message
     * @return bool|int
     */
    public function send($message)
    {
        $file_name = $this->getFileName();
        if ($this->fileHandler != null && $this->fileName != $file_name) {
            $this->close();
            $this->fileName = $file_name;
            $this->fileHandler = null;
        }
        if ($this->fileHandler === null) {
            $this->fileHandler = fopen($file_name, 'a+');
        }
        if (flock($this->fileHandler, LOCK_EX)) {
            $result = fwrite($this->fileHandler, $message . "\n");
            flock($this->fileHandler, LOCK_UN);
            return $result;
        }
    }

    public function close()
    {
        if ($this->fileHandler === null) {
            return false;
        }
        return fclose($this->fileHandler);
    }

    private function getFileName()
    {
        $date_format = $this->rotateHourly ? 'Y-m-d-H' : 'Y-m-d';
        $file_prefix = $this->filePrefix == '' ? '' : $this->filePrefix . '.';
        $file_base = $this->fileDirectory . '/' . $file_prefix . 'log.' . date($date_format, time()) . "_";
        $count = 0;
        $file_complete = $file_base . $count;
        if ($this->fileSize > 0) {
            while (file_exists($file_complete) && $this->fileSizeOut($file_complete)) {
                $count += 1;
                $file_complete = $file_base . $count;
            }
        }
        return $file_complete;
    }

    public function fileSizeOut($fp)
    {
        clearstatcache();
        $fpSize = filesize($fp) / (1024 * 1024);
        if ($fpSize >= $this->fileSize) {
            return true;
        } else {
            return false;
        }
    }
}

发表回复

您的电子邮箱地址不会被公开。