如題,爲了搞明白這個,熬了個夜,我的頭髮啊
場景: 控制器直接 throw New \Exception(123);
調用堆棧:
- app/Exceptions/Handler.php:39行,調用方法:report
- /vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php:122行,調用方法:error
- /vendor/laravel/framework/src/Illuminate/Log/LogManager.php:547行,調用方法:error()->driver():96行 ->get() :115行 ->resolve():187行 -> createDailyDriver():275行
- createDailyDriver() 內實例化了 vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php 在構造函數中得到 nextRotation 是
明天
的時間,並且從配置文件讀取並賦值了日誌文件保留個數 - /vendor/laravel/framework/src/Illuminate/Log/Logger.php:174行,調用方法:error()->addRecord() 在addRecord 中 獲取了
當前的時間戳
賦值給 $record[‘datetime’] - /vendor/monolog/monolog/src/Monolog/Logger.php:323行,調用方法:handle()
7.最終調用了 vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php 的108行 write()
protected function write(array $record): void
{
// on the first record written, if the log is new, we should rotate (once per day)
if (null === $this->mustRotate) {
# 這裏判斷$this->url 就是 當天的日誌文件,不存在的話 循環標識就是 true
# 也就是標誌 在rotate()方法 可以刪除舊日誌 只有當天第一次寫入日誌的時候會觸發舊日誌的刪除
$this->mustRotate = !file_exists($this->url);
}
if ($this->nextRotation <= $record['datetime']) {
# 沒看懂這個if 因爲獲取的nextRotation時間永遠是明天凌晨,
# $record['datetime'] 永遠是今天的當前時間
$this->mustRotate = true;
$this->close();
}
parent::write($record);
}
- RotatingFileHandler 繼承自 StreamHandler 繼承自 AbstractProcessingHandler 繼承自 AbstractHandler 繼承自 vendor/monolog/monolog/src/Monolog/Handler/Handler.php
在 抽象類 Handler 的析構方法中
public function __destruct()
{
try {
$this->close(); # 調用了 close()
} catch (\Throwable $e) {
// do nothing
}
}
回到 RotatingFileHandler 的close方法(60行)
/**
* {@inheritdoc}
*/
public function close(): void
{
parent::close();
# 這裏的 if 條件在當天第一次記錄日誌的時候是已經成立的,然後進入rotate() 126行
if (true === $this->mustRotate) {
$this->rotate();
}
}
在 rotate() 方法中 校驗maxFiles 然後獲取所有日誌文件(glob)並排序,最終刪除舊的日誌文件,並重置 循環標識。 到此 daily 渠道的 日誌保留個數就完成了,撒花~
之前看了很多次沒明白,今天熬個夜才搞明白,debug能力還是太差了,有這個時間,摟着媳婦睡覺不香麼?嘿嘿嘿,睡覺