Yii2 --日志(原創(chuàng)翻譯)

日志

Yii提供了一個高度自定義化和高擴展性的日志框架葛虐。根據(jù)使用場景的不同胎源,你可以很容易的對各種消息就行記錄、過濾屿脐、合并涕蚤,比如說文本文件,數(shù)據(jù)庫文件的诵,郵件万栅。

使用Yii的日志框架包含如下步驟:

  • 調(diào)用日志記錄的方法
  • 在主應(yīng)用的配置文件(例如basic下面的web.php)中配置好日志的過濾和導(dǎo)出的設(shè)置
  • 檢查不同場景下經(jīng)過過濾之后的日志信息

記錄日志

記錄日志其實就是簡簡單單的調(diào)用如下的方法:

上面的這些方法雖然根據(jù)不同的level和類型來記錄信息,但是實際上它們調(diào)用的是同一個方法function($message, $category = 'application')西疤。其中$message就是要記錄的信息烦粒,$category表示的是這個日志的歸屬類。下面的代碼表示在默認的‘a(chǎn)pplication’分類下面記錄了一條trace類型的信息代赁。

 Yii::trace('start calculating average revenue');

提示:記錄的$message可以是簡單的string也可以是復(fù)雜的數(shù)組扰她、對象。你應(yīng)該根據(jù)不同的場景下日志記錄的職責(zé)選取合適的$message類型芭碍。默認情況下徒役,如果你記錄的$message不是String,日志在導(dǎo)出的時候都會調(diào)用[[yii\helpers\VarDumper::export()]] 方法來輸出一個string類型的消息。

為了更好的組織管理及篩選日志消息窖壕,通常情況下應(yīng)當(dāng)為每一種日志分配合適的類別忧勿。你可以選擇一種有明顯等級區(qū)分意思的分類,用以方便根據(jù)不同的目的來篩選不同分類的日志瞻讽。一種簡單且有效的命名方式就是使用PHP的魔術(shù)常量METHOD來作為分類的名稱鸳吸。Yii框架里面的核心代碼在做日志記錄的時候就是這么干的。比如說:

Yii::trace('start calculating average revenue', __METHOD__);

在有常量METHOD出現(xiàn)的地方速勇,它表示的就是當(dāng)前的方法的名稱(并且加上了當(dāng)前方法所屬的類的完整前綴)晌砾。舉個例子吧,如果在app\controllers\RevenueController這個類里面的calculate方法里面有上面的那行代碼快集,那么此時的METHOD表示的就是‘a(chǎn)pp\controllers\RevenueController::calculate’贡羔。

提示:上面所說的方法事實上只是單例對象[[yii\log\Logger|logger object]] 的[[yii\log\Logger::log()|log()]]方法的簡單使用廉白,我們可以通過Yii::getLogger()方法來獲得這個單例對象。當(dāng)我們記錄了足夠的日志信息或者當(dāng)前的應(yīng)用運行結(jié)束了乖寒,日志對象將調(diào)用[yii\log\Dispatcher|message dispatcher]] 方法把記錄的日志信息寫入到配置的目的位置猴蹂。

log targets

一個log target是[[yii\log\Target]]或者其子類的實例。它根據(jù)嚴重的等級和分類類過濾日志楣嘁,然后把日志導(dǎo)出到合適的媒介上面去磅轻。就比如說,一個[[yii\log\DbTarget|database target]] 對象就會把過濾之后的日志信息導(dǎo)出到對應(yīng)數(shù)據(jù)庫逐虚。
你可以在應(yīng)用的配置文件中的日志組件處注冊多個log targets,就像下面這樣:

return [
// the "log" component must be loaded during bootstrapping time
'bootstrap' => ['log'],

'components' => [
    'log' => [
        'targets' => [
            [
                'class' => 'yii\log\DbTarget',
                'levels' => ['error', 'warning'],
            ],
            [
                'class' => 'yii\log\EmailTarget',
                'levels' => ['error'],
                'categories' => ['yii\db\*'],
                'message' => [
                   'from' => ['log@example.com'],
                   'to' => ['admin@example.com', 'developer@example.com'],
                   'subject' => 'Database errors at example.com',
                ],
            ],
        ],
    ],
],
];
注意:日志組件必須在bootstrap中配置聋溜,這樣才能把日志信息分發(fā)到對應(yīng)的log target.

上面的代碼里面,兩個log target注冊到了[[yii\log\Dispatcher::targets]]里面叭爱。

  • 第一個篩選出錯誤和警告信息并且把這些信息保存到了數(shù)據(jù)庫撮躁。
  • 第二個篩選出分類以yii\db*開頭的錯誤信息,并把這些信息通過郵件發(fā)送到admin@example.comdeveloper@example.com.

Yii有下面這些內(nèi)置的log targets,你可以參考API文檔來學(xué)習(xí)具體怎么去配置和使用它們买雾。

接下來把曼,我們就來看看常見的log target具有的功能。

消息過濾

就每一種log target而言漓穿,你可以配置它的 [[yii\log\Target::levels|levels]] 和 [[yii\log\Target::categories|categories]]屬性類設(shè)置它的嚴重程度以及歸屬的分類嗤军。
[[yii\log\Target::levels|levels]]屬性的采用一個數(shù)組里面的一個或者多個值,這個數(shù)組包含如下值:

  • error:對應(yīng)[Yii::error()]記錄的消息
  • warning:對應(yīng)[Yii::warning()]記錄的消息
  • info :對應(yīng) [Yii::info()]記錄的信息
  • trace:對應(yīng) [Yii::trace()]記錄的信息.
  • profile :對應(yīng)[[Yii::beginProfile()]] 和 [[Yii::endProfile()]]記錄的信息晃危,這種方式下面更多詳細信息會被記錄叙赚。

如果你沒有指定[[yii\log\Target::levels|levels]] 的值,那么任何level的信息都會被記錄僚饭。
[[yii\log\Target::categories|categories]] 屬性的值是數(shù)組震叮,這個數(shù)組里面的值可以是一個具體的分類名稱,也可以是類似正則的匹配模式鳍鸵。只有在target能在這個數(shù)組里面找到對應(yīng)的分類名或者符合某一個匹配模式冤荆,他才會處理這些消息。這里的匹配模式的組成是在分類的名稱后面加上一個號权纤。如果這個分類恰好和這個匹配模式的號前的字符匹配,那么也就是這個分類找到對應(yīng)匹配值乌妒。舉個例來說汹想,在類[[yii\db\Command]]中的yii\db\Command::execute和yii \db\Command:: query 方法使用類名類記錄相關(guān)日志信息,那么這個時候他們都匹配模式y(tǒng)ii\db*

同樣的撤蚊,如果我們沒有指定[[yii\log\Target::categories|categories]]古掏,那么每一種分類的日志信息都會被處理。
除了通過[[yii\log\Target::categories|categories]] 屬性來設(shè)置分類的白名單外侦啸,你也可以通過 [[yii\log\Target::except|except]]屬性來設(shè)置分類的黑名單槽唾。屬于黑名單的分類日志信息不會被target處理丧枪。

下面的配置指定了一個分類匹配yii\db*或者 yii\web\HttpException:*,但又不包括yii\web\HttpException:404的分類庞萍,而且它只處理錯誤和警告的日志信息拧烦。

[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
'categories' => [
    'yii\db\*',
    'yii\web\HttpException:*',
],
'except' => [
    'yii\web\HttpException:404',
],
]
注意:當(dāng)錯誤的句柄捕獲到HTTP的異常的時候,記錄的日志信息會以yii\web\HttpException:ErrorCode的這種格式
記錄钝计,例如[[yii\web\NotFoundHttpException]] 就會被記錄成yii\web\HttpException:404

消息格式化

日志targets用多種格式來導(dǎo)出日志恋博。舉個例子,如果你的日志target是[yii\log\FileTarget]私恬,那么你在你的程序中記錄日志的時候债沮,應(yīng)該會找到類似于文件runtime/log/app.log 記錄的如下的信息:

2014-10-04 18:10:15 [::1][][-][trace][yii\base\Module::getModule] Loading module: debug

默認情況下,[[yii\log\Target::formatMessage()]]:會幫我們把日志信息格式化成下面的這種格式:

Timestamp [IP address][User ID][Session ID][Severity Level][Category] Message Text

你可以通過給[[yii\log\Target::prefix]] 屬性配置一個自定義的回調(diào)函數(shù)來 自定義日志的前綴本鸣。下面的代碼就實現(xiàn)了在每條日志信息前面加上了用戶的ID(ip地址疫衩,sessionId等敏感信息因為個人隱私被去掉了)。

[
'class' => 'yii\log\FileTarget',
'prefix' => function ($message) {
    $user = Yii::$app->has('user', true) ? Yii::$app->get('user') : null;
    $userID = $user ? $user->getId(false) : '-';
    return "[$userID]";
}
]

除了日志消息的前綴荣德,日志的target還把一些上下文信息附加在了每一批的日志記錄中闷煤。默認情況下,全局的PHP變量包含$_GET, $_POST, $_FILES, $_COOKIE, $_SESSION 和 $_SERVER. 你可以通過配置 [[yii\log\Target::logVars]] 來調(diào)整日志記錄的全局變量命爬。下面的代碼表示的是只記錄$_SERVER相關(guān)的變量曹傀。

[
'class' => 'yii\log\FileTarget',
'logVars' => ['_SERVER'],
]

當(dāng) 'logVars'為空的時候,表示不記錄相關(guān)的上下文信息饲宛。如果你想自定義上下文信息的提供方式皆愉,你可以覆寫[[yii\log\Target::getContextMessage()]] 方法。

消息的trace等級

在開發(fā)的過程當(dāng)中艇抠,我們總是期望能夠知道每一條日志消息是來自哪里幕庐。在Yii中你可以通過配置[[yii\log\Dispatcher::traceLevel|traceLevel]] 屬性來實現(xiàn)。配置的示例如下:

return [
'bootstrap' => ['log'],
'components' => [
    'log' => [
        'traceLevel' => YII_DEBUG ? 3 : 0,
        'targets' => [...],
    ],
],
];

上面的示例在YII_DEBUG為true的時候?qū)[yii\log\Dispatcher::traceLevel|traceLevel]] 設(shè)置為3家淤,反之設(shè)置為0. 意思是什么呢异剥?3表示每一條日志記錄都會記錄與之相關(guān)的三層棧調(diào)用信息,0表示不記錄任何相關(guān)的棧調(diào)用信息

提示:沒有必要總是記錄調(diào)用的堆棧信息絮重,比較耗性能冤寿。所以,你應(yīng)該只在你開發(fā)的時候或者用于調(diào)試的情況下使用該功能青伤。

消息的清空和導(dǎo)出

就如同上面說的督怜,記錄的消息以數(shù)組的形式保存在[[yii\log\Logger|logger object]]中。為了限制這個數(shù)組消耗過多的內(nèi)存狠角,當(dāng)這個數(shù)組包含的內(nèi)容大小達到某個量的時候會被對應(yīng)的target從內(nèi)存中轉(zhuǎn)移到對應(yīng)的目標(biāo)(文件号杠,數(shù)據(jù)庫...)中。你可以通過設(shè)置 [[yii\log\Dispatcher::flushInterval|flushInterval]] 的值來決定量的大小。像下面這樣:

return [
'bootstrap' => ['log'],
'components' => [
    'log' => [
        'flushInterval' => 100,   // default is 1000
        'targets' => [...],
    ],
],
];
注意:在應(yīng)用運行結(jié)束的時候也會刷新內(nèi)存姨蟋,這樣做事為了讓日志的target能夠記錄完整的信息屉凯。

把日志信息從內(nèi)存刷到對應(yīng)存放的地方的這一動作不是立即發(fā)生的。事實上眼溶,和上面一樣悠砚,都是當(dāng)內(nèi)存中的日志大小達到一定程度才會發(fā)生。你可以像下面的示例一樣通過配置不同target的[[yii\log\Target::exportInterval|exportInterval]]值偷仿,來達到修改的目的:

[
'class' => 'yii\log\FileTarget',
'exportInterval' => 100,  // default is 1000
]

因為清空和導(dǎo)出的設(shè)定哩簿,默認情況下你調(diào)用 Yii::trace() 或者其他的日志記錄方法的時候不會在日志target下立馬看到日志消息。這對某些長時間運行的控制臺程序是一個問題酝静。不過這個問題是可以解決的节榜,方法入下面的代碼,你需要把[[yii\log\Dispatcher::flushInterval|flushInterval]] 和[[yii\log\Target::exportInterval|exportInterval]] 的值都設(shè)置成1:

return [
'bootstrap' => ['log'],
'components' => [
    'log' => [
        'flushInterval' => 1,
        'targets' => [
            [
                'class' => 'yii\log\FileTarget',
                'exportInterval' => 1,
            ],
        ],
    ],
],
];
注意:如此頻繁的清空和導(dǎo)出日志消息會降低系統(tǒng)的性能别智。

切換日志的targets

你可以通過設(shè)置[[yii\log\Target::enabled|enabled]] 屬性來禁止日志的target宗苍。就如同下面的代碼描述的一樣:

Yii::$app->log->targets['file']->enabled = false;

上面的代碼需要你在配置文件里面有一個下面的配置:

return [
'bootstrap' => ['log'],
'components' => [
    'log' => [
        'targets' => [
            'file' => [
                'class' => 'yii\log\FileTarget',
            ],
            'db' => [
                'class' => 'yii\log\DbTarget',
            ],
        ],
    ],
],
];

創(chuàng)建一個新的target

首先,創(chuàng)建一個新的日志target是很簡單的薄榛。你主要做的事情是實現(xiàn)[[yii\log\Target::export()]] 方法并且把數(shù)組類型的消息[[yii\log\Target::messages]]發(fā)送到指定的存儲媒介上去就行了讳窟。在這個過程中你可以調(diào)用[[yii\log\Target::formatMessage()]] 方法來格式化每一條日志消息。至于更多的細節(jié)你可以在Yiid的發(fā)行版本里找到詳細的信息敞恋。

性能評測

性能評測是一種比較特別的日志記錄丽啡。它通常用來獲取某些模塊執(zhí)行時間的數(shù)據(jù),以此來找到性能的問題所在硬猫。比如說补箍,[[yii\db\Command]] 這個類就用性能評測日志來獲得每一條sql查詢所花費的時間。

要使用該類日志啸蜜,你首先要做的時確定你要測試的代碼范圍坑雅。然后在每一段代碼之間你都應(yīng)該要保持它們是閉合的,就像下面這個樣子:

\Yii::beginProfile('myBenchmark');
...code block being profiled...
\Yii::endProfile('myBenchmark');

myBenchmark只是一個標(biāo)識衬横,用于你在查看對應(yīng)日志記錄的時候快速定位裹粤。
在beginProfile和endProfile之間是可以再嵌套的,但是必須保證正確的閉合關(guān)系蜂林,如下所示:

\Yii::beginProfile('block1');

// some code to be profiled

\Yii::beginProfile('block2');
    // some other code to be profiled
\Yii::endProfile('block2');

\Yii::endProfile('block1');

如果上面的閉合關(guān)系出錯了遥诉,對應(yīng)的記錄都不會正常工作。

對于每一塊被評測的代碼噪叙,日志的level都是profile突那。你可以再日志的target中配置這些信息并導(dǎo)出它們。 Yii內(nèi)建了 Yii debugger來展示評測的結(jié)果构眯。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市早龟,隨后出現(xiàn)的幾起案子惫霸,更是在濱河造成了極大的恐慌猫缭,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,378評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件壹店,死亡現(xiàn)場離奇詭異猜丹,居然都是意外死亡,警方通過查閱死者的電腦和手機硅卢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評論 3 399
  • 文/潘曉璐 我一進店門射窒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人将塑,你說我怎么就攤上這事脉顿。” “怎么了点寥?”我有些...
    開封第一講書人閱讀 168,983評論 0 362
  • 文/不壞的土叔 我叫張陵艾疟,是天一觀的道長。 經(jīng)常有香客問我敢辩,道長蔽莱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,938評論 1 299
  • 正文 為了忘掉前任戚长,我火速辦了婚禮盗冷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘同廉。我一直安慰自己仪糖,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,955評論 6 398
  • 文/花漫 我一把揭開白布恤溶。 她就那樣靜靜地躺著乓诽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪咒程。 梳的紋絲不亂的頭發(fā)上鸠天,一...
    開封第一講書人閱讀 52,549評論 1 312
  • 那天,我揣著相機與錄音帐姻,去河邊找鬼稠集。 笑死,一個胖子當(dāng)著我的面吹牛饥瓷,可吹牛的內(nèi)容都是我干的剥纷。 我是一名探鬼主播,決...
    沈念sama閱讀 41,063評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼呢铆,長吁一口氣:“原來是場噩夢啊……” “哼晦鞋!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,991評論 0 277
  • 序言:老撾萬榮一對情侶失蹤悠垛,失蹤者是張志新(化名)和其女友劉穎线定,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體确买,經(jīng)...
    沈念sama閱讀 46,522評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡斤讥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,604評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了湾趾。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芭商。...
    茶點故事閱讀 40,742評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖搀缠,靈堂內(nèi)的尸體忽然破棺而出铛楣,到底是詐尸還是另有隱情,我是刑警寧澤胡嘿,帶...
    沈念sama閱讀 36,413評論 5 351
  • 正文 年R本政府宣布蛉艾,位于F島的核電站,受9級特大地震影響衷敌,放射性物質(zhì)發(fā)生泄漏勿侯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,094評論 3 335
  • 文/蒙蒙 一缴罗、第九天 我趴在偏房一處隱蔽的房頂上張望助琐。 院中可真熱鬧,春花似錦面氓、人聲如沸兵钮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽掘譬。三九已至,卻和暖如春呻拌,著一層夾襖步出監(jiān)牢的瞬間葱轩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評論 1 274
  • 我被黑心中介騙來泰國打工藐握, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留靴拱,地道東北人。 一個月前我還...
    沈念sama閱讀 49,159評論 3 378
  • 正文 我出身青樓猾普,卻偏偏與公主長得像袜炕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子初家,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,747評論 2 361

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理偎窘,服務(wù)發(fā)現(xiàn)乌助,斷路器,智...
    卡卡羅2017閱讀 134,714評論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,859評論 6 342
  • 在應(yīng)用程序中添加日志記錄總的來說基于三個目的:監(jiān)視代碼中變量的變化情況评架,周期性的記錄到文件中供其他應(yīng)用進行統(tǒng)計分析...
    時待吾閱讀 5,057評論 1 13
  • 在應(yīng)用程序中添加日志記錄總的來說基于三個目的:監(jiān)視代碼中變量的變化情況眷茁,周期性的記錄到文件中供其他應(yīng)用進行統(tǒng)計分析...
    時待吾閱讀 4,991評論 0 6
  • 總角 想成為本領(lǐng)超群的齊天大圣七十二變 騰云駕霧 自由及笄 想成為三毛筆下的那棵樹從不依靠 從不尋找 瀟灑花信 想...
    劉發(fā)發(fā)閱讀 298評論 0 0