關(guān)于日志接口,PSR規(guī)范中給出了相當(dāng)好的說明和定義,并且有多種細(xì)分的日記級別。
雖然PSR規(guī)范中詳盡定義了日志接口,然而在用使用開源框架或內(nèi)部框架進(jìn)行項(xiàng)目開發(fā)過程中,實(shí)際上日記的分類并沒有使用得那么豐富,通常只是頻繁集中在某幾類。為了減少不必要的復(fù)雜性,PhalApi特地將此規(guī)范的日志接口精簡為三種,只有:
系統(tǒng)異常類日志用于紀(jì)錄在后端不應(yīng)該發(fā)生卻發(fā)生的事情,即通常所說的系統(tǒng)異常。例如:調(diào)用第三方、的接口失敗了,此時需要紀(jì)錄一下當(dāng)時的場景,以便復(fù)查和定位出錯的原因。又如:寫入一條紀(jì)錄到數(shù)據(jù)紀(jì)錄卻失敗了,此時需要紀(jì)錄一下,以便進(jìn)一步排查。
紀(jì)錄系統(tǒng)異常日志,用法很簡單??梢允褂?a rel="external nofollow" target="_blank" >PhalApi\Logger::error($msg, $data)接口,第一個參數(shù)$msg用于描述日志信息,第二個可選參數(shù)為上下文場景的信息。下面是一些使用示例。
// 只有描述
\PhalApi\DI()->logger->error('fail to insert DB');
// 描述 + 簡單的信息
\PhalApi\DI()->logger->error('fail to insert DB', 'try to register user dogstar');
// 描述 + 當(dāng)時的上下文數(shù)據(jù)
$data = array('name' => 'dogstar', 'password' => '123456');
\PhalApi\DI()->logger->error('fail to insert DB', $data);
上面三條紀(jì)錄,會在日記文件中生成類似以下的日志內(nèi)容。
$ tailf ./runtime/log/201502/20150207.log
2015-02-07 20:37:55|ERROR|fail to insert DB
2015-02-07 20:37:55|ERROR|fail to insert DB|try to register user dogstar
2015-02-07 20:37:55|ERROR|fail to insert DB|{"name":"dogstar","password":"123456"}
業(yè)務(wù)紀(jì)錄日志,是指紀(jì)錄業(yè)務(wù)上關(guān)鍵流程環(huán)節(jié)的操作,以便發(fā)生系統(tǒng)問題后進(jìn)行回滾處理、問題排查以及數(shù)據(jù)統(tǒng)計。如在有緩存的情況下,可能數(shù)據(jù)沒及時寫入數(shù)據(jù)庫而導(dǎo)致數(shù)據(jù)丟失或者回檔,這里可以通過日記簡單查看是否可以恢復(fù)。以及說明一下操作發(fā)生的背景或原由,如通常游戲中用戶的經(jīng)驗(yàn)值添加:
// 假設(shè):10 + 2 = 12
\PhalApi\DI()->logger->info('add user exp', array('name' => 'dogstar', 'before' => 10, 'addExp' => 2, 'after' => 12, 'reason' => 'help one more phper'));
對應(yīng)的日記為:
2015-02-07 20:48:51|INFO|add user exp|{"name":"dogstar","before":10,"addExp":2,"after":12,"reason":"help one more phper"}
開發(fā)調(diào)試類日記,主要用于開發(fā)過程中的調(diào)試。用法如上,這里不再贅述。以下是一些簡單的示例。
// 只有描述
\PhalApi\DI()->logger->debug('just for test');
// 描述 + 簡單的信息
\PhalApi\DI()->logger->debug('just for test', '一些其他的描述 ...');
// 描述 + 當(dāng)時的上下文數(shù)據(jù)
\PhalApi\DI()->logger->debug('just for test', array('name' => 'dogstar', 'password' => '******'));
若上面的error、info、debug都不能滿足項(xiàng)目的需求時,可以使用PhalApi\Logger::log($type, $msg, $data)接口進(jìn)行更靈活的日記紀(jì)錄。
\PhalApi\DI()->logger->log('demo', 'add user exp', array('name' => 'dogstar', 'after' => 12));
\PhalApi\DI()->logger->log('test', 'add user exp', array('name' => 'dogstar', 'after' => 12));
對應(yīng)的日記為:
2015-02-07 21:13:27|DEMO|add user exp|{"name":"dogstar","after":12}
2015-02-07 21:15:39|TEST|add user exp|{"name":"dogstar","after":12}
注意到,第一個參數(shù)為日記分類的名稱,在寫入日記時會自動轉(zhuǎn)換為大寫。其接口函數(shù)簽名為:
/**
* 日記紀(jì)錄
*
* 可根據(jù)不同需要,將日記寫入不同的媒介
*
* @param string $type 日記類型,如:info/debug/error, etc
* @param string $msg 日記關(guān)鍵描述
* @param string/array $data 場景上下文信息
* @return NULL
*/
abstract public function log($type, $msg, $data);
在使用日志紀(jì)錄前,在注冊日志\PhalApi\DI()->logger
服務(wù)時須指定開啟的日志級別,以便允許指定級別的日志得以紀(jì)錄,從而達(dá)到選擇性保存所需要的日志的目的。
通過PhalApi\Logger的構(gòu)造函數(shù)的參數(shù),可以指定日志級別。多個日記級別使用或運(yùn)算進(jìn)行組合。
// 日記紀(jì)錄
$di->logger = new FileLogger(API_ROOT . '/runtime', Logger::LOG_LEVEL_DEBUG | Logger::LOG_LEVEL_INFO | Logger::LOG_LEVEL_ERROR);
上面的三類日記分別對應(yīng)的標(biāo)識如下。
日志類型 | 日志級別標(biāo)識 |
---|---|
error 系統(tǒng)異常類 | PhalApi\Logger::LOG_LEVEL_ERROR |
info 業(yè)務(wù)紀(jì)錄類 | PhalApi\Logger::LOG_LEVEL_INFO |
debug 開發(fā)調(diào)試類 | PhalApi\Logger::LOG_LEVEL_DEBUG |
普遍情況下,我們認(rèn)為將日記存放在文件是比較合理的,因?yàn)楸阌诓榭?、管理和統(tǒng)計。當(dāng)然,如果你的項(xiàng)目需要將日記紀(jì)錄保存在其他存儲媒介中,也可以快速擴(kuò)展實(shí)現(xiàn)的。例如實(shí)現(xiàn)數(shù)據(jù)庫的存儲思路。
<?php
namespace App\Common\Logger;
use PhalApi\Logger;
class DBLogger extends Logger {
public function log($type, $msg, $data) {
// TODO 數(shù)據(jù)庫的日記寫入 ...
}
}
隨后,重新注冊\PhalApiDI()->logger
服務(wù)即可。
$di->logger = new App\Common\Logger\DBLogger(API_ROOT . '/runtime', Logger::LOG_LEVEL_DEBUG | Logger::LOG_LEVEL_INFO | Logger::LOG_LEVEL_ERROR);
更多建議: