在项目开发中,都不可避免的使用到日志。没有日志虽然不会影响项目的正确运行,但是没有日志的项目可以说是不完整的。日志在调试,错误或者异常定位,数据分析中的作用是不言而喻的。
调试
在项目调试时,查看日志信息可以方便地知道当前程序的运行状态,输出的日志便于记录程序在之前的运行结果。尤其在一些性能调优方面,通过日志可以记录每次请求访问的时间,以及调用时间等等。
错误定位
不要以为项目能正确跑起来就可以高枕无忧,项目在运行一段时候后,可能由于数据问题,网络问题,内存问题等出现异常。这时日志可以帮助开发或者运维人员快速定位错误位置,提出解决方案。
数据分析
大数据的兴起,使得大量的日志分析成为可能,ELK也让日志分析门槛降低了很多。日志中蕴含了大量的用户数据,包括点击行为,兴趣偏好等,用户画像对于公司下一步的战略方向有一定指引作用。
日志分类:
日志在程序中的输出也是有级别的,分为 debug , info ,warning,error 四个大的级别。当然有的公司会分的更细。日志是24小时不简单的产生,我们可以根据业务需求,将日志分时间段来保存,可以分为月,日,时等方式来切分日志,不然一个日志文件会太多太大。
以下是具体的实现方式。
1:对日志进行时间段收集,默认按照天来收集,当然如果用户需要自定义文件名,也可以支持。
$this->config = $config->toArray(); $this->open = $this->config['log']['open']; $filerule = $this->config['log']['filerule']; $this->path = $this->config['log']['path']; if (isset($params['filename']) && $params['filename']) { $this->fileName = $params['filename'] . ".log"; } else { if ($filerule == "day") { $this->fileName = date("Y-m-d", time()) . ".log"; } else if ($filerule == "month") { $this->fileName = date("Y-m", time()) . ".log"; } else if ($filerule == "hours") { $this->fileName = date("Y-m-d-H", time()) . ".log"; } }
2:设置日志的级别,判断如果大于当前的级别则写入
/* 1 设置日志的级别 2 判断如果大于当前的级别则写入 3 类作为一个单例的对象存在 4:修改类可以自定义日志文件名字 */ class Log { private static $_instance; private $fileName; private $path; private $level; private $buffer; private $open = ''; private $config = null; //日志添加一个可以自定义文件名字的 private function __construct($params = array()) { $arrConfig = Yaf_Application::app()->getConfig(); Yaf_Registry::set('config', $arrConfig); $config = new Yaf_Config_Ini(APP_PATH . '/conf/application.ini'); $this->config = $config->toArray(); $this->open = $this->config['log']['open']; $filerule = $this->config['log']['filerule']; $this->path = $this->config['log']['path']; if (isset($params['filename']) && $params['filename']) { $this->fileName = $params['filename'] . ".log"; } else { if ($filerule == "day") { $this->fileName = date("Y-m-d", time()) . ".log"; } else if ($filerule == "month") { $this->fileName = date("Y-m", time()) . ".log"; } else if ($filerule == "hours") { $this->fileName = date("Y-m-d-H", time()) . ".log"; } } $this->level = $this->config['log']['level']; } private function __clone() { } public static function getInstance($params = array()) { if (is_null(self::$_instance) || isset (self::$_instance)) { self::$_instance = new self ($params); } return self::$_instance; } public function Write($level, $info) { if ($this->getLevelNumber($level) >= $this->getLevelNumber($this->level)) { $this->WriteLog($this->bindLine($level, $info)); } } public function WriteWithBuffer($level, $info) { if ($this->getLevelNumber($level) >= $this->getLevelNumber($this->level)) { $this->buffer = $this->buffer . $this->bindLine($level, $info); } } private function bindLine($level, $info) { return "[" . $level . "] " . date("Y-m-d H:i:s", time()) . " " . $info . PHP_EOL; } public function flush() { $this->WriteLog($this->buffer); } private function WriteLog($data) { if (!$this->open) { return; } $path = $this->path . $this->fileName; $file = fopen($path, "a+"); if (flock($file, LOCK_EX)) { fwrite($file, $data); // release lock flock($file, LOCK_UN); } fclose($file); } private function getLevelNumber($key) { $data = ["debug" => 1, "info" => 2, "waring" => 3, "error" => 4]; if (in_array($key, array_keys($data))) { return $data[$key]; } return 0; } }
3:日志配置,可在配置文件中自定义日志的配置
[log] path = APP_PATH"/logs/" ;日志路径 open = 1 ;是否开启写入日志 filerule = "day" ;日志写入的方式 level = "debug" ;写入级别 , 大于等于该级别的日志才会写入,对日志进行了分级
4:日志的调用
$log = Log::getInstance() ; $log->Write("debug" , "begin request :" .$request['REQUEST_URI'] );
以上是默认调用 配置文件的方式,以天为单位,写入bebug级别日志
$log = Log::getInstance(array("filename" => "test")) ; $log->Write("info" , "begin request :" .$request['REQUEST_URI'] );
以上是将日志写入到指定的test.log 文件夹中,写入info 级别的日志