【Laravel】管理画面と一般サイトでログファイルを分けてみる

一般ユーザがアクセスする画面と、管理者がアクセスする画面があるサイトの場合、一つのログに出力していると、両方のログが混在して「これはどっちの処理のログ？」みたいになって分かりづらい。

- 一般ユーザは、一般ユーザ用のログファイルに出力
- 管理者は、管理者用のログファイルに出力

という風に完全に分けられれば見やすくなるはず。

さっそく分けてみた。

# 環境
- laravel 5.8

# 前提

## 一般ユーザ用の画面

「https&#58;//example.com/admin」配下以外は全部、一般ユーザ用

## 管理画面

逆に「https&#58;//example.com/admin」配下は全部、管理画面

# 作ってみた

Larvael5.6からログの設定方法・出力方法が大きく変わった様で、今回は5.8で試しています。（検証はしてないけど、たぶん5.6〜5.7でも動くのではないかと。）

## ざっくりとした手順

1. 一般ユーザ用と管理者用のログチャネルを作成
2. ログ出力用の自作ファサードを作成し、そこでログチャネルを指定する
3. 自作ファサードの登録

## 一般ユーザ用と管理者用のログチャネルを作成

ログ設定用のコンフィグファイルに設定を追加します。
`admin`チャネルと`user`チャネルを追加し、それぞれ出力先ファイルを指定する。

```/config/logging.php
    'channels' => [
        /**
         * 
         * 元々書いてある設定は省略
         * 
         */
        
        
        //以降を追加
        'admin' => [
            'driver' => 'daily',
            'path' => storage_path('logs/laravel_admin.log'),
            'level' => env('LOGGING_LEVEL', 'info'),
            'days' => env('LOG_ROTATE_DAYS', 14),
        ],

        'user' => [
            'driver' => 'daily',
            'path' => storage_path('logs/laravel_user.log'),
            'level' => env('LOGGING_LEVEL', 'info'),
            'days' => env('LOG_ROTATE_DAYS', 14),
        ],
    ],
```

## ログ出力用の自作ファサードを作成し、そこでログチャネルを指定する

### ファサードクラス

公式の手順通りに作成

```/app/Facades/CustomLogFacade.php
<?php

namespace App\Facades;


use App\Services\Support\CustomLogSupport;
use Illuminate\Support\Facades\Facade;

class CustomLogFacade extends Facade
{

    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return CustomLogSupport::class;
    }
}
```

### ロジッククラス

ファサードの本体を作成します。

```/app/Service/Support/CustomLogSupport.php
<?php

namespace App\Services\Support;

use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Str;

class CustomLogSupport
{
    public function __call($name, $args)
    {
        $chanel = 'stack';
        try{
            $domain = config('app.url');
            $url = Request::url();
            if(Str::is($domain.'/admin/*', $url)){
                $chanel = 'admin';
            }else if(Str::is($domain.'/*', $url)){
                $chanel = 'user';
            }else{
                $chanel = 'batch';
            }
        }catch (\Exception $e){
            //握りつぶす
        }

        $collectArgs = collect($args);
        Log::channel($chanel)->{$name}($collectArgs->shift(), $collectArgs->toArray());
    }
}
```

マジックメソッドの`__call()`を使って、`Log`ファサードをラップしてます。
その際に`channel($chanel)`で使用するチャネルを指定しています。

このチャネル振り分けロジックを変えればサブドメイン毎にログを分ける事もできそうです。


## 自作ファサードの登録

これもお決まり通りに登録します。

### サービスコンテナに登録
 
```/app/Providers/AppServiceProvider.php
    public function register()
    {
        //ログ出力
        $this->app->singleton(CustomLogSupport::class, CustomLogSupport::class);
    }
```

### ファサードの登録

```/app/config/app.php
    'aliases' => [
        /**
         * 
         * 元々書いてある設定は省略
         * 
         */
        

        'CustomLog' =>  \App\Facades\CustomLogFacade::class,
    ],

```

# 結果
```
$ ls
laravel_admin-2019-10-09.log    laravel_user-2019-10-09.log
```
分割して出力された！

ちなみにファサードの実態クラス（今回でいうと`CustomLogSupport`）ってどういうクラス名で、どういうディレクトリに格納するのが一般的なんですかね？