紀錄


寫入指定的通道

####### ###先進的Monolog 日誌通道自訂############自訂的Monolog 通道############建立Monolog 處理通道######### ####透過工廠建立通道##################################

簡介

為了幫助你更多的了解應用程式中到底發生了什麼,Laravel 提供了強大的日誌服務,讓你可以將日誌訊息、系統錯誤日誌記錄到文件,甚至使用Slack 通知到你的整個團隊。

在 Laravel 框架中,Laravel 使用 Monolog 函式庫,它為各種強大的日誌處理提供支援。 Laravel 讓配置這些處理程序變得簡單,允許你混合併匹配它們自訂的應用程式日誌處理。

設定

所有的應用程式日誌系統設定都位於config/logging.php 設定檔中。這個檔案允許你配置你的應用程式日誌通道,所以務必查看每個可用的通道及它們的選項。當然,我們將在下面回顧一些常用的選項。

預設情況下,Laravel 將使用  stack 去記錄日誌訊息。 stack 通道被用來將多個日誌通道聚合到一個單一的通道。關於堆疊的更多信息,請查看 以下文件

配置通道名稱

預設情況下,Monolog 使用與目前環境相符的『通道名稱』進行實例化,例如productionlocal。要改變這個值,需要增加一個 name  選項到你的通道設定:

'stack' => [  
  'driver' => 'stack',    
  'name' => 'channel-name',    
  'channels' => ['single', 'slack'],
 ],

可用的通道驅動

名稱描述
stack一個方便建立『多通道』通道的包裝器
single 單一檔案或者基於日誌通道的路徑(StreamHandler)
#daily一個每天輪換的基於Monolog 驅動程式的 RotatingFileHandler
slack#一個基於Monolog 驅動程式的SlackWebhookHandler
##syslog一個基於Monolog 驅動程式的SyslogHandler
errorlog#一個基於Monolog 驅動的ErrorLogHandler
monolog一個可以使用任何支援Monolog 處理程序的Monolog工廠驅動程式
custom一個呼叫指定工廠建立通道的驅動程式

{tip} 有關 monolog  與 custom  驅動,請參閱進階通道自訂

##配置Single 和Daily 通道

singledaily 通道包含三個可選配置項目:bubblepermission locking.

名稱描述預設值
#bubble訊息處理後,指示訊息是否推送到其他通道true
#permission日誌檔案權限644
locking寫入之前嘗試鎖定日誌檔案false
#

設定 Slack 通道

slack 通道需要 url 設定選項。這個 URL 應該與你為 Slack 團隊配置的一個 incoming webhook 相符。

#建置日誌堆疊

#前面說過, stack 驅動程式允許你在單一日誌通道中整合多個通道。讓我們透過一個產品級應用的設定實例來看看如果使用日誌堆疊::

'channels' => [ 
   'stack' => [     
      'driver' => 'stack',        
      'channels' => ['syslog', 'slack'],   
     ],    
      'syslog' => [      
       'driver' => 'syslog',        
       'level' => 'debug',    
      ],    
      'slack' => [       
          'driver' => 'slack',        
          'url' => env('LOG_SLACK_WEBHOOK_URL'),        
          'username' => 'Laravel Log',        
          'emoji' => ':boom:',        
          'level' => 'critical',    
         ],
   ],

我們來分析這個配置。首先要注意的是 stack 透過使用它的 channels 選項聚合了另外兩個通道: syslogslack 。因此,在記錄日誌訊息時,這兩個通道都有機會完成日誌訊息記錄:

日誌等級

請留意上面範例syslogslack 中存​​在的level 設定項。這個選項決定了需要被該頻道記錄的日誌的最低 “等級”。 Monolog (一個功能強勁的Laravel 日誌服務)接受定義在RFC 5424 specification 中的全部等級: emergencyalertcriticalerrorwarningnoticeinfodebug

假設我們使用debug 方法來記錄日誌訊息:

Log::debug('An informational message.');

根據我們的配置, syslog 頻道將把該訊息記錄到系統日誌;不過因為錯誤訊息不是 critical 或更高級別,它將不會被傳送到Slack。如果我們記錄一條emergency 訊息,它將被傳送給系統日誌和Slack,因為emergency 的等級高於兩個通道的最低等級限制:

Log::emergency('The system is down!');

寫入日誌訊息

可以使用Log facade 將資訊寫入日誌。如前所述,日誌提供定義在RFC 5424 specification 中的可用日誌等級: emergencyalertcriticalerrorwarningnoticeinfodebug

Log::emergency($message);
Log::alert($message);
Log::critical($message);
Log::error($message);
Log::warning($message);
Log::notice($message);
Log::info($message);
Log::debug($message);

因此,你可以呼叫這些方法中的任一方法記錄對應等級的日誌。預設情況下,訊息會寫入到在config/logging.php 設定檔中定義的預設日誌通道:

<?php
   namespace App\Http\Controllers;use App\User;
   use Illuminate\Support\Facades\Log;
   use App\Http\Controllers\Controller;
   class UserController extends Controller{   
    /**
     * 显示给定用户的配置信息。
     *
     * @param  int  $id
     * @return Response
     */  
    public function showProfile($id)  
      {     
         Log::info('Showing user profile for user: '.$id);        
         return view('user.profile', ['user' => User::findOrFail($id)]);   
       }
    }

上下文資訊

可以將上下文資料數組傳遞給日誌方法。這些資訊將被格式化,並與日誌訊息一直顯示:

Log::info('User failed to login.', ['id' => $user->id]);

寫入指定通道

有時候你可能希望將訊息寫入到應用預設通道以外的通道。可以使用Log facade 的channel 方法取得定義在設定檔中的任一通道並將訊息寫入其中:

Log::channel('slack')->info('Something happened!');

如果想要建立一個由多通道構成的按需記錄的堆疊,可以使用stack 方法:

Log::stack(['single', 'slack'])->info('Something happened!');

高度自訂Monolog 通道

為通道自訂Monolog

有時需要完全控制已存在通道的Monolog: 例如,你可能想要為給定通道的日誌處理配置自訂的Monolog FormatterInterface 實作:

先在通道配置中定義一個tap 陣列。 tap 陣列包含一個在通道建立後有機會用於自訂Monolog 實例的類別清單:

'single' => [   
 'driver' => 'single',    
 'tap' => [App\Logging\CustomizeFormatter::class],    
 'path' => storage_path('logs/laravel.log'),    
 'level' => 'debug',
],

一旦在通道中有了tap 選項配置,就要準備用於自訂Monolog 實例的類別。這種類別這需要一個方法: __invoke,它接受一個 Illuminate\Log\Logger 實例作為其參數。 Illuminate\Log\Logger 實例將所有方法呼叫代理到基礎的Monolog 實例:

<?php
   namespace App\Logging;
   class CustomizeFormatter{   
    /**
     * 自定义给定的日志实例。
     *
     * @param  \Illuminate\Log\Logger  $logger
     * @return void
     */   
   public function __invoke($logger)   
    {      
      foreach ($logger->getHandlers() as $handler) {        
          $handler->setFormatter(...);      
         }  
      }
   }

{tip} 所有的"tap" 類別都是由服務容器解析的,因此任何依賴它們的構造器都會自動被注入。

建立 Monolog 處理器通道

Monolog 多種 可用處理器。在某些情況下,你會想要只建立一個具有指定處理器的 Monolog 驅動程式的日誌類型。這些通道可以使用 monolog 驅動程式建立。

在使用 monolog 驅動時, handler 設定項用於指定被實例化的處理器。如果該處理器的建構器需要參數,可以使用可選的with 組態項目來指定:

'logentries' => [   
 'driver'  => 'monolog',    
 'handler' => Monolog\Handler\SyslogUdpHandler::class,    
 'with' => [      
   'host' => 'my.logentries.internal.datahubhost.company.com',        
   'port' => '10000',   
   ],
  ],

Monolog 格式化

使用monolog 驅動時,Monolog 的LineFormatter 用於預設的格式化處理器。當然,你也可以使用formatter and formatter_with 設定項自訂格式化處理器類型:

'browser' => [  
  'driver' => 'monolog',    
  'handler' => Monolog\Handler\BrowserConsoleHandler::class,    
  'formatter' => Monolog\Formatter\HtmlFormatter::class,    
  'formatter_with' => [      
    'dateFormat' => 'Y-m-d',  
    ],
  ],

如果所使用的Monolog 處理器能夠提供自訂的格式代處理器,可以將formatter 配置項目指定為default:

#
'newrelic' => [ 
   'driver' => 'monolog',    
   'handler' => Monolog\Handler\NewRelicHandler::class,    
   'formatter' => 'default',
],

透過工廠建立頻道

如果你想定義一個完全自訂的通道,你可以完全控制Monolog 的實例化和配置,你可以在config/logging.php 配置文件中指定custom 驅動程式類型。你的配置應該包含一個via 選項,指向將被呼叫以創建Monolog 實例的工廠類別:

'channels' => [  
  'custom' => [      
    'driver' => 'custom',        
    'via' => App\Logging\CreateCustomLogger::class,   
    ],
 ],

一旦配置了custom 通道,就可以定義創建Monolog 實例的類別。這個類別只需要一個方法: __invoke ,它就可以傳回 Monolog 實例:

<?php
  namespace App\Logging;use Monolog\Logger;
  class CreateCustomLogger{    
      /**
     * 创建一个 Monolog 实例.
     *
     * @param  array  $config
     * @return \Monolog\Logger
     */   
    public function __invoke(array $config) 
      {     
         return new Logger(...);  
       }
     }
本文章首發在 LearnKu.com 網站上。