Laravel7 logging 使用 daily日誌保留 7 天是怎麼實現的

Pendant59發表於2020-05-29

如題,為了搞明白這個,熬了個夜,我的頭髮啊
場景: 控制器直接 throw New \Exception(123);
呼叫堆疊:

  1. app/Exceptions/Handler.php:39行,呼叫方法:report

  2. /vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php:122行,呼叫方法:error

  3. /vendor/laravel/framework/src/Illuminate/Log/LogManager.php:547行,呼叫方法:error()->driver():96行 ->get() :115行 ->resolve():187行 -> createDailyDriver():275行

  4. createDailyDriver() 內例項化了 vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php 在建構函式中得到 nextRotation 是明天的時間,並且從配置檔案讀取並賦值了日誌檔案保留個數

  5. /vendor/laravel/framework/src/Illuminate/Log/Logger.php:174行,呼叫方法:error()->addRecord() 在addRecord 中 獲取了當前的時間戳 賦值給 $record[‘datetime’]

  6. /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);
      }
  8. 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() 126if (true === $this->mustRotate) {
             $this->rotate();
         }
     }

    在 rotate() 方法中 校驗maxFiles 然後獲取所有日誌檔案(glob)並排序,最終刪除舊的日誌檔案,並重置 迴圈標識。 到此 daily 渠道的 日誌保留個數就完成了,撒花~

之前看了很多次沒明白,今天熬個夜才搞明白,debug能力還是太差了,有這個時間,摟著媳婦睡覺不香麼?嘿嘿嘿,睡覺

本作品採用《CC 協議》,轉載必須註明作者和本文連結

呦,寫bug呢?

相關文章