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