SeasLog-An effective,fast,stable log extension for PHP

github: https://github.com/Neeke/SeasLogphp

 

@author Chitao.Gao [neeke@php.net]html

@交流羣 312910117git



簡介

爲何使用SeasLog

log日誌,一般是系統或軟件、應用的運行記錄。經過log的分析,能夠方便用戶瞭解系統或軟件、應用的運行狀況;若是你的應用log足夠豐富,也 能夠分析以往用戶的操做行爲、類型喜愛、地域分佈或其餘更多信息;若是一個應用的log同時也分了多個級別,那麼能夠很輕易地分析獲得該應用的健康情況, 及時發現問題並快速定位、解決問題,補救損失。github

php內置error_log、syslog函數功能強大且性能極好,但因爲各類缺陷(error_log無錯誤級別、無固定格式,syslog不分模塊、與系統日誌混合),靈活度下降了不少,不能知足應用需求。web

好消息是,有很多第三方的log類庫彌補了上述缺陷,如log4php、plog、Analog等(固然也有不少應用在項目中本身開發的log類)。其中以log4php最爲著名,設計精良、格式完美、文檔完善、功能強大。推薦。shell

不過log4php在性能方面表現很是差,下圖是SeasLog與log4php的ab併發性能測試( 測試環境:Ubuntu12.04單機,CPU I3,內存 16G,硬盤 SATA 7200): SeasLogVSlog4phpapache

那麼有沒有一種log類庫知足如下需求呢:數組

  • 分模塊、分級別
  • 配置簡單(最好是勿須配置)
  • 日誌格式清晰易讀
  • 應用簡單、性能很棒

SeasLog 正是應此需求而生。多線程

目前提供了什麼

  • 在PHP項目中便捷、規範地記錄log
  • 可配置的默認log目錄與模塊
  • 指定log目錄與獲取當前配置
  • 初步的分析預警框架
  • 高效的日誌緩衝、便捷的緩衝debug
  • 遵循 PSR-3 日誌接口規範
  • 自動記錄錯誤信息
  • 自動記錄異常信息

目標是怎樣的

  • 便捷、規範的log記錄
  • 高效的海量log分析
  • 可配置、多途徑的log預警

安裝

編譯安裝 SeasLog

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

PECL安裝SeasLog

$ pecl install seaslog

seaslog.ini的配置

; 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:i:s"         ;日期格式配置 默認"Y:m:d H:i:s"

seaslog.disting_type = 1 開啓以type分文件,即log文件區分info\warn\erro併發

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"
  • SEASLOG_INFO "info"
  • SEASLOG_NOTICE "notice"
  • SEASLOG_WARNING "warning"
  • SEASLOG_ERROR "error"
  • SEASLOG_CRITICAL "critical"
  • SEASLOG_ALERT "alert"
  • SEASLOG_EMERGENCY "emergency"
var_dump(SEASLOG_DEBUG,SEASLOG_INFO,SEASLOG_NOTICE); /* string('debug') debug級別 string('info') info級別 string('notice') notice級別 */

函數列表

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 = '') { } } 

SeasLog Logger的使用

獲取與設置basePath

$basePath_1 = SeasLog::getBasePath();  SeasLog::setBasePath('/log/base_test'); $basePath_2 = SeasLog::getBasePath();  var_dump($basePath_1,$basePath_2);  /* string(19) "/log/seaslog-ciogao" string(14) "/log/base_test" */

直接使用 SeasLog::getBasePath(),將獲取php.ini(seaslog.ini)中設置的 seaslog.default_basepath 的值。

使用 SeasLog::setBasePath() 函數,將改變 SeasLog::getBasePath() 的取值。

設置logger與獲取lastLogger

$lastLogger_1 = SeasLog::getLastLogger();  SeasLog::setLogger('testModule/app1'); $lastLogger_2 = SeasLog::getLastLogger();  var_dump($lastLogger_1,$lastLogger_2); /* string(7) "default" string(15) "testModule/app1" */

與basePath相相似的,

直接使用 SeasLog::getLastLogger(),將獲取php.ini(seaslog.ini)中設置的 seaslog.default_logger 的值。

使用 SeasLog::setLogger() 函數,將改變 SeasLog::getLastLogger() 的取值。

快速寫入log

上面已經設置過了basePath與logger,因而log記錄的目錄已經產生了,

log記錄目錄 = basePath / logger / {fileName}.log log文件名,以 年月日 分文件,現在天是2014年02月18日期,那麼 {fileName} = 20140218;

還記得 php.ini 中設置的 seaslog.disting_type 嗎?

默認的 seaslog.disting_type = 0,若是今天我使用了 SeasLog ,那麼將產生最終的log文件:

  • LogFile = basePath / logger / 20140218.log

若是 seaslog.disting_type = 1,則最終的log文件將是這樣的三個文件

  • infoLogFile = basePath / logger / INFO.20140218.log

  • warnLogFile = basePath / logger / WARN.20140218.log

  • erroLogFile = basePath / logger / ERRO.20140218.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}

error | 23625 | 1406422432.786 | 2014:07:27 08:53:52 | this is a error test by log debug | 23625 | 1406422432.786 | 2014:07:27 08:53:52 | this is a neeke debug info | 23625 | 1406422432.787 | 2014:07:27 08:53:52 | this is a info log notice | 23625 | 1406422432.787 | 2014:07:27 08:53:52 | this is a notice log warning | 23625 | 1406422432.787 | 2014:07:27 08:53:52 | your github.com was down,please rboot it ASAP! error | 23625 | 1406422432.787 | 2014:07:27 08:53:52 | a error log critical | 23625 | 1406422432.787 | 2014:07:27 08:53:52 | some thing was critical emergency | 23625 | 1406422432.787 | 2014:07:27 08:53:52 | Just now, the house next door was completely burnt out! it is a joke

SeasLog Analyzer的使用

快速統計某類型log的count值

SeasLog在擴展中使用管道調用shell命令 grep -wc快速地取得count值,並返回值(array || int)給PHP。

$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); /* array(8) {  ["debug"]=>  int(3)  ["info"]=>  int(3)  ["notice"]=>  int(3)  ["warning"]=>  int(3)  ["error"]=>  int(6)  ["critical"]=>  int(3)  ["alert"]=>  int(3)  ["emergency"]=>  int(3) }   int(7)  int(1)  */

獲取某類型log列表

SeasLog在擴展中使用管道調用shell命令 grep -w快速地取得列表,並返回array給PHP。

$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
相關文章
相關標籤/搜索