日志统一记录方法

<?php
//日志目录位置
defined('REPORT_LOG_PATH') or define('REPORT_LOG_PATH',     $_SERVER['DOCUMENT_ROOT'].'/Application/Runtime/LogReport/');
//项目名
defined('REPORT_APP_NAME') or define('REPORT_APP_NAME',     'api');
//单日志文件大小限制
defined('LOG_FILE_SIZE') or define('LOG_FILE_SIZE',         2097152);       //2MB

// 设定错误和异常处理
error_reporting(0);

LogReport::auto();

class LogReport
{
    static $handler = [
        'finally_except' => ['ThinkThink', 'appException'],
        'finally_error' => ['ThinkThink', 'appError'],
    ];

    static $data = [
        'msg'       => '',// 错误信息 
        'msgCode'   => '',// 自定义错误码 六位数字字符串 etc "100000" 
        'ts'        => '',// 10位整形 时间戳 
        'dateStr'   => '',// 日期 2018-06-28 21:24:09 
        'app'       => '',// 应用名称 
        'serverIp'  => '',// 服务器ip 
        'fileName'  => '',// 文件名 
        'lineNo'    => '',// 行数 
        'method'    => '',// 函数名 
    ];

    /**
     * 自动注册
     * @return [type] [description]
     */
    static function auto()
    {
        if (defined('APP_PATH')) {
            self::register();
            self::set();
        } else {
            self::$handler = array_map(function($v){
                return [];
            }, self::$handler);
        }
    }

    /**
     * 注册致命错误
     * @return [type] [description]
     */
    static function register()
    {
        register_shutdown_function('LogReport::fatalError');
    }

    /**
     * 设置处理方法
     */
    static function set()
    {
        set_error_handler('LogReport::appError');
        set_exception_handler('LogReport::exception');
    }

    /**
     * 错误数据格式
     * @param  string|array     $e      错误内容|'message','file','line','code','method'
     * @param  string           $file   错误文件
     * @param  string           $line   错误行数
     * @param  string           $code   错误码
     * @param  string           $method 错误函数
     * @return [type]           [description]
     */
    static function anlyError($e, $file = null, $line = null, $code = null, $method = null)
    {
        if (!is_array($e)) {
            $e = [
                'message' => $e,
                'file' => !is_null($file) ? $file : '',
                'line' => !is_null($line) ? $line : '',
                'code' => !is_null($code) ? $code : '',
                'method' => !is_null($method) ? $method : '',
            ];
        }
        $data               = self::$data;
        $data['msg']        = !empty($e['message']) ? $e['message'] : '';
        $data['msgCode']    = str_pad($e['code'], 6, '0', STR_PAD_LEFT);
        $data['ts']         = time();
        $data['dateStr']    = date('Y-m-d H:i:s');
        $data['app']        = REPORT_APP_NAME;
        $data['serverIp']   = $_SERVER['REMOTE_ADDR'];
        $data['fileName']   = !empty($e['file']) ? $e['file'] : '';
        $data['lineNo']     = !empty($e['line']) ? $e['line'] : '';
        $data['method']     = !empty($e['method']) ? $e['method'] : '';
        return $data;
    }

    /**
     * 致命错误处理
     * @return [type] [description]
     */
    static function fatalError()
    {
        if ($e = error_get_last()) {
            switch ($e['type']) {
                case E_ERROR:
                case E_PARSE:
                case E_CORE_ERROR:
                case E_COMPILE_ERROR:
                case E_USER_ERROR:
                    ob_end_clean();
                    self::write(self::anlyError($e));
                    break;
            }
        }
        // exit();
    }

    /**
     * 一般错误处理
     * @param  [type] $errno   [description]
     * @param  [type] $errstr  [description]
     * @param  [type] $errfile [description]
     * @param  [type] $errline [description]
     * @return [type]          [description]
     */
    static function appError($errno, $errstr, $errfile, $errline)
    {
        switch ($errno) {
            case E_ERROR:
            case E_PARSE:
            case E_CORE_ERROR:
            case E_COMPILE_ERROR:
            case E_USER_ERROR:
                self::write(self::anlyError($errstr , $errfile, $errline));
                break;
        }
        if (!empty(self::$handler['finally_error'])) {
            call_user_func(self::$handler['finally_error'], $errno, $errstr, $errfile, $errline);
        }
    }

    /**
     * 异常处理
     * @return [type] [description]
     */
    static function exception($e)
    {
        self::write(self::anlyError($e->getMessage() , $e->getFile(), $e->getLine()));
        if (!empty(self::$handler['finally_except'])) {
            call_user_func(self::$handler['finally_except'], $e);
        }
    }

    /**
     * 日志记录
     * @param  string $log 日志内容
     * @return [type]      [description]
     */
    static function write($log)
    {
        if (is_array($log)) {
            $log = json_encode($log);
        }
        if (empty($log)) {
            return false;
        }
        // 自动创建日志目录
        if (!is_dir(REPORT_LOG_PATH)) {
            mkdir(REPORT_LOG_PATH, 0755, true);
        }
        $name = date('Ymd');
        $filename = REPORT_LOG_PATH.$name.'.log';
        //检测日志文件大小,超过配置大小则备份日志文件重新生成
        if (is_file($filename) && floor(LOG_FILE_SIZE) <= filesize($filename)) {
            rename($filename, dirname($filename) . '/' . $name. '-' . time() . '.log');
        }
        $log .= PHP_EOL;
        return file_put_contents($filename, $log, FILE_APPEND);
    }
}

原文地址:https://www.cnblogs.com/jiangzuo/p/9328775.html