Lesson 13

ログ

Lesson 13 Chapter 1
ログの確認とローテーション

Lesson13ではログについて学習していきましょう。ログの認識や使い方を学んでおくことで作業効率の向上やバグの早期発見、エラー対応などが行いやすくなります。

ログとは

LaravelにはLogファイルにログを残す機能が存在します。ユーザーがサービスを利用している中で起きたエラーなどをログとして残しておくことで開発者は素早い対応が可能となります。又、エラー内容をログに残すことで、ある程度の原因を絞り込むことができ、開発者側にとってもエラーの修正を行いやすい状況を作ることが可能です。

ログの実行準備

それでは早速Laravelのログの機能を利用する為の準備を行なっていきます。ログの処理を以下メソッドに追記してみましょう。

app > Http > Controllers > TodosController.php

TodosController.php
<?php

namespace App\Http\Controllers;

// 省略

// 追記
use Illuminate\Support\Facades\Log;


class TodosController extends Controller
{
    public function TodoLists()
    {
        // 追記
        Log::debug([
            "ログインユーザーID: " . Auth::id(),
            "ログインユーザー名: " . Auth::user()->name,
        ]);

        $todos = Todo::get()->sortBy("todo_time");

        return view("top", compact("todos"));
    }

TodosControllerのTodoListsメソッドでLogクラスを呼び出します。Logクラスにはdebugメソッドが用意されていますので、debugメソッド内にログへ残したい内容を設定しておきましょう。今回はユーザーがログインする度にログインしたユーザーのIDと名前がログに書き込まれるように設定しました。又、Logクラスを使用する為、use宣言も忘れずに行います。

ログの動作確認

続いてはログの動作確認を行っていきます。ログインを行ってみましょう。Laravelではデフォルトで以下ファイルにログが残るようになっています。

storage > logs > laravel.log

laravel.log
[2023-03-26 09:50:35] local.DEBUG: array (
  0 => 'ログインユーザーID: 1',
  1 => 'ログインユーザー名: テスト太郎',
)  

ここまで教材を進めてくる中で、恐らくいくつかのエラーに直面していると思います。その際のエラーも全てlaravel.logへ残っている状態なのでlaravel.log内に他のエラーも表示されている場合は一度全て消去し、空白の状態で再度TODO一覧画面でブラウザの更新を行いlaravel.logを確認してみると、上記のようにユーザーIDと名前だけが表示されている状態になっているはずです。

ログの設定(ログのローテーション)

デフォルトでは発生したエラーなど全てのログが一つのlaravel.logへ集約されている為、該当箇所を調べるまでの時間を要してしまいます。そこで1日ごとにログを分ける設定を行い、管理上の効率を上げていきます。設定箇所は2箇所です。

config > logging.php

1箇所目
logging.php
'default' => env('LOG_CHANNEL', 'daily'),

1箇所目はlogging.phpの修正です。デフォルトではenvの第二引数に「stack」が指定されていますが「daily」へ変更しましょう。dailyは日毎にファイルを作成しログを出力するドライバになります。こちらもLaravelでは標準で用意されています。

2箇所目
.env
LOG_CHANNEL=daily

envファイルにもデフォルトでLOG_CHANNELLに「stack」が設定されているので、こちらも「daily」へ変更します。これで設定は完了になります。envファイルに変更を加えた為、以下2コマンドを実行しておきます。

ターミナル、コマンドプロンプト
php artisan config:cache
ターミナル、コマンドプロンプト
php artisan cache:clear

再度TODO一覧画面でブラウザの更新を行ってみるとlogsディレクトリの配下に「laravel-年-月-日.log」ファイルが生成されていますので、ファイルの中身を確認しておきます。

storage > logs > laravel-年-月-日.log

laravel-年-月-日.log
[2023-03-26 12:10:04] local.DEBUG: array (
  0 => 'ログインユーザーID: 1',
  1 => 'ログインユーザー名: テスト太郎',
)  

これでログを日毎に分ける設定が完了しました。今後は0時を回った段階でエラー等が発生すれば自動的に翌日のlogファイルが作成され、そこへログが残されていきます。

Lesson 13 Chapter 2
ログインエラーをログファイルに書き込む

chapter2ではchapter1で学習した内容も踏まえて、ログインエラーをログに出力していきます。

仕様の確認

今回の仕様としては、ログインに成功した場合はログに何も残さず、失敗した場合にのみ入力されたメールアドレスとパスワードをログへ残していきます。ログのイメージは以下になります。

laravel.log
[2023-03-26 12:17:55] local.DEBUG: array (
  0 => 'ログインに失敗しました。',
  1 => 'メールアドレス : shippai@com',
  2 => 'パスワード : shippaipass',
)

実装準備

logへ出力するための準備を行っていきましょう。前回設定を終わらせたので、今回は容易に実装することが可能です。該当処理のメソッドへ処理を追記します。

app > Http > Controllers > Auth > LoginController.php

LoginController.php
<?php

namespace App\Http\Controllers;

// 省略

// 追記
use Illuminate\Support\Facades\Log;


class TodosController extends Controller
{

    // 省略


    public function loginCheck(Request $request)
    {
        $email = $request->email;
        $password = $request->password;

        if (!Auth::attempt(["email" => $email, "password" => $password])) {

            // 追記
            Log::debug([
                "ログインに失敗しました。",
                "メールアドレス:" . $email,
                "パスワード:" . $password
            ]);

            session()->flash(
              "error_message",
              "メールアドレス、又はパスワードの入力に誤りがあります。"
            );

            return redirect()->route("login");
        }

        return redirect()->route("todo.lists");
    }

ログを出力するタイミングとしては「ログインに失敗したとき」になる為、ログインの処理であるloginCheckメソッドへ処理を記述していきます。loginCheckメソッドにあるif文の処理がログイン失敗時の処理に該当する部分なので、chapter1と同様Logクラスを呼び出し、debugメソッド内にログとして残したい内容を設定しておきます。

動作確認

準備はこれで以上になります。ログイン画面へ戻り、未登録のログイン情報を入力してみましょう。

storage > logs > laravel-年-月-日.log

laravel-年-月-日.log
[2023-03-26 12:17:55] local.DEBUG: array (
  0 => 'ログインに失敗しました。',
  1 => 'メールアドレス : (メールアドレスに入力した内容)',
  2 => 'パスワード: (パスワードに入力した内容)',
)

このようにlogファイルへログが出力されていれば成功です。

Lesson 13 Chapter 3
TODOの作成エラーをログファイルに書き込む

chapter3ではTODO作成時のエラーをログファイルに出力してみましょう。

仕様の確認

TODO作成時に入力の不備等でバリデーションが発生した場合のみ、laravel.logへ出力していきます。ログのイメージは以下になります。

laravel.log
[2023-03-26 14:20:23] local.DEBUG: 優先度 : 必須項目です。
[2023-03-26 14:20:23] local.DEBUG: 時間 : 必須項目です。
[2023-03-26 14:20:23] local.DEBUG: タスク入力欄 : 必須項目です。

実装準備

TODO作成の処理はFormRequestを使用したバリデーションの設定を行っています。FormRequestの場合は、バリデーションが発生した際にControllerの処理は実行されずFormRequestの処理としてページのリダイレクトが行われる為、ログインエラーの時のようにControllerでLogクラスを使用することができません。その場合は、blade.phpからログへ出力する方法もあるので、今回はそちらをご紹介します。create.blade.phpを開きましょう。

resources > views > create.blade.php

create.blade.php

// 優先度のエラーメッセージ
@if($errors->first("priority"))
    {{ $errors->first("priority") }}
    // 追加
    {{ logger()->debug("優先度 : " . $errors->first("priority")) }}
@endif
create.blade.php

// 時間のエラーメッセージ
@if($errors->first("time"))
    {{ $errors->first("time") }}
    // 追加
    {{ logger()->debug("時間 : " . $errors->first("time")) }}
@endif
create.blade.php

// タスク入力欄のエラーメッセージ
@if($errors->first("todo"))
    {{ $errors->first("todo") }}
    // 追加
    {{ logger()->debug("タスク入力欄 : " . $errors->first("todo")) }}
@endif

create.blade.phpの上記3箇所にデーションメッセージの下へログへ出力する処理を追加しましょう。

logger

logger()
logger()->debug("出力したい内容")

Laravelではヘルパ関数としてloggerヘルパが用意されています。役割はLogクラスと変わりません。blade.phpでクラスを呼び出すことができない為、今回はloggerを使用してログの出力を実装しました。

動作確認

準備は以上となります。TODO作成フォームより、バリデーションが発生する条件で追加ボタンをクリックしてみてください。

laravel-年-月-日.log
[2023-03-26 14:20:23] local.DEBUG: 優先度 : 必須項目です。
[2023-03-26 14:20:23] local.DEBUG: 時間 : 必須項目です。
[2023-03-26 14:20:23] local.DEBUG: タスク入力欄 : 必須項目です。

Lesson 13 Chapter 4
ログの出し分けをする

chapter4ではログの出し分けを行っていきましょう。ログを任意に出し分けておくことで、状況の管理向上に繋がります。

仕様の確認

ログの出し分けとは、ログによって出力するログファイルを変更することを言います。これまではどの処理においても当日のログに出力されていましたが、例えばログインに関するログのみ別のログファイルに出力することも可能です。今回はログインのログのみ別ファイルに出力していきます。

実装準備

変更は主に各ドライバの設定が行われているlogging.phpになります。logging.phpを開きましょう。

config > logging.php

logging.php
'channels' => [
        'stack' => [
            'driver' => 'stack',
            'channels' => ['single', 'login'], // ←追加
            'ignore_exceptions' => false,
        ],

今回は新たに「login」チャンネルを作成していきます。こちらは任意なので、プロジェクトや仕様に合わせて命名が可能です。既存のchannelsへ「login」を追加しましょう。

logging.php
'channels' => [

// 省略

// 追加
'login' => [
    'driver' => 'daily',
    'path' => storage_path('logs/login.log'),
    ],
];

実際にloginチャンネルを作成している記述になります。storage_pathで指定したファイルが新たに作成されます。今回はログイン時のログになる為、login.logを作成しそこへログインに関するログを出力していきます。

app > Http > Controllers > Auth > LoginController.php

LoginController.php
<?php

namespace App\Http\Controllers;

// 省略

// 追記
use Illuminate\Support\Facades\Log;

class TodosController extends Controller
{

    // 省略

    public function loginCheck(Request $request)
    {
        $email = $request->email;
        $password = $request->password;

        if (!Auth::attempt(["email" => $email, "password" => $password])) {

            // 追記
            Log::channel("login")->debug("login.logへ出力テスト");

            session()->flash(
              "error_message",
              "メールアドレス、又はパスワードの入力に誤りがあります。"
            );

            return redirect()->route("login");
        }

        return redirect()->route("todo.lists");
    }

最後にログを出力する処理を追加しましょう。作成した任意のログファイルへ出力する場合はLogクラスにchannnel("チャンネル名")と指定してあげる必要があります。

動作確認

準備は整いましたので、早速動作確認を行っていきます。ログイン画面でログインに失敗してみましょう

storage > logs > login.log

login-年-月-日.log
[2023-03-27 10:59:34] local.DEBUG: login.logへ出力テスト

ログインに関するログのみlogin.logへ出し分けを行うことができました。このようにデバッグやバグなど扱うログによってはディレクトリを分けておくとより管理が行いやすくなる為、方法として認識しておきましょう。