blog

[Laravel] ユーザーのリクエストとサーバーの応答を記録する

ここでは、環境とLaravelフレームワークをインストールしたと仮定します。 1.Laravelプロジェクトのルートディレクトリにミドルウェアを作成し、次の実装:エラーが報告されていない場合、それは次...

Mar 16, 2020 · 5 min. read
シェア

プロジェクトでは、単に要求処理と応答の良い仕事をすることができますが、また、すべてのユーザーの行動の完全な記録を必要とするため、抜け穴やバグがあるかどうか、プロジェクトの開発のためのLaravelフレームワークの使用などのプログラムの把握を容易にするために、あなたは、ユーザーの要求とサーバーがミドルウェア上のデータに対応する応答を与えるために記録することができます。

ここでは、環境とLaravelフレームワークがインストールされていることを前提としています。

ミドルウェアの作成

Laravelプロジェクトのルートディレクトリに移動し、以下を実行します:

php artisan make:middleware UserRequestAndResponse

エラーが報告されなければ、以下のように成功を示します:

Middleware created successfully.

カスタムログクラス

アプリのディレクトリに移動し、新しいフォルダ「Utils」を作成します。

cd app && mkdir Utils

新しい PHP クラスファイルCustomLogger作成します:

<?php
namespace App\Utils; 
use Illuminate\Support\Facades\Log;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
class CustomLogger 
{ 
 /** 
 * @param $message 
 * @param array $data 
 * @param string $filename 
 * @param string $type 
 */ 
 private static function _save($message, $data = [], $filename = 'log' , $type = 'info') 
 { 
 try{ 
 $dir_name = $filename; 
 $log = new Logger('req_res'); 
 if (PHP_SAPI == 'cli') { 
 // スクリプトへのコマンドラインアクセスについては、ユーザーブラウザのアクセスと区別するためにcliを追加する。
 $filename .= '_cli'; 
 } 
 $filename = date('Y-m-d') . '-'.$filename .'.log'; 
 $path = storage_path('logs/'.$dir_name); 
 // 時々、Opsは、ログを書き込むために失敗につながることができる番号に許可を与えていない。
 self::mkDirs($path); 
 $path = $path . '/' . $filename; 
 if (gettype($data) != 'array') { 
 $message .= ":". $data; 
 $data = []; 
 } 
 if($type == 'info'){ 
 $log->pushHandler(new StreamHandler($path, Logger::INFO)); 
 $log->addInfo($message, $data); 
 }else{ 
 $log->pushHandler(new StreamHandler($path, Logger::ERROR)); 
 $log->addError($message , $data); 
 } 
 }catch (\Exception $e){ 
 Log::info("ロギングエラー:".$e->getMessage()); 
 }
 } 
 /** 
 * @param $message 
 * @param array $data 
 * @param string $filename 
 */ 
 public static function info($message, $data = [], $filename = 'info') 
 { 
 self::_save($message, $data, $filename); 
 } 
 /** 
 * @param $message 
 * @param array $data 
 * @param string $filename 
 */ 
 public static function error($message, $data = [], $filename = 'error') 
 { 
 // あまり多くのエラーログはないだろう、ちょうど単一のファイル。
 self::_save($message, $data, $filename); 
 } 
 /** 
 * ログフォルダにアクセス許可を与える
 *
 * @param $dir 
 * @param int $mode 
 * @return bool 
 */ 
 public static function mkDirs($dir, $mode = 0777) 
 { 
 if (is_dir($dir) || @mkdir($dir, $mode)) {
 return TRUE; 
 } 
 if (!self::mkdirs(dirname($dir), $mode)) { 
 return FALSE; 
 } 
 return @mkdir($dir, $mode); 
 } 

CustomLogger ロギング・クラスは次のように使用します:

use App\Utils\CustomLogger;
/**
* ログ名を定義する
*/
const LOG_NAME = 'req_res';
# メソッドでは
CustomLogger::info($message , $data , self::LOG_NAME);
CustomLogger::error($message , $data , self::LOG_NAME);

UserRequestAndResponseミドルウェアの編集

ファイルの場所

app/Http/Middleware/UserRequestAndResponse.php
<?php
namespace App\Http\Middleware;
use App\Utils\ReqResLogger;
use Closure;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UserRequestAndResponse
{ 
 protected $sequence; 
 protected $code;
 const LOG_NAME = 'req_res';
 /** 
 * リクエストとレスポンスデータのログ
 * 
 * UserRequestAndResponse constructor. 
 * @param Request $request 
 */ 
 public function __construct(Request $request) 
 { 
 $this->code = $request->path(); 
 $this->sequence = str_pad(microtime(true), 15, 0); 
 } 
 /** 
 * メインアプリケーションを処理する. 
 * 
 * @param \Illuminate\Http\Request $request 
 * @param \Closure $next 
 * @return mixed 
 */ 
 public function handle($request, Closure $next) 
 { 
 ReqResLogger::info("======================================" , [] , self::LOG_NAME);
 $this->request($request); 
 $response = $next($request); 
 if ($response instanceof JsonResponse) { 
 $this->response($response); 
 }
 $this->time(); 
 ReqResLogger::info("======================================" , [] , self::LOG_NAME); return $response; 
 } 
 /** 
 * 時間計算
 * 
 */ 
 protected function time():void 
 { 
 $start = str_pad(LARAVEL_START, 15, 0);
 $end = str_pad(microtime(true), 15, 0);
 $standard = config('develop.runtime-lower-limit');
 $time = ($end - LARAVEL_START) * 1000;
 switch (true) {
 case $time > $standard:
 $mark = ' [>]';
 $diff = $time - $standard;
 break;
 case $time === $standard: 
 $mark = ' [=]';
 $diff = 0;
 break;
 default:
 $mark = ' [<]';
 $diff = $time - $standard;
 } 
 $message = "リクエスト番号[{$this->sequence}] リクエストインターフェース[{$this->code}] 開始時間[{$start}] 終了時間[{$end}] ランタイム[{$time}] {$mark}[{$standard}] {$diff} ;
 ReqResLogger::info($message ,[], self::LOG_NAME); } 
 /** 
 * ロギングを要求する
 * 
 * @param $request 
 */ 
 protected function request($request):void 
 { 
 $input = $request->input();
 if (array_key_exists('data', $input)) {
 $input['data'] = json_decode($input['data'], true);
 }
 ReqResLogger::info("リクエストデータ:",$input, self::LOG_NAME); } 
 /** 
 * 応答ロギング
 * 
 * @param JsonResponse $response 
 */ 
 protected function response(JsonResponse $response):void 
 { 
 $output = json_decode($response->getContent(), true); 
 if (json_last_error() === JSON_ERROR_NONE) { 
 ReqResLogger::info("応答データ:",$output, self::LOG_NAME); } 
 }
}

カーネルファイルを編集

ファイルの場所

app/Http/Kernel.php
protected $middleware = [ 
 \App\Http\Middleware\TrustProxies::class, 
 \App\Http\Middleware\CheckForMaintenanceMode::class, 
 \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, 
 \App\Http\Middleware\TrimStrings::class, 
 \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, 
+ \App\Http\Middleware\UserRequestAndResponse::class];

これでコンフィギュレーションは終了です。

プロジェクトがアクセスされると、storage/logsディレクトリに新しいディレクトリres_reqが作成され、その中にログファイルが生成されます。xxxx-xx-xx-res_req.log

それを試してみて、将来的にユーザーの要求とサーバーの応答の記録があるでしょう、長い息......心はしっかりしています。

Read next

Kubeletポッド作成ワークフロー

Kubeletの4つのコンポーネントの1つであるKubeletは、Podのライフサイクル全体を維持し、Podを作成するチェーンの最後のリンクとなります。今回はKubeletを使ったPodの作成方法を紹介します。 KubeletはAPIレイヤー、syncLoopレイヤー、...と大きく3つのレイヤーに分かれていることがわかります。

Mar 16, 2020 · 18 min read