github: https://github.com/Neeke/SeasLog

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

@交流群 312910117



简介

为什么使用SeasLog

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

php内置error_log、syslog函数功能强大且性能极好,但由于各种缺陷(error_log无错误级别、无固定格式,syslog不分模块、与系统日志混合),灵活度降低了很多,不能满足应用需求。

好消息是,有不少第三方的log类库弥补了上述缺陷,如log4php、plog、Analog等(当然也有很多应用在项目中自己开发的log类)。其中以log4php最为著名,设计精良、格式完美、文档完善、功能强大。推荐。

不过log4php在性能方面表现非常差,下图是SeasLog与log4php的ab并发性能测试( 测试环境:Ubuntu12.04单机,CPU I3,内存 16G,硬盘 SATA 7200):

那么有没有一种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

SeasLog-An effective,fast,stable log extension for PHP的更多相关文章

  1. mac机上搭建php56/nginx 1.8.x/thinkphp 3.2.x/gearman扩展/seaslog扩展/redis扩展环境

    php的各种扩展配置起来实在不容易,记录一下备忘: 一.php56 安装 虽然php7出来了,但是没用过,不知道有没有坑,这里仍然使用php5.6版本 1.1 安装php/php-pfm brew u ...

  2. php SeasLog使用以及liunx环境下安装

    1.下载SeasLog http://pecl.php.net/package/SeasLog php官方 https://github.com/Neeke/SeasLog 作者的github  2. ...

  3. php 之 日志系统seaslog安装

    php 之 日志系统seaslog 特点: 1.高性能(使用C语言编写的). 2.无需配置. 3.功能完善.使用简单. 安装: 打开php的扩展官网:https://pecl.php.net/. 然后 ...

  4. Managing IIS Log File Storage

    Managing IIS Log File Storage   You can manage the amount of server disk space that Internet Informa ...

  5. 手动创建binary log files和手动编辑binary log index file会有什么影响

    基本环境:官方社区版MySQL 5.7.19 一.了解Binary Log结构 1.1.High-Level Binary Log Structure and Contents • Binlog包括b ...

  6. Ubuntu下的log日志查看器

    1.lnav:Linux 下一个基于控制台的高级日志文件查看器 https://www.cnblogs.com/michealLang/p/9761886.html http://www.imooc. ...

  7. 学习了解PHP中的SeasLog日志扩展

    今天来学习的扩展是和日志相关的一个扩展,对于 PHP 的日志应用来说,除了本身自带的 error_log() . syslog() 之外,在大多数的框架中还会经常见到 monolog 的踪影.当然,我 ...

  8. go语言项目汇总

    Horst Rutter edited this page 7 days ago · 529 revisions Indexes and search engines These sites prov ...

  9. GO语言的开源库

    Indexes and search engines These sites provide indexes and search engines for Go packages: godoc.org ...

随机推荐

  1. 建立Maven工程时出错,Failure to transfer com.thoughtworks.xstream:xstream:jar:1.3.1

    Failure to transfer com.thoughtworks.xstream:xstream:jar: from http://repo1.maven.org/maven2 was cac ...

  2. MongoDB 入门之基础 DML

    此文章主要记录部分主要的 MongoDB Collection 的 DML 操作. 文章中的 Collection 名字为 yourColl,每一次操作包含以下两条初始数据 { "_id&q ...

  3. Repeater 双向排序

      做项目的时候,DataGrid ,DataList,Repeater 三个控件都是很优秀的数据显示控件,DataGrid的方便,简单易用,功能强大,但对性能会有所影响,在loading页面的时候大 ...

  4. sparklyr包--实现R与Spark接口

    1.sparklyr包简介 Rstudio公司发布的sparklyr包具有以下几个功能: 实现R与Spark的连接: sparklyr包提供了一个完整的dplyr后端,可筛选并聚合Spark数据集,接 ...

  5. BZOJ2164 : 采矿

    树链剖分+线段树,每个节点维护以下信息: (1)单独在某个点分配$i$个人的最大收益.可以$O(m)$合并. (2)分配$i$个人的最大收益.可以用$O(m^2)$合并. 时间复杂度$O(c(m^2\ ...

  6. 【BZOJ1426】收集邮票 期望

    [BZOJ1426]收集邮票 Description 有n种不同的邮票,皮皮想收集所有种类的邮票.唯一的收集方法是到同学凡凡那里购买,每次只能买一张,并且买到的邮票究竟是n种邮票中的哪一种是等概率的, ...

  7. Extjs 属性控件[转载]

    Ext.form.TimeField: 配置项:            maxValue:列表中允许的最大时间            maxText:当时间大于最大值时的错误提示信息          ...

  8. css3 使用SVG做0.5px 的边框细线

    .HalfPixelLine{ background: repeat-x top left url("data:image/svg+xml;utf8,<svg xmlns='http: ...

  9. LVS DR脚本 解析

    vip.sh #!/bin/bash 192.168.2.240 broadcast 192.168.2.240 netmask 255.255.255.255 up route add -host ...

  10. (转)深入理解flash重绘

    深入理解Flash Player重绘 Flash Player 会以SWF内容的帧频速度来刷新需要变化的内容,而这个刷新的过程,我们通常称为“重绘(redraw)”,相信即便是初级的菜鸟也知道,只要使 ...