Laravel Log dailyログとerrorログを別々に出力する

## 目的

- エラーログだけ別ファイルに出力して欲しい時の方法を下記に記載する。

## 実施環境

- MacのローカルにLaravelの環境を構築して実施する。環境構築手順の記事はリンクを後述する。
- ハードウェア環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Catalina(10.15.5) |
| ハードウェア | MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) |
| プロセッサ | 2 GHz クアッドコアIntel Core i5 |
| メモリ | 32 GB 3733 MHz LPDDR4 |
| グラフィックス | Intel Iris Plus Graphics 1536 MB |

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| PHP バージョン | 7.4.3 | Homwbrewを用いて導入 |
| Laravel バージョン | 7.0.8 | commposerを用いてこちらの方法で導入→[Mac Laravelの環境構築を行う](https://qiita.com/miriwo/items/adaaaeecae69d6392e08) |
| MySQLバージョン | 8.0.19 for osx10.13 on x86_64 | Homwbrewを用いてこちらの方法で導入→[Mac HomebrewでMySQLをインストールする](https://qiita.com/miriwo/items/ef6a064bc545fbea29d9) |

## 前提条件

- 下記、または下記に準ずる方法でLaravelの環境構築がされていること。
    - [Mac Laravelの環境構築を行う](https://qiita.com/miriwo/items/adaaaeecae69d6392e08)

## 前提情報

- 本記事ではログの出力までの方法を最短で記載する、ログの機能の詳細の説明は実施しない。
- 本記事ではあえてエラーを発生させるべく.envファイルにDBの設定などを記載しない。

## 読後感

- dailyログをアプリ名ディレクトリ/storage/logs/直下のdaily-YYYY-MM-DD.logファイルに「[YYYY-MM-DD HH:MM:SS] local.DEBUG: test」と言う文字列で出力し、errorログをアプリ名ディレクトリ/storage/logs/直下のerror.logに「[YYYY-MM-DD HH:MM:SS] local.ERRORLOG: error test」と言う文字列で出力することができる。

## 概要

1. アプリ作成
1. ルーティングの記載
1. UserHomeController作成と記載
1. dailyログ出力確認
1. errorログ出力確認
1. ログの設定変更
1. 確認

## 詳細

1. アプリ作成
    1. アプリを作成する任意のディレクトリに移動して下記コマンドを実行して「test」と言う名前のアプリを作成する。(オプション`--auth`を付与してユーザ認証機能付きアプリを作成する。)

        ```terminal
        $ laravel new test --auth
        ```
1. ルーティングの記載
    1. testディレクトリで下記コマンドを実行してルーティングファイルを開く。

        ```terminal
        $ routes/web.php
        ```
    1. 開いたルーティングファイルに下記の一行を記載する。

        ```routes/web.php
        Route::get('/user_home', 'UserHomeController@index');
        ```
    1. 記載後のルーティングファイルの内容を下記に記載する。

        ```routes/web.php
        <?php
        
        use Illuminate\Support\Facades\Route;
        
        /*
        |--------------------------------------------------------------------------
        | Web Routes
        |--------------------------------------------------------------------------
        |
        | Here is where you can register web routes for your application. These
        | routes are loaded by the RouteServiceProvider within a group which
        | contains the "web" middleware group. Now create something great!
        |
        */
        
        Route::get('/', function () {
            return view('welcome');
        });
        
        Auth::routes();
        
        Route::get('/home', 'HomeController@index')->name('home');
        
        //下記を追記
        Route::get('/user_home', 'UserHomeController@index');
        ```
    1. 保存して閉じる。
1. UserHomeController作成と記載
    1. testディレクトリで下記コマンドを実行してUserHomeController.phpを作成する。

        ```terminal
        $ php artisan make:controller UserHomeController
        ```
    1. 下記コマンドを実行して先のコマンドで作成したUserHomeController.phpを開く。

        ```terminal
        $ vi app/Http/Controllers/UserHomeController.php
        ```
    1. 開いたUserHomeController.phpを下記の様に修正する。

        ```test/app/Http/Controllers/UserHomeController.php
        <?php
        
        namespace App\Http\Controllers;
        
        use Illuminate\Http\Request;
        //下記を追記する、下記の宣言がないとエラーになる
        use Illuminate\Support\Facades\Log;
        
        class UserHomeController extends Controller
        {
            //下記を追記する
            public function index()
            {
                //Log::debug('ログとして出力したい文字列')の様に記載する
                Log::debug('test');
                return redirect('/');
            }
            //上記までを追記する。
        }
        ```
    1. 保存して閉じる。
1. dailyログ出力確認
    1. testディレクトリで下記コマンドを実行してまだlogファイルが存在していないことを確認する。「No such file or directory」が出力されればsingle.logファイルとdaily.logは存在しない。

        ```terminal
        $ ls storage/logs/laravel.log
        >ls: storage/logs/laravel.log: No such file or directory
        ```
    1. testディレクトリで下記コマンドを実行してローカルサーバを起動する。

        ```terminal
        $ php artisan serve
        ```
    1. ブラウザからtestアプリにアクセスする。デフォルトだと[http://127.0.0.1:8000/](http://127.0.0.1:8000/)にアクセスするとブラウザでtestアプリが表示できる。
    1. 下記画面が表示されていることを確認する。

        <img width="1439" alt="Laravel.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/09257ca1-3b09-f7b8-f2c9-4a98f88556ec.png">


    1. [http://127.0.0.1:8000/user_home](http://127.0.0.1:8000/user_home)にアクセスしてみる。(アクセスしても何も起こらず、先の画像と同じLaravelのトップページが表示されると思うがその動作は期待する動作である。)
    1. testディレクトリで下記コマンドを実行してログファイルを開く。

        ```terminal
        $ less storage/logs/laravel.log
        ```
    1. 下記の一行が記載されていることを確認する。(YYYY-MM-DD HH:MM:SSはみなさんが[http://127.0.0.1:8000/user_home](http://127.0.0.1:8000/user_home)にアクセスした時間が入る。)

        ```test/storage/logs/laravel.log
        [YYYY-MM-DD HH:MM:SS] local.DEBUG: test 
        ```
1. errorログ出力確認
    1. 下記画面右上の「LOGIN」をクリックしログイン画面に進む。

        <img width="1439" alt="Laravel.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/61cce232-aff0-4808-8a9e-0d04bd02b914.png">

    1. なんでも良いのでE-Mail AddressとPasswordを入力して「Login」をクリックする。

        <img width="1436" alt="Laravel.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/af5c23f1-5832-78de-2da5-6d692a0b3ba5.png">

    1. 下記の様なエラーが出る(このエラー画面は期待する画面である。)

        <img width="1439" alt="🧨_SQLSTATE_HY000___1045__Access_denied_for_user__root___localhost___using_password__NO___SQL__select___from_&#x60;users&#x60;_where_&#x60;email&#x60;___shunokawa_gmail_com_limit_1_.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/bcbf970b-2b42-86ee-2593-308f6b436031.png">

    1. testディレクトリで下記コマンドを実行してログファイルを開く。

        ```terminal
        $ less storage/logs/laravel.log
        ```
    1. 下記の様な出力が記載されていることを確認する。

        ```log
        [2020-07-01 03:14:59] local.ERROR: SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: NO) (SQL: select * from `users` where `email` = shunokawa@gmail.com limit 1) {"exception":"[object] (Illuminate\\Database\\QueryException(code: 1045): SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: NO) (SQL: select * from `users` where `email` = shunokawa@gmail.com limit 1) at /Users/okawashun/test/vendor/laravel/framework/src/Illuminate/Database/Connection.php:671)
        [stacktrace]
        #0 /Users/okawashun/test/vendor/laravel/framework/src/Illuminate/Database/Connection.php(631): Illuminate\\Database\\Connection->runQueryCallback('select * from `...', Array, Object(Closure))
        #1 /Users/okawashun/test/vendor/laravel/framework/src/Illuminate/Database/Connection.php(339): Illuminate\\Database\\Connection->run('select * from `...', Array, Object(Closure))
        #2 /Users/okawashun/test/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php(2203): Illuminate\\Database\\Connection->select('select * from `...', Array, true)
                ・
                ・
                ・
        ```
1. ログの設定変更
    1. testディレクトリで下記コマンドを実行してログの設定ファイルを開く。

        ```terminal
        $ vi config/logging.php
        ```
    1. 開いた設定ファイルを下記の様に修正する。

        ```test/config/logging.php
        <?php
        
        use Monolog\Handler\NullHandler;
        use Monolog\Handler\StreamHandler;
        use Monolog\Handler\SyslogUdpHandler;
        
        return [
        
            /*
            |--------------------------------------------------------------------------
            | Default Log Channel
            |--------------------------------------------------------------------------
            |
            | This option defines the default log channel that gets used when writing
            | messages to the logs. The name specified in this option should match
            | one of the channels defined in the "channels" configuration array.
            |
            */
        
            'default' => env('LOG_CHANNEL', 'stack'),
        
            /*
            |--------------------------------------------------------------------------
            | Log Channels
            |--------------------------------------------------------------------------
            |
            | Here you may configure the log channels for your application. Out of
            | the box, Laravel uses the Monolog PHP logging library. This gives
            | you a variety of powerful log handlers / formatters to utilize.
            |
            | Available Drivers: "single", "daily", "slack", "syslog",
            |                    "errorlog", "monolog",
            |                    "custom", "stack"
            |
            */
        
            'channels' => [
                'stack' => [
                    'driver' => 'stack',
                    //下記修正・追記する
                    'channels' => [
                        'daily',
                        'errors',
                    ],
                    'ignore_exceptions' => false,
                ],
        
                'single' => [
                    'driver' => 'single',
                    'path' => storage_path('logs/laravel.log'),
                    'level' => 'debug',
                ],
        
                'daily' => [
                    'driver' => 'daily',
                    //下記を修正する
                    'path' => storage_path('logs/daily.log'),
                    'level' => 'debug',
                    'days' => 14,
                ],
        
                'slack' => [
                    'driver' => 'slack',
                    'url' => env('LOG_SLACK_WEBHOOK_URL'),
                    'username' => 'Laravel Log',
                    'emoji' => ':boom:',
                    'level' => 'critical',
                ],
        
                'papertrail' => [
                    'driver' => 'monolog',
                    'level' => 'debug',
                    'handler' => SyslogUdpHandler::class,
                    'handler_with' => [
                        'host' => env('PAPERTRAIL_URL'),
                        'port' => env('PAPERTRAIL_PORT'),
                    ],
                ],
        
                'stderr' => [
                    'driver' => 'monolog',
                    'handler' => StreamHandler::class,
                    'formatter' => env('LOG_STDERR_FORMATTER'),
                    'with' => [
                        'stream' => 'php://stderr',
                    ],
                ],
        
                'syslog' => [
                    'driver' => 'syslog',
                    'level' => 'debug',
                ],
        
                'errorlog' => [
                    'driver' => 'errorlog',
                    'level' => 'debug',
                ],
        
                'null' => [
                    'driver' => 'monolog',
                    'handler' => NullHandler::class,
                ],
        
                'emergency' => [
                    'path' => storage_path('logs/laravel.log'),
                ],

                //下記を追記
                'errors' => [
                    'driver' => 'daily',
                    'path' => storage_path('logs/error.log'),
                    'level' => 'error',
                    'days' => 14,
                ],
                //上記までを追記
            ],
        
        ];
        ```
1. 確認
    1. testディレクトリで下記コマンドを実行してまだlogファイルが存在していないことを確認する。「No such file or directory」が出力されればsingle.logファイルとdaily.logは存在しない。

        ```terminal
        $ ls storage/logs/daily*
        >ls: storage/logs/daily*: No such file or directory
        $ ls storage/logs/error*
        >ls: storage/logs/error*: No such file or directory
        ```
    1. testディレクトリで下記コマンドを実行してローカルサーバを起動する。

        ```terminal
        $ php artisan serve
        ```
    1. ブラウザからtestアプリにアクセスする。デフォルトだと[http://127.0.0.1:8000/](http://127.0.0.1:8000/)にアクセスするとブラウザでtestアプリが表示できる。
    1. 下記画面が表示されていることを確認する。

        <img width="1438" alt="Laravel.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/876e5cdd-ddee-27fe-2993-e56b6496bf5f.png">

    1. [http://127.0.0.1:8000/user_home](http://127.0.0.1:8000/user_home)にアクセスしてみる。(アクセスしても何も起こらず、先の画像と同じLaravelのトップページが表示されると思うがその動作は期待する動作である。)
    1. 二つのファイルに下記の一行が記載されていることを確認する。(YYYY-MM-DD HH:MM:SSはみなさんが[http://127.0.0.1:8000/user_home](http://127.0.0.1:8000/user_home)にアクセスした時間が入る。)

        ```test/storage/logs/laravel.log
        [YYYY-MM-DD HH:MM:SS] local.DEBUG: test 
        ```
    1. 下記画面右上の「LOGIN」をクリックしログイン画面に進む。

        <img width="1439" alt="Laravel.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/61cce232-aff0-4808-8a9e-0d04bd02b914.png">

    1. なんでも良いのでE-Mail AddressとPasswordを入力して「Login」をクリックする。

        <img width="1436" alt="Laravel.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/af5c23f1-5832-78de-2da5-6d692a0b3ba5.png">

    1. 下記の様なエラーが出る(このエラー画面は期待する画面である。)

        <img width="1439" alt="🧨_SQLSTATE_HY000___1045__Access_denied_for_user__root___localhost___using_password__NO___SQL__select___from_&#x60;users&#x60;_where_&#x60;email&#x60;___shunokawa_gmail_com_limit_1_.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/bcbf970b-2b42-86ee-2593-308f6b436031.png">

    1. testディレクトリで下記コマンドを実行してログファイルを開く。

        ```terminal
        $ less storage/logs/error.log
        ```
    1. 下記の様な出力が記載されていることを確認する。

        ```log
        [2020-07-01 03:14:59] local.ERROR: SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: NO) (SQL: select * from `users` where `email` = shunokawa@gmail.com limit 1) {"exception":"[object] (Illuminate\\Database\\QueryException(code: 1045): SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: NO) (SQL: select * from `users` where `email` = shunokawa@gmail.com limit 1) at /Users/okawashun/test/vendor/laravel/framework/src/Illuminate/Database/Connection.php:671)
        [stacktrace]
        #0 /Users/okawashun/test/vendor/laravel/framework/src/Illuminate/Database/Connection.php(631): Illuminate\\Database\\Connection->runQueryCallback('select * from `...', Array, Object(Closure))
        #1 /Users/okawashun/test/vendor/laravel/framework/src/Illuminate/Database/Connection.php(339): Illuminate\\Database\\Connection->run('select * from `...', Array, Object(Closure))
        #2 /Users/okawashun/test/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php(2203): Illuminate\\Database\\Connection->select('select * from `...', Array, true)
                ・
                ・
                ・
        ```
    1. 正常に書き込まれていた場合作業完了となる。

## 参考文献

- [Laravelのログ出力をエラーログのみ出し分ける](https://qiita.com/K-Shuuun/items/37b7cc9a95030fe79494)