API、AJAX的調試:SocketLog
SocketLog方便API,AJAX的調試,能將日志通過WebSocket輸出到Chrome瀏覽器的console中
說明:
-
正在運行的API有bug,不能var_dump進行調試,因為會影響client的調用。這時候用SocketLog最 好,SocketLog 通過websocket將調試日志打印到瀏覽器的console中。你還可以用它來分析開源程序,分析SQL性能,結合taint分析程序漏洞。
-
它能代替ChromePHP、FirePHP等工具,ChromePHP等是通過header通信,適合AJAX調試,但不適合API調試,而且它們是通過Header通信,Chrome瀏覽器對傳遞Header大小有限制,日志如果多了,Chrome瀏覽器就無法支持。
-
SocketLog 支持SAE等特殊的運行環境,ChromePHP,FirePHP都不支持SAE,因為SAE接收不到非標準HTTP協議的Header,而ChromePHP和FirePHP傳遞了自定義Header
-
Chrome插件安裝: https://chrome.google.com/webstore/detail/socketlog/apkmbfpihjhongonfcgdagliaglghcod
-
目錄結構:
-
chrome 目錄是 chrome插件的源代碼
-
chrome.crx 文件是chrome插件的安裝包, 如果你無法從chrome應用商店安裝,可進行手動安裝, 瀏覽器地址欄輸入并打開: chrome://extensions/ ,然后將chrome.crx拖入即可安裝。
-
php 目錄是php相關腳本。 SocketLog.server.php 是一個 Websocket服務器, SocketLog.class.php是發送日志的類庫,我們在發送日志的時候,需要載入這個類庫然后調用函數slog即可。
-
效果展示: 我們在瀏覽網站的時候在瀏覽器console中就知道程序做了什么,這對于二次開發產品十分有用。 下面效果圖在console中打印出瀏覽discuz程序時,執行了哪些sql語句, 以及執行sql語句的調用棧。程序的warning,notice等錯誤信息也可以打到console中。
說明
- 正在運行的API有bug,不能var_dump進行調試,因為會影響client的調用。 將日志寫到文件,查看也不方便,特別是帶調用棧或大數據結構的文件日志,查看日志十分困難。 這時候用SocketLog最好,SocketLog通過websocket將調試日志打印到瀏覽器的console中。你還可以用它來分析開源程序,分析SQL性能,結合taint分析程序漏洞。
- 它能代替ChromePHP、FirePHP等工具,ChromePHP等是通過header通信,適合AJAX調試,但不適合API調試,而且它們是通過Header通信,Chrome瀏覽器對傳遞Header大小有限制,日志如果多了,Chrome瀏覽器就無法支持。
- SocketLog 支持SAE等特殊的運行環境,ChromePHP,FirePHP都不支持SAE,因為SAE接收不到非標準HTTP協議的Header,而ChromePHP和FirePHP傳遞了自定義Header
- Chrome插件安裝: https://chrome.google.com/webstore/detail/socketlog/apkmbfpihjhongonfcgdagliaglghcod (如果不能正常訪問這個頁面,你可以用下面手動安裝的方法進行安裝)
- 目錄結構:
- chrome 目錄是 chrome插件的源代碼
- chrome.crx 文件是chrome插件的安裝包, 如果你無法從chrome應用商店安裝,可進行手動安裝, 瀏覽器地址欄輸入并打開: chrome://extensions/ ,然后將chrome.crx拖入即可安裝。
- php 目錄是php相關腳本。 SocketLog.server.php 是一個 Websocket服務器, SocketLog.class.php是發送日志的類庫,我們在發送日志的時候,需要載入這個類庫然后調用函數slog即可。
- 效果展示: 我們在瀏覽網站的時候在瀏覽器console中就知道程序做了什么,這對于二次開發產品十分有用。 下面效果圖在console中打印出瀏覽discuz程序時,執行了哪些sql語句, 以及執行sql語句的調用棧。程序的warning,notice等錯誤信息也可以打到console中。
使用方法
- 首先,請在chrome瀏覽器上安裝好插件。
- 然后,啟用Websocket服務, 在命令行中運行
php php/SocketLog.server.php
, 將會在本地起一個websocket服務 ,監聽端口是1229 。 如果想服務后臺運行:nohup php php/SocketLog.server.php > /dev/null &
-
在自己的程序中發送日志:
<?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語句。 如下圖所示。
- 圖中顯示出了三條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為實例再對數據庫調試進行演示。
-
注意,有時候在數據比較少的情況下,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( 'User-Agent: '.$_SERVER['HTTP_USER_AGENT'] ); curl_setopt($ch,CURLOPT_HTTPHEADER,$headers);
分析開源程序
有了SocketLog,我們能很方便的分析開源程序,下面以OneThink為例, 大家可以在 http://www.onethink.cn/ 下載最新的OneThink程序。 安裝好OneThink后,按下面步驟增加SocketLog程序。
- 將SocketLog.class.php復制到OneThink的程序目錄中,你如果沒有想好將文件放到哪個子文件夾,暫且放到根目錄吧。
-
編輯入口文件index.php, 再代碼的最前面加載SocketLog.class.php ,并設置SocketLog
<?php include './SocketLog.class.php'; slog(array( 'error_handler'=>true, 'optimize'=>true, 'show_included_files'=>true ),'set_config');
-
編輯ThinkPHP/Library/Think/Db/Driver/Mysqli.class.php 文件, 如果你用的數據庫驅動類型不是mysqli,而是mysql,那么請打開Mysql.class.php, 找到執行sql語句的地方, 這個類中得execute 方法為一個執行sql語句的方法,大約在119行處,增加代碼:
slog($this->queryStr,$this->_linkID);
-
類中的query方法也是一個執行sql語句的地方, 同樣需要增加上面的代碼, 大約在92行增加slog($this->queryStr,$this->_linkID);
-
然后瀏覽網站看看效果:
通過console的日志,訪問每一頁我們都知道程序干了什么,是一件很爽的事情。
- 提示:另一種更簡單的方法,因為OneThink每次執行完sql語句都會調用$this->debug, 所以我們可以把slog($this->queryStr,$this->_linkID); 直接寫在 Db.class.php文件的debug方法中。 這樣不管是mysqli還是mysql驅動都有效。