Laravel5.6以降のログの機能をちょっと調べた

# 目的

- 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のログ出力方法はMonologと言う名前のライブラリを使用している。
- 本記事より公式ドキュメントの方がわかりやすいかもしれない。ログについて詳しく書いてあるLaravel5.6のドキュメントのリンクを下記に記載する。
     - [Laravel 5.6 ログ](https://readouble.com/laravel/5.6/ja/logging.html)

# ログチャンネル

- ログの出力にはチャンネルと言う機能を使用する。
- チャンネルは複数存在する。
- チャンネル = ログ出力の方法と考えていただいても差し支えないと思う。
- 下記にログチャンネルの種類を記載する。

    | チャンネル | 説明 |
    |:--|:--|
    | stack | チャンネルをまとめるためのチャンネル |
    | single | シングルチャンネル、一つのファイルにずっとログを書き込む。デフォルトの設定はこれ |
    | daily | デイリーチャンネル一日毎にファイルを分けてログを出力してくれる。デフォルトだと14日間ログファイルを保持する。 |
    | slack | slackチャンネル、社内のコミュニケーションツールであるslackにログを送信するためのチャンネル |
    | syslog | システムログチャンネル、アプリのシステムログを出力するためのチャンネル |
    | errorlog | エラーログチャンネル、エラーメッセージを出力するためのチャンネル |
    | monolog | そのほかのライブラリで定義されているログを出力するためのチャンネル |
    | custom | カスタムチャンネル、開発者が任意のチャンネルを作成するためのチャンネル |

- 公式ドキュメントのログチャンネルの表を下記に記載する。

    <img width="843" alt="ログ_5_6_Laravel.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/f821de62-8e9e-94e6-7582-c219dfc9647f.png">

# ログレベル

- laravelのログにはレベルが存在する。
- 出力の優先度によってレベル分けされている。
- 8個のレベルが存在し、最も重要性の高いログのレベル名はemergencyで開発段階の情報など重要度の低いログを出力するレベルはdebugとなる
- ログのレベルはチャンネル毎に設定可能である。ログ出力の指令を行うコードでも、出力したいログのレベルを指定することができる。
- ログレベルの種類を下記に記載する。上位に行けば行くほど危険度が高いログレベルとして設計することが一般的である。

    | ログレベル |
    | --- |
    | emergency |
    | alert |
    | critical |
    | error |
    | warning |
    | notice |
    | info |
    | debug |

- ログレベルは下記の規約で決められたものを使用している。
    - [RFC 5424規約](https://tools.ietf.org/html/rfc5424)

        <img width="751" alt="RFC_5424_-_The_Syslog_Protocol.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/6786e238-ba09-ddbf-2c3e-c0eb7ba0c8a8.png">

- ログレベルはアプリ開発段階でのログに出力したい情報とデプロイしてユーザが使用している段階でのログに出力したい情報を分けるために存在する。
- 後述するログの設定ファイルでdebugを選択していれば全てのログレベルのログがログファイルに記載される。

# ログの設定ファイル

- laravel5.6からログの設定ファイルの場所が変更になった。
- `アプリ名ディレクトリ/config/`直下のlogging.phpファイルがログの設定ファイルである。
- 下記にloggingファイルの内容を記載する。

    ```アプリ名ディレクトリ/config/loggign.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' => ['single'],
                'ignore_exceptions' => false,
            ],
    
            'single' => [
                'driver' => 'single',
                'path' => storage_path('logs/laravel.log'),
                'level' => 'debug',
            ],
    
            'daily' => [
                'driver' => 'daily',
                'path' => storage_path('logs/laravel.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'),
            ],
        ],
    
    ];
    ```

# ログチャンネルの指定

- どのログチャンネルを指定してログを出力するのかの設定は`アプリ名ディレクトリ/`直下にある.envファイルに記載する。
- .envの下記の部分でログチャンネルの設定を行っている。

    ```アプリ名ディレクトリ/.env
    LOG_CHANNEL=stack
    ```
- 上記の様に記載されていると、stackチャンネル(チャンネルをまとめるためのチャンネル)が選択されていることになる。
- dailyチャンネルでログを出力したい場合は下記の様に.envファイルに記載する。

    ```アプリ名ディレクトリ/.env
    LOG_CHANNEL=daily
    ``` 
- 複数のログを出力するための方法は下記の記事にまとめてみた。(stackチャンネルに出力したいログチャンネルを配列状に追加することがセオリーの様である。) 
    - [Laravel Log singleログとdailyログを同時に出力する](https://qiita.com/miriwo/items/188653fce78a264db84d)
    - [Laravel Log dailyログとerrorログを別々に出力する]()

# ログの初期設定の状態

- `$ laravel new アプリ名`を実行した直後の何もいじっていない状態のログの設定がどうなっているのか確認してみる。

1. アプリの設定ファイルである.envファイルのログチャンネルの設定の確認
    - 下記に.envファイルのログチャンネルの記載部分のみ抜粋して記載する。

        ```アプリ名ディレクトリ/.env
        LOG_CHANNEL=stack
        ```
    - ログチャンネルはstackが選択されている。

1. ログの設定ファイルlogging.phpの記載の確認
    - 下記にlogging.phpファイルの内容を記載する。

        ```アプリ名ディレクトリ/config/loggign.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' => ['single'],
                    'ignore_exceptions' => false,
                ],
        
                'single' => [
                    'driver' => 'single',
                    'path' => storage_path('logs/laravel.log'),
                    'level' => 'debug',
                ],
        
                'daily' => [
                    'driver' => 'daily',
                    'path' => storage_path('logs/laravel.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'),
                ],
            ],
        
        ];
        ```
    - コード`'default' => env('LOG_CHANNEL', 'stack'),`では.envファイルにてログチャンネルの設定が行われなかった場合に指定されるデフォルトのログチャンネルが記載されている。デフォルトではログチャンネルの設定が.envファイルにて行われなかった場合、stackチャンネルを指定する様に記載されている。本記載は基本的に変更しない。
    - 配列状に格納されているログチャンネルの情報について説明する。下記に.envファイルで指定されているstackチャンネルの記載部分のみ抜粋したコードを記載する。

        ```アプリ名ディレクトリ/config/loggign.php
        'stack' => [
            'driver' => 'stack',  //ライブラリの実行ドライバを指定している(チャンネル名を指定していると考えていただきたい)
            'channels' => ['single'],  //まとめて実行するログチャンネルを配列状に指定している デフォルトだとsingleチャンネルのみが指定されている。
            'ignore_exceptions' => false,  //本記載の意味を現在調査中です。
        ],
        ```

# ログチャンネルを変更するには？

- デフォルトのログチャンネルから変更する方法は主に二通りあると考える。下記に二通りの方法を記載する。
    - .envファイルにて`LOG_CHANNEL=`の記載を設定したいログチャンネルに変更する。
    - .envファイルの`LOG_CHANNEL=`の記載は弄らずに「stack」チャンネルを選択し、`アプリ名ディレクトリ/config/loggign.php`の「stack」チャンネルの設定部分`'channels' =>`にて出力チャンネルを変更する。
- 単一のログのみを出力するなら.envにてログチャンネルを設定するだけで良いが、「single」チャンネルと「daily」チャンネル両方のログが欲しい時は`アプリ名ディレクトリ/config/loggign.php`の「stack」チャンネルの設定部分で指定する必要がある。下記に筆者が以前まとめた二種類のログを出力する方法の記事のリンクを記載する。
    - [Laravel Log singleログとdailyログを同時に出力する](https://qiita.com/miriwo/items/188653fce78a264db84d)

# 参考文献

- [PHPのロガーMonologを理解しよう](https://tech.quartetcom.co.jp/2018/05/31/monolog/)
- [Laravel 5.6 ログ](https://readouble.com/laravel/5.6/ja/logging.html)