新浪SAE日志中心的魔改打开方式(使用ThinkPHP)

众所周知,新浪SAE是一家很好很强大的云平台,而ThinkPHP是一个对sae支持很好的,易于上手的框架,然而我研究了ThinkPHP中sae模式的日志实现,发现了一些问题,所以写出来分享一下。下面以ThinkPHP3.2.3版举例,但(截至本文发布前)ThinkPHP5版也有相同的问题。

话不多说,先上代码。ThinkPHP在sae模式下输出日志的实现是这样的:

(ThinkPHP3.2.3版,ThinkPHP\Library\Think\Log\Driver\Sae.class.php

    /**
     * 日志写入接口
     * @access public
     * @param string $log 日志信息
     * @param string $destination  写入目标
     * @return void
     */
    public function write($log,$destination='') {
        static $is_debug=null;
        $now = date($this->config['log_time_format']);
        $logstr="[{$now}] ".$_SERVER['REMOTE_ADDR'].' '.$_SERVER['REQUEST_URI']."\r\n{$log}\r\n";
        if(is_null($is_debug)){
            preg_replace('@(\w+)\=([^;]*)@e', '$appSettings[\'\\1\']="\\2";', $_SERVER['HTTP_APPCOOKIE']);
            $is_debug = in_array($_SERVER['HTTP_APPVERSION'], explode(',', $appSettings['debug'])) ? true : false;
        }
        if($is_debug){
            sae_set_display_errors(false);//记录日志不将日志打印出来
        }
        sae_debug($logstr);
        if($is_debug){
            sae_set_display_errors(true);
        }

    }

那么这样的代码输出的日志是什么样的呢?我们打开sae控制台-应用日志中心-错误日志,看到的是这种场景:

新浪SAE日志中心的魔改打开方式(使用ThinkPHP)_第1张图片
默认日志效果

我们可以看到,这种情况下输出的日志是非常乱的。问题出在哪里呢?我来说明一下:

首先,所有在Log::record()中记录的日志内容,会汇总到一个字符串,最后传给write方法,也就是上文中的代码。通过这个代码我们可以发现问题:

  • 第一个问题,就是sae日志中心对单行日志的长度有限制。我们看上图,日志到了最后一个”第“的位置就截止了,后面的内容都没了。
  • 第二个问题,就是上图中橙色圈中的#015#012。这个是什么呢?观察一下就会发现,这个就是代码中的\r\n。sae日志中心并不支持包含换行符等特殊字符的日志内容,换行只会显示为这个#015#012,令人感到莫名其妙。实际是这样的,SAE这边的日志,都是通过syslog协议传输的,然而syslog协议本身,也是用\n去分割单条日志的,因此,在传输过程中,就需要进行转义了,在rsyslog的配置中,就会直接转义成#xxx的形式,就导致了这种情况。
  • 还有一个小问题,就是上图中蓝色的圈,我们可以看到访问时间和IP被输出了两遍。这是因为sae日志中心默认就会记录访问时间和IP,而ThinkPHP又再次输出了一遍,导致重复。

针对以上问题,我建议用到这个sae日志功能的朋友对代码进行修改:

首先是重复问题,

$now = date($this->config['log_time_format']);
$logstr="[{$now}] ".$_SERVER['REMOTE_ADDR'].' '.$_SERVER['REQUEST_URI']."\r\n{$log}\r\n";

这两行代码改一下,把时间和IP去掉:

$logstr="REQUEST".$_SERVER['REQUEST_URI']."\r\n{$log}";

这样就避免了重复输出时间和IP。

然后是前两个问题,一个简单的改法是:

sae_debug($logstr);

改为

$arr = explode("\r\n", $logstr);
foreach ($arr as $s) {
    sae_debug($s);
}

由于sae对单个请求支持多达1000行日志,所以这样把单行日志拆成多行,既解决了单行长度限制问题,顺便也把不能正常显示的换行符去掉了。

改好之后的效果:

新浪SAE日志中心的魔改打开方式(使用ThinkPHP)_第2张图片
改后效果

可以看到这样一来整齐了很多。

不过这样还不够。再接下来,我要对sae日志中心进行魔改。先上效果图:

新浪SAE日志中心的魔改打开方式(使用ThinkPHP)_第3张图片
魔改效果

这就是最终的魔改效果。

我是怎么做的呢?分两步。第一步,再次修改write方法,为输出的日志添加花边:


$arr = explode("\r\n", $log);
sae_debug("╚════════════════════════════════════════════");
sae_debug('║ REQUEST ['.$_SERVER['REQUEST_URI']."]");
sae_debug("╟────────────────────────────────────────────");
foreach ($arr as $s) {
    if(!empty(trim($s)))
        sae_debug("║ ".$s);
}
sae_debug("╔════════════════════════════════════════════");

第二步,调整网页的css显示效果。我用的是Chrome插件Stylebot。

tbody.showLog.table {
    background-color: #fdf6e3;
}

tbody.showLog.table tr td {
    border-top: 0px;
    padding: 0;
}

tr td img {
    display: none;
}

tr td span {
    color: #000000;
    font-size: 16px;
}

tr td span[title="客户端IP"] {
    color: #b58900;
}

tr td span[title="时区"] {
    color: #008080;
}

tr td span[title="本条日志产生的时刻"] {
    color: #008080;
}

这其中的几点:

  • 一点是去掉日志前面的+号按钮,因为debug日志是并没有LogDetail的,前面有个加号按钮会让人总以为能展开出什么东西,但实际上什么都没有,实在是太让人难受了,所以一定要去掉。
  • 然后就是既然展开不出什么别的东西,那么原有的日志行之间间距就太大了,缩小间距,去掉分割线,也便于展示花边效果。
  • 最后就是配色了,原网页的IP、时间和内容明明有不同的title,显示字体颜色却完全一样,真是浪费。这里我用了类似Solarized Light风格的配色,大家也可以使用自己喜欢的风格。

这里将Stylebot的网址匹配设为sae.sina.com.cn/?service=http&m=applog&level=debug**。注意这种魔改只适用于debug日志,不适用于访问日志(因为访问日志有LogDetail,内容也不能自定义),所以level=debug是要有的。

如此一来魔改就完成了。

魔改后会出现的另一个问题是,日志中心显示的日志是从后往前的,最新的在最上面,而如果下载日志查看的话却是从前往后的,这样一来两种模式的╚╔花边是反的。如果经常需要下载日志查看的话,可以选择不用这种花边。

以上。

你可能感兴趣的:(新浪SAE日志中心的魔改打开方式(使用ThinkPHP))