1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

アクションの前後に開始・終了ログを自動で挟みたい

Last updated at Posted at 2021-09-20

エラーなどでデバッグする時、どのアクションでコケているのか分かりにくいことがあります。
bladeとかControllerの中以外、Requestとかvendoerの中でコケているとどこまで通過しているのかわかりづらい。
そこでアクションの開始時と終了時にログを出しておくと、そもそも始まったのかどうかと、無事に通過したかどうかを判別できて問題の切り分けが楽になります。

コントローラでこれをやるとデメリットもあって悩みどころでした。

・コントローラで全てのアクションにログの出力コードを入れるのは結構大変な労力。
・コードが肥大化する。本文が return viewの1行しかないのにログ出力が開始と終了で2行とか。
・クラス名とアクション名を書くのがめんどくさい。
・クライアントがログの出力を嫌がる場合がある。
・アクセス数が多い本番環境ではログだけでもサーバのディスク容量に負荷がかかる場合がある。別途cronなどで整理する処理が必要になる。

というわけでミドルウェアでなんとかならないか色々ググってたらできたのでメモ。

ミドルウェアを作成する

アクション開始前とアクション終了後に割り込む用のミドルウェアを作る。

php artisan make:middleware BeforeActionLog
php artisan make:middleware AfterActionLog

アクション開始前の処理を書く

handleメソッドに以下を記入する。
$request->route()->getActionName() で
[05:42:57] LOG.debug: App\Http\Controllers\Admin\TemplateController@show
のような文字列が返ってくる。

本番環境では出力させたくない場合、config('app.env')で .envのAPP_ENV= の値を拾ってきて分岐させればいいと思う。

app/Http/Middleware/BeforeActionLog.php
    public function handle(Request $request, Closure $next)
    {
        logger($request->route()->getActionName() . '[START]');

        return $next($request);
    }

アクション終了後の処理を書く

app/Http/Middleware/AfterActionLog.php
    public function handle(Request $request, Closure $next)
    {
        $response = $next($request);
        
        logger($request->route()->getActionName() . '[END]');

        return $response;
    }

ミドルウェアグループに登録する

app/Http/Kernel.php

    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
// ここから追加 -------------------------------------------
        'log' => [
            \App\Http\Middleware\BeforeActionLog::class,
            \App\Http\Middleware\AfterActionLog::class,
        ]
// ここまで追加 -------------------------------------------
    ];

ルーティングに紐づける。

一番上の行の middleware('log') の部分でさっきのミドルウェアグループのキー名の'log' と紐づいています。
どこに書くかはご自身のアプリケーションに合わせてログを出力したいルート範囲に設定してください。

ちなみに、ミドルウェアグループを使わずにメソッドチェーンでBeforeActionLogとAfterActionLogを繋いだら後ろに書いた方しか適用されなくて失敗しました。
もしかするとですが前処理ミドルウェアと後処理ミドルウェアを同時に同じルートに適用するにはミドルウェアグループに登録しないと無理なのかもしれません。

routes/web.php
Route::prefix('admin')->name('admin.')->middleware('log')->group(function() {
    Route::get('login', [App\Http\Controllers\Admin\Auth\LoginController::class,'showLoginForm']);
    Route::post('login', [App\Http\Controllers\Admin\Auth\LoginController::class,'login'])->name('login');
    Route::post('logout', [App\Http\Controllers\Admin\Auth\LoginController::class,'logout'])->name('logout');

    Route::middleware('auth:admin')->group(function() {
        Route::get('/', [App\Http\Controllers\Admin\HomeController::class, 'index'])->name('home');
        Route::get('/home', [App\Http\Controllers\Admin\HomeController::class, 'index'])->name('home');
        Route::resource('/template', App\Http\Controllers\Admin\TemplateController::class);
        Route::resource('/template_item', App\Http\Controllers\Admin\TemplateItemController::class);
    });
});

出力結果

デバッグバーだとこんな感じになれば成功。

スクリーンショット 2021-09-20 16.12.09.png

参考サイト

参考書

PHPフレームワーク Laravel入門 秀和システム

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?