# 什么是SocketLog?
羅飛大神開發的一個php語言用的調試工具。由服務端和客戶端插件及php擴展類組成。
# SocketLog有什么特色?
- SocketLog通過websocket將調試日志打印到瀏覽器的console中。
適合Ajax調試和API調試, 舉一個常見的場景,用SocketLog來做微信調試, 我們在做微信API開發的時候,如果API有bug,微信只提示“改公眾賬號暫時無法提供服務,請稍候再試” ,我們根本不知道API出來什么問題。 有了SocketLog就不一樣了, 我們可以知道微信給API傳遞了哪些參數, 程序有錯誤我們也能看見錯誤信息(下方有張圖片,可能加載慢,請耐心等待一下)

- 配置allow_client_ids 配置項,讓指定的瀏覽器才能獲得日志
- 方便調試API
- 對數據庫進行調試
- 分析開源項目
- 結合taint分析程序漏洞
# 安裝
1.客戶端
<https://chrome.google.com/webstore/detail/socketlog/apkmbfpihjhongonfcgdagliaglghcod> (如果不能正常訪問這個頁面,你可以用下面手動安裝的方法進行安裝)
目錄結構:
chrome 目錄是 chrome插件的源代碼
chrome.crx 文件是chrome插件的安裝包, 如果你無法從chrome應用商店安裝,可進行手動安裝, 瀏覽器地址欄輸入并打開: chrome://extensions/ ,然后將chrome.crx拖入即可安裝。
2.socket端
啟用Websocket服務,該服務是nodejs寫的,在server目錄下,請先確保你的環境已經安裝nodejs, 啟動Websocket服務運行命令 node server/index.js , 將會在本地起一個websocket服務 ,監聽端口是1229 。 如果想服務后臺運行: nohup node server/index.js > /dev/null &
3.php程序
php 目錄下的`SocketLog.class.php`是發送日志的類庫,我們在發送日志的時候,需要載入這個類庫然后調用函數slog即可。
# 使用
## 在自己的程序中發送日志:
~~~
<?php
include './php/SocketLog.class.php';
slog('hello world');
?>
~~~
## 用slog函數發送日志, 支持多種日志類型:
~~~
slog('msg','log'); //一般日志
slog('msg','error'); //錯誤日志
slog('msg','info'); //信息日志
slog('msg','warn'); //警告日志
slog('msg','trace');// 輸入日志同時會打出調用棧
slog('msg','alert');//將日志以alert方式彈出
slog('msg','log','color:red;font-size:20px;');//自定義日志的樣式,第三個參數為css樣式
~~~
slog函數支持三個參數:
第一個參數是日志內容,日志內容不光能支持字符串喲,大家如果傳遞數組,對象等一樣可以打印到console中。
第二個參數是日志類型,可選,如果沒有指定日志類型默認類型為log。
第三個參數是自定樣式,在這里寫上你自定義css樣式即可。
# 配置
在載入SocketLog.class.php文件后,還可以對SocketLog進行一些配置。
例如:我們如果想將程序的報錯信息頁輸出到console,可以配置
~~~
<?php
include './php/SocketLog.class.php';
slog(array(
'error_handler'=>true
),'set_config');
echo notice;//制造一個notice報錯
slog('這里是輸出的一般日志');
?>
~~~
配置SocketLog也是用slog函數, 第一個參數傳遞配置項的數組,第二個參數設置為set_config
~~~
<?php
include './php/SocketLog.class.php';
slog(array(
'host'=>'localhost',//websocket服務器地址,默認localhost
'port'=>'1229',//websocket服務器端口,默認端口是1229
'optimize'=>false,//是否顯示利于優化的參數,如果運行時間,消耗內存等,默認為false
'show_included_files'=>false,//是否顯示本次程序運行加載了哪些文件,默認為false
'error_handler'=>false,//是否接管程序錯誤,將程序錯誤顯示在console中,默認為false
'force_client_id'=>'',//日志強制記錄到配置的client_id,默認為空
'allow_client_ids'=>array()////限制允許讀取日志的client_id,默認為空,表示所有人都可以獲得日志。
)
,'set_config');
?>
~~~
optimize 參數如果設置為true, 可以在日志中看見利于優化參數,如:[運行時間:0.081346035003662s][吞吐率:12.29req/s][內存消耗:346,910.45kb]
`show_included_files` 設置為true,能顯示出程序運行時加載了哪些文件,比如我們在分析開源程序時,如果不知道模板文件在那里, 往往看一下加載文件列表就知道模板文件在哪里了。
`error_handler` 設置為true,能接管報錯,將錯誤信息顯示到瀏覽器console, 在開發程序時notice報錯能讓我們快速發現bug,但是有些notice報錯是不可避免的,如果讓他們顯示在頁面中會影響網頁的正常布局,那么就設置`error_handler`,讓它顯示在瀏覽器console中吧。 另外此功能結合php taint也是極佳的。 taint能自動檢測出xss,sql注入, 如果只用php taint, 它warning報錯只告訴了變量輸出的地方,并不知道變量在那里賦值、怎么傳遞。通過SocketLog, 能看到調用棧,輕松對有問題變量進行跟蹤。 更多taint的信息:<http://www.laruence.com/2012/02/14/2544.html>
設置`client_id`: 在chrome瀏覽器中,可以設置插件的`Client_ID` ,`Client_ID`是你任意指定的字符串。

設置client_id后能實現以下功能:
1,配置`allow_client_ids` 配置項,讓指定的瀏覽器才能獲得日志,這樣就可以把調試代碼帶上線。 普通用戶訪問不會觸發調試,不會發送日志。 開發人員訪問就能看的調試日志, 這樣利于找線上bug。 `Client_ID` 建議設置為姓名拼命加上隨機字符串,這樣如果有員工離職可以將其對應的`client_id`從配置項`allow_client_ids`中移除。 `client_id`除了姓名拼音,加上隨機字符串的目的,以防別人根據你公司員工姓名猜測出`client_id`,獲取線上的調試日志。
設置`allow_client_ids`示例代碼:
~~~
slog(array(
'allow_client_ids'=>array('luofei_zfH5NbLn','easy_DJq0z80H')
),'set_config')
~~~
2, 設置`force_client_id`配置項,讓后臺腳本也能輸出日志到chrome。 網站有可能用了隊列,一些業務邏輯通過后臺腳本處理, 如果后臺腳本需要調試,你也可以將日志打印到瀏覽器的console中, 當然后臺腳本不和瀏覽器接觸,不知道當前觸發程序的是哪個瀏覽器,所以我們需要強制將日志打印到指定`client_id`的瀏覽器上面。 我們在后臺腳本中使用SocketLog時設置`force_client_id` 配置項指定要強制輸出瀏覽器的`client_id` 即可。
示例代碼:
~~~
<?php
include './php/SocketLog.class.php';
slog(array(
'force_client_id'=>'luofei_zfH5NbLn'
),'set_config');
slog('test'); `
~~~
# 對數據庫進行調試
* SocketLog還能對sql語句進行調試,自動對sql語句進行explain分析,顯示出有性能問題的sql語句。 如下圖所示。
![enter image description here][3]
* 圖中顯示出了三條sql語句 , 第一條sql語句字體較大,是因為它又性能問題, 在sql語句的后臺已經標注Using filesort。 我們還可以點擊某個sql語句看到sql執行的調用棧,清楚的知道sql語句是如何被執行的,方便我們分析程序、方便做開源程序的二次開發。圖中第三條sql語句為被點開的狀態。
* 用slog函數打印sql語句是,第二個參數傳遞為mysql或mysqli的對象即可。 示例代碼:
~~~
$link=mysql_connect( 'localhost:3306' , 'root' , '123456' , true ) ;
mysql_select_db('kuaijianli',$link);
$sql="SELECT * FROM `user`";
slog($sql,$link);
~~~
后面會以OneThink為實例再對數據庫調試進行演示。
通過上面的方法,socketlog還能自動為你檢測沒有where語句的sql操作,然后自動提示你。
* 注意,有時候在數據比較少的情況下,mysql查詢不會使用索引,explain也會提示Using filesort等性能問題, 其實這時候并不是真正有性能問題, 你需要自行進行判斷,或者增加更多的數據再測試。
##對API進行調試
網站調用了API ,如何將API程序的調試信息也打印到瀏覽器的console中? 前面我們講了一個配置 `force_client_id`, 能將日志強制記錄到指定的瀏覽器。 用這種方式也可以將API的調試信息打印到console中,但是`force_client_id` 只能指定一個`client_id`, 如果我們的開發環境是多人共用,這種方式就不方便了。
其實只要將瀏覽器傳遞給網站的User-Agent 再傳遞給API, API程序中不用配置`force_client_id`, 也能識別當前訪問程序的瀏覽器, 將日志打印到當前訪問程序的瀏覽器, 我們需要將SDK代碼稍微做一下修改。 調用API的SDK,一般是用curl寫的,增加下面代碼可以將瀏覽器的User-Agent傳遞到API 。
~~~
$headers=array();
if(isset($_SERVER['HTTP_USER_AGENT']))
{
$headers[]='User-Agent: '.$_SERVER['HTTP_USER_AGENT'];
}
if(isset($_SERVER['HTTP_SOCKETLOG']))
{
$headers[]='Socketlog: '.$_SERVER['HTTP_SOCKETLOG'];
}
curl_setopt($ch,CURLOPT_HTTPHEADER,$headers);
~~~
## 在Freelog案列中的應用
首先,入口包含類庫,和設置好配置

然后,修改了數據庫驅動文件`/ThinkPHP/Library/Think/Db/Driver.class.php`的 query 和execute 方法


然后瀏覽網站看看效果:

通過console的日志,訪問每一頁我們都知道程序干了什么,是一件很爽的事情。
- 序
- 前言
- 內容簡介
- 目錄
- 基礎知識
- 起步
- 控制器
- 模型
- 模板
- 命名空間
- 進階知識
- 路由
- 配置
- 緩存
- 權限
- 擴展
- 國際化
- 安全
- 單元測試
- 拿來主義
- 調試方法
- 調試的步驟
- 調試工具
- 顯示trace信息
- 開啟調試和關閉調試的區別
- netbeans+xdebug
- Socketlog
- PHP常見錯誤
- 小黃鴨調試法,每個程序員都要知道的
- 應用場景
- 第三方登錄
- 圖片處理
- 博客
- SAE
- REST實踐
- Cli
- ajax分頁
- barcode條形碼
- excel
- 發郵件
- 漢字轉全拼和首字母,支持帶聲調
- 中文分詞
- 瀏覽器useragent解析
- freelog項目實戰
- 需求分析
- 數據庫設計
- 編碼實踐
- 前端實現
- rest接口
- 文章發布
- 文件上傳
- 視頻播放
- 音樂播放
- 圖片幻燈片展示
- 注冊和登錄
- 個人資料更新
- 第三方登錄的使用
- 后臺
- 微信的開發
- 首頁及個人主頁
- 列表
- 歸檔
- 搜索
- 分頁
- 總結經驗
- 自我提升
- 進行小項目的鍛煉
- 對現有輪子的重構和移植
- 寫技術博客
- 制作視頻教程
- 學習PHP的知識和新特性
- 和同行直接溝通、交流
- 學好英語,走向國際
- 如何參與
- 瀏覽官網和極思維還有看云
- 回答ThinkPHP新手的問題
- 嘗試發現ThinkPHP的bug,告訴官方人員或者push request
- 開發能提高效率的ThinkPHP工具
- 嘗試翻譯官方文檔
- 幫新手入門
- 創造基于ThinkPHP的產品,進行連帶推廣
- 展望未來
- OneThink
- ThinkPHP4
- 附錄