123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435 |
- <?php
- namespace App\Library\Logger;
- /**
- * Created by PhpStorm.
- * User: lhz
- * Date: 2016-5-31
- * Time: 8:50
- * 日志器
- */
- use Fluent\Logger\FluentLogger;
- class Logger {
- //常量定义
- const DEBUG = 0b00000001; //Debug: debug-level messages
- const INFO = 0b00000010; //Informational: informational messages
- const NOTICE = 0b00000100; //Notice: normal but significant condition
- const WARNING = 0b00001000; //Warning: warning conditions
- const ERROR = 0b00010000; //Error: error conditions
- const FATAL = 0b00100000; //Critical: critical conditions
- const ALERT = 0b01000000; //Alert: action must be taken immediately
- const EMERGENCY = 0b10000000; //Emergency: system is unusable
- const PRE_DEFINE_ALL = self::EMERGENCY | self::ALERT | self::FATAL | self::ERROR | self::WARNING | self::NOTICE | self::INFO | self::DEBUG;
- const PRE_DEFINE_ERROR = self::EMERGENCY | self::ALERT | self::FATAL | self::ERROR;
- const PRE_DEFINE_WARN = self::PRE_DEFINE_ERROR | self::WARNING;
- const PRE_DEFINE_INFO = self::WARNING | self::NOTICE | self::INFO | self::DEBUG;
- const DEVELOP = 'development';
- const PRODUCT = 'production';
- //单例对象
- static $_instance = NULL;
- //邮件
- static $_mailer = NULL;
- //fluentd
- private $_fluentd = NULL;
- //日志句柄
- private $_fp = NULL;
- //日志级别
- private $_level = self::FATAL;
- //应用环境
- private $_env = self::DEVELOP;
- //项目ID
- private $_project = '';
- //邮件错误通知开关
- private $_mailSwitch = 'auto';//auto表示自动,级别在error及以上发邮件;on表示全部发送邮件;off表示关闭邮件警告
- //debug_backtrace开关
- private $_debugBackTrace = true;
- //日志类型枚举
- private $_TYPES = [
- self::DEBUG => 'DEBUG',
- self::INFO => 'INFO',
- self::NOTICE => 'NOTICE',
- self::WARNING => 'WARNING',
- self::ERROR => 'ERROR',
- self::FATAL => 'FATAL',
- self::ALERT => 'ALERT',
- self::EMERGENCY => 'EMERGENCY',
- ];
- //日志类型分类
- private $_CATEGORIES = [
- self::DEBUG => 'INFO',
- self::INFO => 'INFO',
- self::NOTICE => 'INFO',
- self::WARNING => 'INFO',
- self::ERROR => 'ERROR',
- self::FATAL => 'ERROR',
- self::ALERT => 'ERROR',
- self::EMERGENCY => 'ERROR',
- ];
- public function __construct($path = NULL)
- {
- $this->setPath($path);
- $this->setLevel(self::EMERGENCY | self::ALERT | self::FATAL | self::ERROR | self::WARNING);
- }
- private function __clone() {
- }
- private function _formatMsg($msg, $type, $file = null, $line = null) {
- $extra = '';
- if ($this->_debugBackTrace && $file === null && $line === null) {
- $traceLevel = 10;
- $trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, $traceLevel);
- $cnt = count($trace);
- if ($cnt > 0) {
- foreach ($trace as $l) {
- if (isset($l['file']) && isset($l['line'])) {
- $extra .= sprintf("%s(%d)\n", $l['file'], $l['line']);
- }
- }
- $file = $trace[$cnt-1]['file'];
- $line = $trace[$cnt-1]['line'];
- }
- }
- if ($file === null) {
- $file = __FILE__;
- }
- if ($line === null) {
- $line = __LINE__;
- }
- return sprintf("%s [%-5s] [%-25s :%5d] %s\n%s\n", date('Y-m-d H:i:s'), $this->_TYPES[$type], substr($file, -24), $line, $msg, $extra);
- }
- private function _sendFluentd($data, $type, $errFile = null, $errLine = null) {
- $tag = sprintf("%s.%s.%s", $this->_project, $this->_CATEGORIES[$type], $this->_TYPES[$type]);
- $subject = sprintf("[%s][%s]%s", $this->_project, $this->_TYPES[$type], substr($data, 0, 40));
- $reqMicro = explode('.', $_SERVER['REQUEST_TIME_FLOAT']);
- $reqTime = new \DateTime(date('Y-m-d H:i:s.' . $reqMicro[1], $_SERVER['REQUEST_TIME']));
- $curMicro = microtime(true);
- $tMicro = sprintf("%06d", ($curMicro - floor($curMicro)) * 1000000);
- $curTime = new \DateTime(date('Y-m-d H:i:s.' . $tMicro, $curMicro));
- $msg = [
- 'title' => $subject,
- 'server_name' => $_SERVER['SERVER_NAME'],
- 'server_ip' => $_SERVER['SERVER_ADDR'],
- 'server_port' => $_SERVER['SERVER_PORT'],
- 'client_ip' => $_SERVER['REMOTE_ADDR'],
- 'request_uri' => $_SERVER['REQUEST_URI'],
- 'request_time' => $reqTime->format('Y-m-d H:i:s.u'),
- 'current_time' => $curTime->format('Y-m-d H:i:s.u'),
- 'server_info' => print_r($_SERVER, true),
- 'get_info' => print_r($_GET, true),
- 'post_info' => print_r($_POST, true),
- 'data' => $data,
- 'trace' => $this->_formatMsg($data, $type, $errFile, $errLine),
- ];
- $this->_fluentd->post($tag, $msg);
- }
- private function _write($msg, $type, $errFile = null, $errLine = null) {
- if ($type & $this->_level) {
- if (is_object($msg) || is_array($msg)) {
- $data = print_r($msg, true);
- } else {
- $data = strval($msg);
- }
- //发送fluentd
- if ($this->_fluentd !== null) {
- $this->_sendFluentd($data, $type, $errFile, $errLine);
- }
- $data = $this->_formatMsg($data, $type, $errFile, $errLine);
- //记录日志
- fwrite($this->_fp, $data);
- //发送邮件
- // if ($this->_mailSwitch == 'on' ||
- // ($this->_mailSwitch == 'auto' &&
- // ($type & self::ERROR || $type & self::FATAL))) {
- // if (self::$_mailer !== null) {
- // $subject = sprintf("[ERROR_MAIL][%s][%s]Error info from logger", $this->_TYPES[$type], $this->_project);
- // self::$_mailer->subject($subject);
- // self::$_mailer->msgHTML($data);
- // if (!self::$_mailer->send()) {//邮件发送失败,写日志
- // $err = self::$_mailer->ErrorInfo();
- // fwrite($this->_fp, $this->_formatMsg($err, self::ERROR));
- // }
- // }
- // }
- }
- }
- private function parseArgs($args) {
- $ret = "";
- foreach ($args as $arg) {
- if (is_object($arg) || is_array($arg)) {
- $data = print_r($arg, true);
- } else {
- $data = strval($arg);
- }
- $ret .= $data . " ";
- }
- return $ret;
- }
- /**
- * @param string $path
- * @return Logger|null
- * 单例对象,参数为日志路径
- */
- public static function getInstance($path = '') {
- if (!(self::$_instance instanceof self)) {
- self::$_instance = new self($path);
- }
- return self::$_instance;
- }
- /**
- * @param string $path
- * @throws Exception
- * 设置log路径,默认标准输出
- */
- public function setPath($path = '') {
- if (empty($path)) {
- $this->_fp = fopen('php://stdout', 'w');
- } else {
- if (is_dir($path)) {
- throw new \Exception('Cannot be a path, must be a file ' . $path);
- }
- $dn = dirname($path);
- if (!file_exists($dn)) {
- @mkdir($dn, 0777, true);
- }
- if (!file_exists($path)) {
- @touch($path);
- }
- if (!is_writable($path)) {
- throw new \Exception('Log file cannot be written! ' . $path);
- }
- $this->_fp = fopen($path, 'a');
- }
- }
- /**
- * @param string $host
- * @param int $port
- * @param array $options
- * 配置fluentd
- */
- public function setFluentd($host = '127.0.0.1', $port = 24224, $options = []) {
- $this->_fluentd = new FluentLogger($host, $port, $options);
- }
- /**
- * @param $val [development | production]
- * 设置应用环境,默认development
- * 关联日志级别
- */
- public function setEnv($val) {
- if ($val == self::DEVELOP) {
- $this->_env = $val;
- $this->setLevel(self::EMERGENCY | self::ALERT | self::FATAL | self::ERROR | self::WARNING | self::NOTICE | self::INFO | self::DEBUG);
- } elseif ($val == self::PRODUCT) {
- $this->_env = $val;
- $this->setLevel(self::EMERGENCY | self::ALERT | self::FATAL | self::ERROR | self::WARNING);
- }
- }
- /**
- * @param $val
- * 设置日志级别,默认self::EMERGENCY | self::ALERT | self::FATAL | self::ERROR | self::WARNING
- */
- public function setLevel($val) {
- $this->_level = $val;
- }
- /**
- * @param $val true/false
- * debug back trace开关,默认打开
- */
- public function setDebugBackTrace($val) {
- $this->_debugBackTrace = $val;
- }
- public function setMailer(Mailer $mailer) {
- self::$_mailer = $mailer;
- }
- /**
- * @param $mail array
- * key as mail address
- * value as mail name
- */
- public function addMailTo($mail) {
- foreach ($mail as $addr => $name) {
- if (strpos($addr, '@') !== false) {
- self::$_mailer->addAddress($addr, $name);
- } elseif (strpos($name, '@') !== false) {
- self::$_mailer->addAddress($name);
- }
- }
- }
- public function setProjectId($projectId) {
- $this->_project = $projectId;
- }
- /**
- * @param null $msg
- * 调试输出
- */
- public function Debug() {
- if (func_num_args() == 0) {
- return;
- }
- $args = func_get_args();
- $msg = $this->parseArgs($args);
- $this->_write($msg, self::DEBUG);
- }
- /**
- * @param null $msg
- * 信息输出
- */
- public function Info() {
- if (func_num_args() == 0) {
- return;
- }
- $args = func_get_args();
- $msg = $this->parseArgs($args);
- $this->_write($msg, self::INFO);
- }
- /**
- * @param null $msg
- * 注意输出
- */
- public function Notice() {
- if (func_num_args() == 0) {
- return;
- }
- $args = func_get_args();
- $msg = $this->parseArgs($args);
- $this->_write($msg, self::NOTICE);
- }
- /**
- * @param null $msg
- * 警告输出
- */
- public function Warning() {
- if (func_num_args() == 0) {
- return;
- }
- $args = func_get_args();
- $msg = $this->parseArgs($args);
- $this->_write($msg, self::WARNING);
- }
- /**
- * @param null $msg
- * 错误输出
- */
- public function Error() {
- if (func_num_args() == 0) {
- return;
- }
- $args = func_get_args();
- $msg = $this->parseArgs($args);
- $this->_write($msg, self::ERROR);
- }
- /**
- * @param null $msg
- * 致命错误输出
- */
- public function Fatal() {
- if (func_num_args() == 0) {
- return;
- }
- $args = func_get_args();
- $msg = $this->parseArgs($args);
- $this->_write($msg, self::FATAL);
- }
- /**
- * @param null $msg
- * 警报错误输出
- */
- public function Alert() {
- if (func_num_args() == 0) {
- return;
- }
- $args = func_get_args();
- $msg = $this->parseArgs($args);
- $this->_write($msg, self::ALERT);
- }
- /**
- * @param null $msg
- * 紧急错误输出
- */
- public function Emergency() {
- if (func_num_args() == 0) {
- return;
- }
- $args = func_get_args();
- $msg = $this->parseArgs($args);
- $this->_write($msg, self::EMERGENCY);
- }
- /**
- * @param $errno
- * @param $errstr
- * @param $errfile
- * @param $errline
- * 系统错误捕获器
- */
- public function cbErrorHandler($errno, $errstr, $errfile, $errline) {
- switch ($errno) {
- case E_ERROR:
- case E_USER_ERROR:
- case E_CORE_ERROR:
- $errType = self::FATAL;
- break;
- case E_WARNING:
- case E_USER_WARNING:
- case E_CORE_WARNING:
- $errType = self::ERROR;
- break;
- default:
- $errType = self::WARNING;
- }
- $this->_write($errstr, $errType, $errfile, $errline);
- }
- }
|