自定义CILog日志类的使用(php的CI框架的日志类)

来源:互联网 发布:置乱算法 arnold 编辑:程序博客网 时间:2024/06/05 16:45

参见:http://www.phpnotes.top/2017/11/24/php/40/

1、  将CILog复制到application下的core文件夹下,并且以自定义前缀_开头,例如MY_CILog

<?php


/**
 * 日志模块
 * @author caisicen
 * @date 2017-08-23
 */
class MY_CILog {


    private $_log_path; //日志文件存放路径
    private $_date_path; //此刻记录日志存放的文件夹
    private $_file_permissions; //日志文件权限
    private $_date_fmt; //存放格式
    private $_enabled; //是否开启日志记录
    private $_threshold; //日志记录级别
    private $_levels; //级别对应值
    private $_debugInfo; //是否开启详细调试信息
    private $_allLog_controller; //包含的控制器将会记录所有的日志级别记录


    public function __construct() {
        $this->_file_permissions = 0644;
        $this->_date_fmt = 'Y-m-d H:i:s';
        $this->_enabled = TRUE;
        $this->_threshold = 1;
        $this->_levels = array('ERROR' => 1, 'DEBUG' => 2, 'INFO' => 3, 'ALL' => 4);
        $this->_debugInfo = TRUE;
        $this->_allLog_controller = array();
        $config = & get_config(); //获取config配置信息
        $this->_log_path = ($config['CILog_path'] !== '') ? $config['CILog_path'] : APPPATH . 'CIlogs/'; //日志文件夹根目录地址
        if (!$this->_mkdir()) //创建日志存放结构失败或者不可写,则不记录日志
            $this->_enabled = FALSE;
        if (is_numeric($config['CILog_threshold'])) { //获取配置文件的日志记录级别
            $this->_threshold = (int) $config['CILog_threshold'];
        }
        if (!empty($config['CILog_date_fmt'])) { //获取日志记录的时间格式
            $this->_date_fmt = $config['CILog_date_fmt'];
        }
        if (!empty($config['CILog_file_permissions']) && is_int($config['CILog_file_permissions'])) { //获取生成文件的文件去那些
            $this->_file_permissions = $config['CILog_file_permissions'];
        }
        $this->_debugInfo = $config['CILog_debugInfo']; //是否开启调试信息和浏览器信息
        !empty($config['CILog_allLog_controller']) && $this->_allLog_controller = $config['CILog_allLog_controller']; //是否有特殊控制器
        if (!empty($this->_allLog_controller)) { //将特殊控制器中的所有值转为小写
            foreach ($this->_allLog_controller as &$controller) {
                $controller = strtolower($controller);
            }
        }
    }


    /**
     * 记录日志
     * @param type $level 级别
     * @param type $msg 日志内容
     * @param type $onlyMain 是否只将日志记入主流程
     */
    public function write_log($level, $msg, $onlyMain = false) {


        $level = strtoupper($level);


        if ($this->_enabled === FALSE) { //文件夹创建失败或者无法读取,则失败
            return FALSE;
        }


        //根据配置文件判断是否记录此类型的日志
        if ((!isset($this->_levels[$level]) OR (
                ($this->_levels[$level] > $this->_threshold) && !in_array(strtolower(REQUEST_CLASS), $this->_allLog_controller) ))) {
            return FALSE;
        }


        $mainfilePath = $this->_date_path . 'Main.log'; //main Log的存放路径
        $filePath = $this->_date_path . 'Class-' . REQUEST_CLASS . '.log'; //当前控制器的存放路径
        $message = ''; //待写入的日志内容
        //根据配置文件的日期参数获取写入文件的日期格式内容
        if (strpos($this->_date_fmt, 'u') !== FALSE) {
            $microtime_full = microtime(TRUE);
            $microtime_short = sprintf("%06d", ($microtime_full - floor($microtime_full)) * 1000000);
            $date = new DateTime(date('Y-m-d H:i:s.' . $microtime_short, $microtime_full));
            $date = $date->format($this->_date_fmt);
        } else {
            $date = date($this->_date_fmt);
        }


        //判断是否第一次生成文件
        if (!is_file($mainfilePath)) {
            $notMainFile = true;
        }
        if (!is_file($filePath) && !$onlyMain) {
            $notClassFile = true;
        }


        $message = $this->_disposalData($level, $date, $msg); //拼接每条日志的记录
        file_put_contents($mainfilePath, $message, FILE_APPEND | LOCK_EX); //将内容追加写入主日志文件
        if (!$onlyMain) { //如果不是设置只写主日志文件,默认都写入对应的控制器日志文件
            file_put_contents($filePath, $message, FILE_APPEND | LOCK_EX); //将内容追加写入主日志文件
        }


        //修改新生成的日志文件的权限
        if (isset($notMainFile) && $notMainFile === TRUE) {
            chmod($mainfilePath, $this->_file_permissions);
        }
        if (isset($notClassFile) && $notClassFile === TRUE) {
            chmod($filePath, $this->_file_permissions);
        }
        return TRUE;
    }


    /**
     * 创建文件夹结构
     * @return boolean
     */
    private function _mkdir() {
        file_exists($this->_log_path) OR mkdir($this->_log_path, 0777, TRUE);
        if (!is_dir($this->_log_path) OR ! is_really_writable($this->_log_path)) {
            return FALSE;
        }


        $datePath = $this->_log_path . date('Y-m-d', time()) . '/'; //创建以此刻日期为文件名的文件夹
        file_exists($datePath) OR mkdir($datePath, 0777, TRUE);
        if (!is_dir($datePath) OR ! is_really_writable($datePath)) {
            return FALSE;
        }
        $this->_date_path = $datePath;
        return TRUE;
    }


    /**
     * 拼装日志记录信息
     * @param type $level 级别
     * @param type $date 时间
     * @param type $message 日志内容
     * @return type
     */
    private function _disposalData($level, $date, $message) {
        if ($level == 'INFO')
            $level = "$level "; //如果是INFO的日志,多加个空格,日志格式整齐一些
        $msg = '级别:' . $level . ' | 时间:' . $date . ' | 标识号:' . IDNUM . ' | 请求的url:' . REQUEST_CLASS . "/" . REQUEST_METHOD . PHP_EOL;
        $msg .= '    内容:' . $message . PHP_EOL;
        if (version_compare(phpversion(), '5.4.0') >= 0) { //debug_backtrace函数只有在5.4以上才支持第二个参数
            $debugInfo = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 4); //获取调试信息
        } else {
            $debugInfo = debug_backtrace();
        }
        //开启了调试信息配置且是ERROR级别且是由自定义的日志报错,才显示调试信息和浏览器信息
        if (($this->_debugInfo or in_array(strtolower(REQUEST_CLASS), $this->_allLog_controller)) && $level == "ERROR" && $debugInfo[3]['function'] !== 'write_log') {
            $msg .= '    调试信息:在' . $debugInfo[2]['file'] . "中的第{$debugInfo[2]['line']}行中调用记录日志方法,包含在{$debugInfo[3]['function']}方法中";
            if (isset($debugInfo[3]['file']))
                $msg .= ",调用{$debugInfo[3]['function']}的是{$debugInfo[3]['file']}中的{$debugInfo[3]['line']}行";
            if (!empty($debugInfo[3]['args'])) {
                $msg .= ",传入{$debugInfo[3]['function']}方法的参数值序列化后为:" . serialize($debugInfo[3]['args']) . PHP_EOL;
            } else {
                $msg .= ",无参数传入" . PHP_EOL;
            }
            $input = load_class('INPUT', 'core'); //加载INPUT辅助类
            //拼接IP地址和浏览器版本信息
            $msg .= "    浏览器信息:IP地址为{$input->ip_address()},使用的浏览器是:" . $this->_getBrowser() . "(" . $this->_getBrowserVersion() . "版本)";
            //拼接访问方式
            $msg .= ",访问方式为:" . $input->method();
            if ($input->is_ajax_request()) //是否以ajax访问
                $msg .= ",以ajax形式访问";
            if ($input->is_cli_request()) //是否以cli访问
                $msg .= ",以cli形式访问";
            $HTTP_REFERER = $input->server('HTTP_REFERER');
            if (!empty($HTTP_REFERER)) //能够获取上个来源页
                $msg .= ",上个来源页是:{$input->server('HTTP_REFERER')}";
            $get = $input->get();
            if (!empty($get)) //如果传入的get参数不为空
                $msg .= ",传入的get参数序列化后为:" . serialize($input->get());
            $post = $input->post();
            if (!empty($post)) //如果传入的post参数不为空
                $msg .= ",传入的post参数序列化后为:" . serialize($input->post());
//            if (strlen($input->raw_input_stream) > 0) { //如果传入的input流不为空
//                $msg .= ",传入的input流序列化后为:". serialize($input->raw_input_stream);
//            }
//                
            $msg .= PHP_EOL; //换行符
            if (isset($_SESSION))
                $msg .= "    SESSION信息序列化后为:" . serialize($_SESSION) . PHP_EOL;
        }
        $msg .= PHP_EOL; //换行符
        return $msg;
    }


    /**
     * 获取浏览器类型。
     * @return string
     */
    private function _getBrowser() {
        if (empty($_SERVER['HTTP_USER_AGENT']))
            return 'unknow';


        $agent = $_SERVER["HTTP_USER_AGENT"];
        if (strpos($agent, 'MSIE') !== false || strpos($agent, 'rv:11.0')) {
            return "ie";
        } else if (strpos($agent, 'Firefox') !== false) {
            return "firefox";
        } else if (strpos($agent, 'Chrome') !== false) {
            return "chrome";
        } else if (strpos($agent, 'Opera') !== false) {
            return 'opera';
        } else if ((strpos($agent, 'Chrome') == false) && strpos($agent, 'Safari') !== false) {
            return 'safari';
        } else {
            return 'unknown';
        }
    }


    /**
     * 获得浏览器版本号
     * @return string
     */
    private function _getBrowserVersion() {
        if (empty($_SERVER['HTTP_USER_AGENT']))
            return 'unknow';


        $agent = $_SERVER['HTTP_USER_AGENT'];
        if (preg_match('/MSIE\s(\d+)\..*/i', $agent, $regs)) {
            return $regs[1];
        } else if (preg_match('/FireFox\/(\d+)\..*/i', $agent, $regs)) {
            return $regs[1];
        } else if (preg_match('/Opera[\s|\/](\d+)\..*/i', $agent, $regs)) {
            return $regs[1];
        } else if (preg_match('/Chrome\/(\d+)\..*/i', $agent, $regs)) {
            return $regs[1];
        } else if ((strpos($agent, 'Chrome') == false) && preg_match('/Safari\/(\d+)\..*$/i', $agent, $regs)) {
            return $regs[1];
        } else if (preg_match('/rv:(\d+)\..*/i', $agent, $regs)) {
            return $regs[1];
        } else {
            return 'unknow';
        }
    }




2、  在application下的config文件夹下config.php文件中追加

 

1.  /* 

2. |-------------------------------------------------------------------------- 

3.  自定义的日志记录配置 

4. |-------------------------------------------------------------------------- 

5.  | 

6.  */  

7.  $config['CILog_path'] = ''//默认在application下的CIlogs  

8. $config['CILog_file_permissions'] = 0644; //生成文件的权限  

9.  $config['CILog_date_fmt'] = 'Y-m-d H:i:s'//日志内容中的时间格式  

10.$config['CILog_threshold'] = 4; //记录日志的级别,默认记录全部。1-ERROR 2-DEBUG 3-INFO 4-ALL 0-不记录  

11. $config['CILog_debugInfo'] = true; //true时开启详细调试信息和浏览器信息,false时关闭。  

12.$config['CILog_allLog_controller'] = array(); //所有信息都记录的控制器,包含的话,则无论CILog_thresholdCILog_debugInfo如何设置,都将会记录该控制器下所有日志内容  

3、  在system\core\CodeIgniter.php下,找到$LANG=& load_class('Lang', 'core'); 在这行代码之后追加

 

1.  /* 

2.  * ------------------------------------------------------ 

3.   *  加载日志类 

4.  * ------------------------------------------------------ 

5.   */  

6.         $CILog =& load_class('CILog''core');  

7.          defined('REQUEST_CLASS'or define('REQUEST_CLASS', $RTR->class); //请求的控制器名  

8.         defined('REQUEST_METHOD'or define('REQUEST_METHOD', $RTR->method); //请求的控制器名  

9.          defined('IDNUM'or define('IDNUM', uniqid());  

4、  在system\core\Log.php中的write_log方法中,在方法开头增加

1.  //自定义的CILog类总需记录ERROR类型的报错  

2. if(strtoupper($level) == 'ERROR') {  

3.      logMsg('error', $msg, true);  

4. }  

5、  在system\core\Common.php中增加

1.  if (!function_exists('logMsg')) {  

2.   

3.      /** 

4.      * 记录自定义的日志信息 

5.       * @staticvar type $_log 静态变量存放日志对象(单例) 

6.      * @param type $level 级别 level: 'error', 'debug' or 'info' 

7.       * @param type $message 日志内容 

8.      * @param type $onlyMain 是否只将日志记入主流程 

9.       */  

10.    function logMsg($level, $message, $onlyMain = false) {  

11.         static $_logObj;  

12.  

13.         if ($_logObj === NULL) {  

14.            $_logObj[0] = & load_class('CILog''core');  

15.         }  

16.  

17.         $_logObj[0]->write_log($level, $message, $onlyMain);  

18.    }  

19.   

20.}  

6、  如果CI的版本过低,system\core\Input.php中不包含method方法,则增加

1.  public function method($upper = FALSE) {  

2.     return ($upper) ? strtoupper($this->server('REQUEST_METHOD')) : strtolower($this->server('REQUEST_METHOD'));  

3.  }  

 

7、  在代码的任意处,可以使用logMsg(‘错误级别’,’内容’);记录日志

 

错误级别分为:error、info、debug三类

Error:错误、在走异常分支的流程时,需要记录错误日志信息

Info:流程信息,可记录一个流程的输入至输出时记录的流程信息

Debug:调试信息,调试某些功能时,需要记录参数等内容时,并在功能运行完后比对查看是否符合自己预期时

 

内容:需描述清楚此步骤时的具体含义,若有类似调用接口的上下文信息、过程生成返回值时,也需相关信息

原创粉丝点击