[关闭]
@a5635268 2016-05-13T18:20:17.000000Z 字数 8981 阅读 3426

PHP高性能日志组件SeasLog

PHP


简述

什么是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

安装

编译安装

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

PECL安装SeasLog

  1. $ pecl install seaslog

配置php.ini

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

seaslog.disting_type = 1 开启以type分文件,即log文件区分info\warn\error
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 提供了这样一组函数,可以方便地获取与设置根目录、模块目录、快速写入与统计log。

  1. <?php
  2. /**
  3. * @author neeke@php.net
  4. * Date: 14-1-27 下午4:47
  5. */
  6. class SeasLog
  7. {
  8. public function __construct()
  9. {
  10. #SeasLog init
  11. }
  12. public function __destruct()
  13. {
  14. #SeasLog distroy
  15. }
  16. /**
  17. * 设置basePath
  18. *
  19. * @param $basePath
  20. *
  21. * @return bool
  22. */
  23. static public function setBasePath($basePath)
  24. {
  25. return TRUE;
  26. }
  27. /**
  28. * 获取basePath
  29. *
  30. * @return string
  31. */
  32. static public function getBasePath()
  33. {
  34. return 'the base_path';
  35. }
  36. /**
  37. * 设置模块目录
  38. * @param $module
  39. *
  40. * @return bool
  41. */
  42. static public function setLogger($module)
  43. {
  44. return TRUE;
  45. }
  46. /**
  47. * 获取最后一次设置的模块目录
  48. * @return string
  49. */
  50. static public function getLastLogger()
  51. {
  52. return 'the lastLogger';
  53. }
  54. /**
  55. * 设置DatetimeFormat配置
  56. * @param $format
  57. *
  58. * @return bool
  59. */
  60. static public function setDatetimeFormat($format)
  61. {
  62. return TRUE;
  63. }
  64. /**
  65. * 返回当前DatetimeFormat配置格式
  66. * @return string
  67. */
  68. static public function getDatetimeFormat()
  69. {
  70. return 'the datetimeFormat';
  71. }
  72. /**
  73. * 统计所有类型(或单个类型)行数
  74. * @param string $level
  75. * @param string $log_path
  76. * @param null $key_word
  77. *
  78. * @return array | long
  79. */
  80. static public function analyzerCount($level = 'all', $log_path = '*', $key_word = NULL)
  81. {
  82. return array();
  83. }
  84. /**
  85. * 以数组形式,快速取出某类型log的各行详情
  86. *
  87. * @param $level
  88. * @param string $log_path
  89. * @param null $key_word
  90. * @param int $start
  91. * @param int $limit
  92. * @param $order
  93. *
  94. * @return array
  95. */
  96. static public function analyzerDetail($level = SEASLOG_INFO, $log_path = '*', $key_word = NULL, $start = 1, $limit = 20, $order = SEASLOG_DETIAL_ORDER_ASC)
  97. {
  98. return array();
  99. }
  100. /**
  101. * 获得当前日志buffer中的内容
  102. *
  103. * @return array
  104. */
  105. static public function getBuffer()
  106. {
  107. return array();
  108. }
  109. /**
  110. * 将buffer中的日志立刻刷到硬盘
  111. *
  112. * @return bool
  113. */
  114. static public function flushBuffer()
  115. {
  116. return TRUE;
  117. }
  118. /**
  119. * 记录debug日志
  120. *
  121. * @param $message
  122. * @param array $content
  123. * @param string $module
  124. */
  125. static public function debug($message, array $content = array(), $module = '')
  126. {
  127. #$level = SEASLOG_DEBUG
  128. }
  129. /**
  130. * 记录info日志
  131. *
  132. * @param $message
  133. * @param array $content
  134. * @param string $module
  135. */
  136. static public function info($message, array $content = array(), $module = '')
  137. {
  138. #$level = SEASLOG_INFO
  139. }
  140. /**
  141. * 记录notice日志
  142. *
  143. * @param $message
  144. * @param array $content
  145. * @param string $module
  146. */
  147. static public function notice($message, array $content = array(), $module = '')
  148. {
  149. #$level = SEASLOG_NOTICE
  150. }
  151. /**
  152. * 记录warning日志
  153. *
  154. * @param $message
  155. * @param array $content
  156. * @param string $module
  157. */
  158. static public function warning($message, array $content = array(), $module = '')
  159. {
  160. #$level = SEASLOG_WARNING
  161. }
  162. /**
  163. * 记录error日志
  164. *
  165. * @param $message
  166. * @param array $content
  167. * @param string $module
  168. */
  169. static public function error($message, array $content = array(), $module = '')
  170. {
  171. #$level = SEASLOG_ERROR
  172. }
  173. /**
  174. * 记录critical日志
  175. *
  176. * @param $message
  177. * @param array $content
  178. * @param string $module
  179. */
  180. static public function critical($message, array $content = array(), $module = '')
  181. {
  182. #$level = SEASLOG_CRITICAL
  183. }
  184. /**
  185. * 记录alert日志
  186. *
  187. * @param $message
  188. * @param array $content
  189. * @param string $module
  190. */
  191. static public function alert($message, array $content = array(), $module = '')
  192. {
  193. #$level = SEASLOG_ALERT
  194. }
  195. /**
  196. * 记录emergency日志
  197. *
  198. * @param $message
  199. * @param array $content
  200. * @param string $module
  201. */
  202. static public function emergency($message, array $content = array(), $module = '')
  203. {
  204. #$level = SEASLOG_EMERGENCY
  205. }
  206. /**
  207. * 通用日志方法
  208. * @param $level
  209. * @param $message
  210. * @param array $content
  211. * @param string $module
  212. */
  213. static public function log($level, $message, array $content = array(), $module = '')
  214. {
  215. }
  216. }

Example

获取与设置basePath

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

设置logger与获取lastLogger

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

快速写入log

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

相关链接:

https://github.com/Neeke/SeasLog

SeasLog Analyzer的使用

快速统计某类型log的count值

  1. $countResult_1 = SeasLog::analyzerCount();
  2. $countResult_2 = SeasLog::analyzerCount(SEASLOG_WARNING);
  3. $countResult_3 = SeasLog::analyzerCount(SEASLOG_ERROR,date('Ymd',time()));
  4. var_dump($countResult_1,$countResult_2,$countResult_3);

获取某类型log列表

  1. $detailErrorArray_inAll = SeasLog::analyzerDetail(SEASLOG_ERROR);
  2. $detailErrorArray_today = SeasLog::analyzerDetail(SEASLOG_ERROR,date('Ymd',time()));
  3. var_dump($detailErrorArray_inAll,$detailErrorArray_today);
  4. /*
  5. SeasLog::analyzerDetail(SEASLOG_ERROR) == SeasLog::analyzerDetail(SEASLOG_ERROR,'*');
  6. 取当前模块下所有level为 SEASLOG_ERROR 的信息列表:
  7. array(6) {
  8. [0] =>
  9. string(66) "error | 8568 | 1393172042.717 | 2014:02:24 00:14:02 | test error 3 "
  10. [1] =>
  11. string(66) "error | 8594 | 1393172044.104 | 2014:02:24 00:14:04 | test error 3 "
  12. [2] =>
  13. string(66) "error | 8620 | 1393172044.862 | 2014:02:24 00:14:04 | test error 3 "
  14. [3] =>
  15. string(66) "error | 8646 | 1393172045.989 | 2014:02:24 00:14:05 | test error 3 "
  16. [4] =>
  17. string(66) "error | 8672 | 1393172047.882 | 2014:02:24 00:14:07 | test error 3 "
  18. [5] =>
  19. string(66) "error | 8698 | 1393172048.736 | 2014:02:24 00:14:08 | test error 3 "
  20. }
  21. SeasLog::analyzerDetail(SEASLOG_ERROR,date('Ymd',time()));
  22. 只取得当前模块下,当前一天内,level为SEASLOG_ERROR 的信息列表:
  23. array(2) {
  24. [0] =>
  25. string(66) "error | 8568 | 1393172042.717 | 2014:02:24 00:14:02 | test error 3 "
  26. [1] =>
  27. string(66) "error | 8594 | 1393172044.104 | 2014:02:24 00:14:04 | test error 3 "
  28. }
  29. 同理,取当月
  30. $detailErrorArray_mouth = SeasLog::analyzerDetail(SEASLOG_ERROR,date('Ym',time()));
  31. */

使用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
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注