Laravel/Lumen的日誌簡單系統介紹:
Laravel/Lumen的日誌默認是基於Monolog進行了一層封裝,如果要求不高,用起來還是十分容易的,本文基於laravel5.6/Lumen5.6版本進行解說。5.6版對日誌系統做了升級,將日誌的配置單獨放以了config/logging.php 配置文件中,所以現在實用多了。
基本配置(解決日誌路徑文件名和保存週期等)
開始使用Laravel5.5時經常遇到有人問Laravel中日誌的爲什麼只有一個文件,能不能修改日誌目錄,能不能修改日誌文件名?剛開始用時我也有這樣的困惑,由於早期項目簡單(其實是懶),沒有去深入研究。後來跟到了5.6,官方終於發飆了,完美通過配置解決問題(5.5的版本其實也有解決方案,可以自行搜索一下,順便吐槽一下Lavavel官方文檔太簡單了,感覺一大半的強大功能都沒有提及如何深度使用)。以下代理示例,大概的備註了一下參數說明,還有一些可以挖掘。
<?php
// 配置文件路徑:/config/logging.php
return [
// 默認用哪個
'default' => env('LOG_CHANNEL', 'stack'),
'channels' => [
//自定義頻道
'myapplog' => [
// 日誌驅動模式:
'driver' => 'daily',
// 日誌存放路徑
'path' => storage_path('logs/myapplog.log'),
// 日誌等級:
'level' => 'info',
// 日誌分片週期,多少天一個文件
'days' => 1,
],
// 系統默認,可以合併幾個頻道,按等級對應記錄,符合等級條件的都記錄
'stack' => [
'driver' => 'stack',
'channels' => ['single','daily'],
],
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => 'debug',
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => 'info',
'days' => 7,
],
],
];
日誌使用:
<?php
use Log;
class LogTestController extends Controller
{
$message = 'Some message';
$log = ['user_id'=>1,'user_name'=>'abcd'];
Log::channel('myapplog')->info($message, $log); //Log後的數組會自動轉成Json存到日誌記錄中
查看記錄到的效果:
[2018-02-23 10:22:28] local.INFO: Some message {'user_id':1,'user_name':'abcd'}
高階定製:(完全定義日誌格式,本例爲全Json格式)
踩了好多坑,開始嘗試直接自己 new 一個 monolog 的方案,雖然也實現了全 Json 記錄了,但有很多不想要的字段。達不到要求。
幾經折騰,發現 Monolog 有很多可以用的 Formatter ,但發現官方的把字段寫死在裏邊了,抓狂到了想直接改官方源碼的齷齪地步了,還是不死心,最終發現Laravel5.6的logging參數中有一個tap的接口可以用。順着這條線,最終通過重定義 Formatter 的 format() 方法實現了需求 :
1、配置logging.php中的 tap項:
return [
'default' => env('LOG_CHANNEL', 'myapplog'),
'channels' => [
'myapplog' => [
'driver' => 'daily',
'path' => storage_path('logs/myapplog.log'),
// 掛載日誌格式接口(重點)
'tap' => [App\Logging\ApplogFormatter::class],
'level' => 'info',
'days' => 1,
],
],
];
新建App/Logging/ApplogFormatter.php
<?php
namespace App\Logging;
use App\Logging\JsonFormatter;
class ApplogFormatter
{
/**
* Customize the given logger instance.
*
* @param \Illuminate\Log\Logger $logger
* @return void
*/
public function __invoke($logger)
{
foreach ($logger->getHandlers() as $handler) {
$handler->setFormatter(new JsonFormatter());
}
}
}
重點:新建/App/Logging/JsonFormatter.php
<?php
namespace App\Logging;
use Monolog\Formatter\JsonFormatter as BaseJsonFormatter;
class JsonFormatter extends BaseJsonFormatter
{
public function format(array $record)
{
// 這個就是最終要記錄的數組,最後轉成Json並記錄進日誌
$newRecord = [
'time' => $record['datetime']->format('Y-m-d H:i:s'),
'message' => $record['message'],
];
if (!empty($record['context'])) {
$newRecord = array_merge($newRecord, $record['context']);
}
//$json = 'aaa,bbb,ccc'; // 這是最終返回的記錄串,可以按自己的需求改
$json = $this->toJson($this->normalize($newRecord), true) . ($this->appendNewline ? "\n" : '');
return $json;
}
}
Log的記錄方法還是一樣用:
class LogTestController extends Controller
{
$message = 'Some message';
$log = ['user_id'=>1,'user_name'=>'abcd'];
Log::channel('myapplog')->info($message, $log); //Log後的數組會自動轉成Json存
看看最終的效果:
{"time":"2018-06-09 13:39:39","message":"Some message","user_id":1,"user_name":"abcd"}
大功告成!