zoukankan      html  css  js  c++  java
  • 【PHP调试篇】PHP高性能日志组件SeasLog

    简述

    什么是SeasLog

    SeasLog是一个C语言编写的PHP扩展,提供一组规范标准的功能函数,在PHP项目中方便、规范、高效地写日志,以及快速地读取和查询日志。

    为什么使用SeasLog

    无论在什么应用中,log日志都是架构中不可缺少的一个重要组成部分,它通常是系统或软件、应用的运行记录。通过log的分析,可以方便用户了解系统或软件、应用的运行情况;如果你的应用log足够丰富,也可以分析以往用户的操作行为、类型喜好、地域分布或其他更多信息;如果一个应用的log同时也分了多个级别,那么可以很轻易地分析得到该应用的健康状况,及时发现问题并快速定位、解决问题,补救损失。

    我们知道,php内置了很多log函数,如error_logsyslogfile_put_content,这些函数功能强大且性能极好,但由于各种缺陷(error_logfile_put_content无错误级别、无固定格式像是信马由缰随处乱画;syslog不区分模块、而且与系统日志混合,读syslog记录会让人抓狂的。),灵活度降低了很多,很不能满足应用需求。基本上所有的开发者,都会自行设计封装log库,当然也会有很多开发者选择已有的开源日志库。

    也有很多开源log类库弥补了上述缺陷,如log4phpplogAnalog等(当然也有很多应用在项目中自己开发的log类)。其中以log4php最为著名,它的设计精良、格式完美、文档完善、功能强大。但是经过测试,log4php的性能非常差。

    sealog在性能上有着强大的优势,假设一个请求中需要写出1000处log,那么势必会有1000次IO,这对性能将是一个很大的拖延点。一般对于处理这种多次相同的请求场景,我们要解决的其实也很简单,使用cache或buffer,把多次请求作归并,从而降低对磁盘或网络的IO,这是一个基本的思想。

    SeasLog也是这么做的。设定一个buffer_size(默认100log),使用PHP请求内存,每写一次log,塞入内存,同时buffer_size加;当buffer_size等于设置值时,则进行一次IO,同时清除buffer; 当然,如果请求结束了、或执行了dieexit或其他异常退出时,不管buffer_size有没有攒够设置值,立刻进行一次IO,同时清除buffer

    安装

    编译安装

    $ /path/to/phpize
    $ ./configure --with-php-config=/path/to/php-config
    $ make && make install
    

    PECL安装SeasLog

    $ pecl install seaslog 
    

    配置php.ini

    [SeasLog]
    extension = "/usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/seaslog.so"
    ; configuration for php SeasLog module
    extension = seaslog.so
    seaslog.default_basepath = /log/seaslog-test            ;默认log根目录
    seaslog.default_logger = default                        ;默认logger目录
    seaslog.disting_type = 1                                ;是否以type分文件 1是 0否(默认)
    seaslog.disting_by_hour = 1                             ;是否每小时划分一个文件 1是 0否(默认)
    seaslog.use_buffer = 1                                  ;是否启用buffer 1是 0否(默认)
    seaslog.buffer_size = 100                               ;buffer中缓冲数量 默认0(不使用buffer_size)
    seaslog.level = 0                                       ;记录日志级别 默认0(所有日志)
    seaslog.trace_error = 1                                 ;自动记录错误 默认1(开启)
    seaslog.trace_exception = 0                             ;自动记录异常信息 默认0(关闭)
    seaslog.default_datetime_format = "%Y:%m:%d %H:%M:%S"   ;日期格式配置 默认"%Y:%m:%d %H:%M:%S"
    

    seaslog.disting_type = 1 开启以type分文件,即log文件区分infowarnerror
    seaslog.disting_by_hour = 1 开启每小时划分一个文件
    seaslog.use_buffer = 1 开启buffer。默认关闭。当开启此项时,日志预存于内存,当请求结束时(或异常退出时)一次写入文件。
    seaslog.buffer_size = 100 设置缓冲数量为100. 默认为0,即无缓冲数量限制.当buffer_size大于0时,缓冲量达到该值则写一次文件..
    seaslog.level = 3 记录的日志级别.默认为0,即所有日志均记录。当level为1时,关注debug以上级别(包括debug),以此类推。level大于8时,所有日志均不记录。

    记录

    常量列表

    SeasLog 共将日志分成8个级别

    • SEASLOG_DEBUG "debug" debug,仅仅是在debug模式下才可以记录的debug日志。
    • SEASLOG_INFO "info" 重要事件,例如:用户登录和SQL记录。
    • SEASLOG_NOTICE "notice" 一般性重要的事件。
    • SEASLOG_WARNING "warning" 出现非错误性的异常。例如:使用了被弃用的API、错误地使用了API或者非预想的不必要错误。
    • SEASLOG_ERROR "error" 错误,运行时出现的错误,不需要立刻采取行动,但必须记录下来以备检测。
    • SEASLOG_CRITICAL "critical" 紧急情况, 例如:程序组件不可用或者出现非预期的异常。
    • SEASLOG_ALERT "alert" 必须立刻采取行动的错误级别,比如在整个网站都垮掉了、数据库不可用了或者其他的情况下,应该发送一条警报短信把你叫醒。
    • SEASLOG_EMERGENCY "emergency" 紧急情况,最高级别,系统已不可用。

    函数列表

    SeasLog 提供了这样一组函数,可以方便地获取与设置根目录、模块目录、快速写入与统计log。

    <?php
    /**
     * @author neeke@php.net
     * Date: 14-1-27 下午4:47
     */
    
    class SeasLog
    {
        public function __construct()
        {
            #SeasLog init
        }
    
        public function __destruct()
        {
            #SeasLog distroy
        }
    
        /**
         * 设置basePath
         *
         * @param $basePath
         *
         * @return bool
         */
        static public function setBasePath($basePath)
        {
            return TRUE;
        }
    
        /**
         * 获取basePath
         *
         * @return string
         */
        static public function getBasePath()
        {
            return 'the base_path';
        }
    
        /**
         * 设置模块目录
         * @param $module
         *
         * @return bool
         */
        static public function setLogger($module)
        {
            return TRUE;
        }
    
        /**
         * 获取最后一次设置的模块目录
         * @return string
         */
        static public function getLastLogger()
        {
            return 'the lastLogger';
        }
    
        /**
         * 设置DatetimeFormat配置
         * @param $format
         *
         * @return bool
         */
        static public function setDatetimeFormat($format)
        {
            return TRUE;
        }
    
        /**
         * 返回当前DatetimeFormat配置格式
         * @return string
         */
        static public function getDatetimeFormat()
        {
            return 'the datetimeFormat';
        }
    
        /**
         * 统计所有类型(或单个类型)行数
         * @param string $level
         * @param string $log_path
         * @param null   $key_word
         *
         * @return array | long
         */
        static public function analyzerCount($level = 'all', $log_path = '*', $key_word = NULL)
        {
            return array();
        }
    
        /**
         * 以数组形式,快速取出某类型log的各行详情
         *
         * @param        $level
         * @param string $log_path
         * @param null   $key_word
         * @param int    $start
         * @param int    $limit
         * @param        $order
         *
         * @return array
         */
        static public function analyzerDetail($level = SEASLOG_INFO, $log_path = '*', $key_word = NULL, $start = 1, $limit = 20, $order = SEASLOG_DETIAL_ORDER_ASC)
        {
            return array();
        }
    
        /**
         * 获得当前日志buffer中的内容
         *
         * @return array
         */
        static public function getBuffer()
        {
            return array();
        }
    
        /**
         * 将buffer中的日志立刻刷到硬盘
         *
         * @return bool
         */
        static public function flushBuffer()
        {
            return TRUE;
        }
    
        /**
         * 记录debug日志
         *
         * @param        $message
         * @param array  $content
         * @param string $module
         */
        static public function debug($message, array $content = array(), $module = '')
        {
            #$level = SEASLOG_DEBUG
        }
    
        /**
         * 记录info日志
         *
         * @param        $message
         * @param array  $content
         * @param string $module
         */
        static public function info($message, array $content = array(), $module = '')
        {
            #$level = SEASLOG_INFO
        }
    
        /**
         * 记录notice日志
         *
         * @param        $message
         * @param array  $content
         * @param string $module
         */
        static public function notice($message, array $content = array(), $module = '')
        {
            #$level = SEASLOG_NOTICE
        }
    
        /**
         * 记录warning日志
         *
         * @param        $message
         * @param array  $content
         * @param string $module
         */
        static public function warning($message, array $content = array(), $module = '')
        {
            #$level = SEASLOG_WARNING
        }
    
        /**
         * 记录error日志
         *
         * @param        $message
         * @param array  $content
         * @param string $module
         */
        static public function error($message, array $content = array(), $module = '')
        {
            #$level = SEASLOG_ERROR
        }
    
        /**
         * 记录critical日志
         *
         * @param        $message
         * @param array  $content
         * @param string $module
         */
        static public function critical($message, array $content = array(), $module = '')
        {
            #$level = SEASLOG_CRITICAL
        }
    
        /**
         * 记录alert日志
         *
         * @param        $message
         * @param array  $content
         * @param string $module
         */
        static public function alert($message, array $content = array(), $module = '')
        {
            #$level = SEASLOG_ALERT
        }
    
        /**
         * 记录emergency日志
         *
         * @param        $message
         * @param array  $content
         * @param string $module
         */
        static public function emergency($message, array $content = array(), $module = '')
        {
            #$level = SEASLOG_EMERGENCY
        }
    
        /**
         * 通用日志方法
         * @param        $level
         * @param        $message
         * @param array  $content
         * @param string $module
         */
        static public function log($level, $message, array $content = array(), $module = '')
        {
    
        }
    }
    

    Example

    获取与设置basePath

    $basePath_1 = SeasLog::getBasePath(); //直接使用 SeasLog::getBasePath(),将获取php.ini(seaslog.ini)中设置的 seaslog.default_basepath 的值。
    
    SeasLog::setBasePath('/log/base_test');
    $basePath_2 = SeasLog::getBasePath();
    

    设置logger与获取lastLogger

    $lastLogger_1 = SeasLog::getLastLogger(); // 直接使用 SeasLog::getLastLogger(),将获取php.ini(seaslog.ini)中设置的 seaslog.default_logger 的值。
    
    SeasLog::setLogger('testModule/app1');
    $lastLogger_2 = SeasLog::getLastLogger();
    

    快速写入log

    SeasLog::log(SEASLOG_ERROR,'this is a error test by ::log');
    
    SeasLog::debug('this is a {userName} debug',array('{userName}' => 'neeke'));
    
    SeasLog::info('this is a info log');
    
    SeasLog::notice('this is a notice log');
    
    SeasLog::warning('your {website} was down,please {action} it ASAP!',array('{website}' => 'github.com','{action}' => 'rboot'));
    
    SeasLog::error('a error log');
    
    SeasLog::critical('some thing was critical');
    
    SeasLog::alert('yes this is a {messageName}',array('{messageName}' => 'alertMSG'));
    
    SeasLog::emergency('Just now, the house next door was completely burnt out! {note}',array('{note}' => 'it`s a joke'));
    
    /*
    这些函数同时也接受第3个参数为logger的设置项
    注意,当last_logger == 'default'时等同于:
    SeasLog::setLogger('test/new/path');
    SeasLog::error('test error 3');
    如果已经在前文使用过SeasLog::setLogger()函数,第3个参数的log只在此处临时使用,不影响下文。
    */
    
    log格式统一为: {type} | {pid} | {timeStamp} |{dateTime} | {logInfo}
    

    相关链接:

    https://github.com/Neeke/SeasLog

    SeasLog Analyzer的使用

    快速统计某类型log的count值

    $countResult_1 = SeasLog::analyzerCount();
    $countResult_2 = SeasLog::analyzerCount(SEASLOG_WARNING);
    $countResult_3 = SeasLog::analyzerCount(SEASLOG_ERROR,date('Ymd',time()));
    
    var_dump($countResult_1,$countResult_2,$countResult_3);
    

    获取某类型log列表

    $detailErrorArray_inAll   = SeasLog::analyzerDetail(SEASLOG_ERROR);
    $detailErrorArray_today   = SeasLog::analyzerDetail(SEASLOG_ERROR,date('Ymd',time()));
    
    var_dump($detailErrorArray_inAll,$detailErrorArray_today);
    
    /*
    SeasLog::analyzerDetail(SEASLOG_ERROR) == SeasLog::analyzerDetail(SEASLOG_ERROR,'*');
    取当前模块下所有level为 SEASLOG_ERROR 的信息列表:
    array(6) {
     [0] =>
      string(66) "error | 8568 | 1393172042.717 | 2014:02:24 00:14:02 | test error 3 "
      [1] =>
      string(66) "error | 8594 | 1393172044.104 | 2014:02:24 00:14:04 | test error 3 "
      [2] =>
      string(66) "error | 8620 | 1393172044.862 | 2014:02:24 00:14:04 | test error 3 "
      [3] =>
      string(66) "error | 8646 | 1393172045.989 | 2014:02:24 00:14:05 | test error 3 "
      [4] =>
      string(66) "error | 8672 | 1393172047.882 | 2014:02:24 00:14:07 | test error 3 "
      [5] =>
      string(66) "error | 8698 | 1393172048.736 | 2014:02:24 00:14:08 | test error 3 "
    }
    
    SeasLog::analyzerDetail(SEASLOG_ERROR,date('Ymd',time()));
    只取得当前模块下,当前一天内,level为SEASLOG_ERROR 的信息列表:
    array(2) {
      [0] =>
      string(66) "error | 8568 | 1393172042.717 | 2014:02:24 00:14:02 | test error 3 "
      [1] =>
      string(66) "error | 8594 | 1393172044.104 | 2014:02:24 00:14:04 | test error 3 "
    }
    
    同理,取当月
    $detailErrorArray_mouth = SeasLog::analyzerDetail(SEASLOG_ERROR,date('Ym',time()));
    */
    

    使用SeasLog进行健康预警

    预警的配置

    [base]
    wait_analyz_log_path = /log/base_test
    
    [fork]
    ;是否开启多线程 1开启 0关闭
    fork_open = 1
    
    ;线程个数
    fork_count = 3
    
    [warning]
    email[smtp_host] = smtp.163.com
    email[smtp_port] = 25
    email[subject_pre] = 预警邮件 -
    email[smtp_user] = seaslogdemo@163.com
    email[smtp_pwd] = seaslog#demo
    email[mail_from] = seaslogdemo@163.com
    email[mail_to] = gaochitao@weiboyi.com
    email[mail_cc] = ciogao@gmail.com
    email[mail_bcc] =
    
    [analyz]
    ; enum
    ; SEASLOG_DEBUG      "debug"
    ; SEASLOG_INFO       "info"
    ; SEASLOG_NOTICE     "notice"
    ; SEASLOG_WARNING    "warning"
    ; SEASLOG_ERROR      "error"
    ; SEASLOG_CRITICAL   "critical"
    ; SEASLOG_ALERT      "alert"
    ; SEASLOG_EMERGENCY  "emergency"
    
    test1[module] = test/bb
    test1[level] = SEASLOG_ERROR
    test1[bar] = 1
    test1[mail_to] = gaochitao@weiboyi.com
    
    test2[module] = 222
    test2[level] = SEASLOG_WARNING
    
    test3[module] = 333
    test3[level] = SEASLOG_CRITICAL
    
    test4[module] = 444
    test4[level] = SEASLOG_EMERGENCY
    
    test5[module] = 555
    test5[level] = SEASLOG_DEBUG
    

    crontab配置

    ;每天凌晨3点执行
    0 3 * * * /path/to/php /path/to/SeasLog/Analyzer/SeasLogAnalyzer.php
  • 相关阅读:
    37. Sudoku Solver(js)
    36. Valid Sudoku(js)
    35. Search Insert Position(js)
    34. Find First and Last Position of Element in Sorted Array(js)
    33. Search in Rotated Sorted Array(js)
    32. Longest Valid Parentheses(js)
    函数的柯里化
    俞敏洪:我和马云就差了8个字
    vue路由传值params和query的区别
    简述vuex的数据传递流程
  • 原文地址:https://www.cnblogs.com/nixi8/p/6648076.html
Copyright © 2011-2022 走看看