歡迎閱讀本文,希望能給與你一定的幫助,Laravel新人一枚,技術不過關,如有撰寫錯誤的地方,懇請不吝賜教!
Laravel常規寫入的Log是這樣的,帶有日期和日誌型別:
[2020-04-10 09:37:23] local.INFO: record request message
本文最終實現寫入的Log記錄是純Json格式儲存:
{"datetime":"2020-04-10 09:27:36","message":"record request message","url":"URL","method":"POST"}
配置 config/logging.php
新增自定義通道 request
,有時需要完全控制已存在通道的 Monolog: 比如,你可能想要為給定通道的日誌處理配置自定義的 Monolog FormatterInterface 實現。
先在通道配置中定義一個 tap 陣列
。 tap 陣列包含一個在通道建立後有機會用於自定義 Monolog 例項的類列表。
return [
'channels' => [
'request' => [
'driver' => 'daily',
'path' => storage_path('logs/request.log'),
'level' => 'info',
'days' => 5,
'tap' => [App\Logging\CustomizeFormatter::class],
'value_max_length' => env('REQUEST_LOG_VALUE_MAX_LENGTH', 300),
],
]
]
建立app/Logging/CustomizeFormatter.php
檔案
<?php
namespace App\Logging;
use App\Logging\CustomizeJsonFormatter;
class CustomizeFormatter
{
/**
* 自定義給定的日誌例項。
*
* @param \Illuminate\Log\Logger $logger
* @return void
*/
public function __invoke($logger)
{
foreach ($logger->getHandlers() as $handler) {
$handler->setFormatter(new CustomizeJsonFormatter());
}
}
}
建立app/Logging/CustomizeJsonFormatter.php
檔案
<?php
namespace App\Logging;
use Monolog\Formatter\JsonFormatter;
class CustomizeJsonFormatter extends JsonFormatter
{
// 重構
public function format(array $record): string
{
$newRecord = [
'datetime' => $record['datetime']->format('Y-m-d H:i:s'),
'message' => $record['message'],
];
if (!empty($record['context'])) {
$newRecord = array_merge($newRecord, $record['context']);
}
$json = $this->toJson($this->normalize($newRecord), true) . ($this->appendNewline ? "\n" : '');
return $json;
}
}
建立中介軟體命令:php artisan make:middleware RecordRequestMessage
命令執行後,檔案會生成在app/Http/Middleware/RecordRequestMessage.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
class RecordRequestMessage
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// 記錄所有請求資訊
$requestMessage = [
'url' => $request->url(),
'method' => $request->method(),
'ip' => $request->ips(),
'path' => $request->path(),
'headers' => $request->header(),
'query' => $request->query()
];
if ($request->file()) {
// 檔案內容不做日誌記錄,使用<file>做標識
$requestMessage['body'] = '<file>';
}
else {
// 獲取請求體Body資訊
$bodyContent = $request->all();
// 從.env檔案中獲取引數內容的長度
$parameterLength = \config('logging.channels.request.value_max_length');
if ($bodyContent && in_array($request->method(), ['POST', 'PATCH']))
{
foreach ($request->all() as $key => $value) {
if (Str::length($value) > $parameterLength) {
// 引數內容的長度過大的進行裁剪
$bodyContent[$key] = Str::limit($value, $parameterLength);
}
}
}
$requestMessage['body'] = $bodyContent;
}
Log::channel('request')->info('record request message', $requestMessage);
return $next($request);
}
}
在app/Http/Kernel.php
加入全域性中介軟體
protected $middleware = [
\App\Http\Middleware\RecordRequestMessage::class,
];
最後訪問請求站點,即可在storage/logs/request-xxxx.log
中看到日誌最終效果
{"datetime":"2020-04-10 09:27:36","message":"record request message","url":"URL","method":"POST"}
後續:精簡版
只需要配置config/logging.php
使用內建的Monolog方法實現即可,不需要配置tap陣列
use Monolog\Formatter\JsonFormatter;
use Monolog\Handler\StreamHandler;
return [
'channels' => [
'request' => [
'driver' => 'daily',
'path' => storage_path('logs/request.log'),
'level' => 'info',
'days' => 5,
'handler' => StreamHandler::class,
'formatter' => JsonFormatter::class,
'value_max_length' => env('REQUEST_LOG_VALUE_MAX_LENGTH', 300),
],
]
]
日誌《Laravel 7 中文文件》上沒有介紹到handler
、formatter
這些配置項,對新手而然容易忽略這些便捷的實現方法,從而使用較為複雜的方式來實現最終效果,可查閱官網https://learnku.com/docs/laravel/7.x/logging#creat... 以及Monolog的文件 https://github.com/Seldaek/monolog
參考
日誌《Laravel 7 中文文件》
中介軟體《Laravel 7 中文文件》
https://www.jianshu.com/p/b8e0ef4ef249
本作品採用《CC 協議》,轉載必須註明作者和本文連結