こんにちは。今回は表題通り、Laravel5.8でのログの扱い方です。
わざわざバージョンを記載しているのは、2019年7月現在のLTSである5.5と5.6以降で大きな変更があったためです。本記事の内容は5.5以前には適用できない可能性がありますので、ご注意ください。
Laravelのログ機能はMonologのラッパーであり、これは5.8になっても同じです。変わったのはログの呼び出し方や設定方法のようです(私は5.8からLaravelを使い始めたので、5.5以前の書き方は把握していません…)。
なおMonolog自体はLaravelとは本来関係ないパッケージのため、Laravel公式のドキュメントよりはMonolog単体で調べた方が、まとまった情報を得ることができると思います。
では早速Laravelでの使い方を見ていきます。簡単かつMonologに不慣れな人でもパッと見で分かりやすいのは、コード上で全て設定してしまう方法です。
以下は「ユーザー登録時にLaravel標準とは別にログを出力したい」という意図のコードです。
use Monolog\Formatter\LineFormatter; use Monolog\Handler\RotatingFileHandler; use Monolog\Logger; protected function create(array $data) { $user = User::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => Hash::make($data['password']), ]); $log_path = storage_path('logs/user-register.log'); $days = 90; $log_level = 'debug'; $bubble = true; $filePermission = 0777; $handler = new RotatingFileHandler($log_path, $days, $log_level, $bubble, $filePermission); $formatter = new LineFormatter(null, null, true, true); $handler->setFormatter($formatter); $logger = new Logger('user-register'); $logger->pushHandler($handler); $logger->info(sprintf('ユーザーID:%sが登録されました。', $user->id)); return $user; }
storage_path()
を使ってstorage/logs
以下を指定するのが慣例です。chmod
と同じように指定できます。StreamHandler
、Slackに手軽にPOSTできるSlackHandler
など、様々なハンドラがあり、実体はvendor/monolog/monolog/src/Monolog/Handler
以下にあります。const SIMPLE_FORMAT = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n";
というフォーマットに沿って出力されます。ControllerやServiceに書いてしまうのはあまりスマートではなく、コードの肥大化も招きます。trait化したり、設定値を.env
やconfig
に追い出すことで可読性を保てるのではないでしょうか。
上記のコードでstorage/logs/user-register-[YYYY-MM-DD].log
が生成され、以下のようなログが出力されます。storage/logs/laravel-[YYYY-MM-DD].log
はLaravelデフォルトのログで、config/logging.php
の設定に沿って出力されます(後述)。
5.6以降で追加された設定ファイルで、公式ドキュメントを見る限り、恐らくこちらが推奨の方法だと思います。
'default' => env('LOG_CHANNEL', 'stack'), (中略) 'channels' => [ 'stack' => [ 'driver' => 'stack', 'channels' => ['daily'], '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, ], (中略) 'user-register' => [ 'driver' => 'daily', 'level' => 'debug', 'path' => storage_path('logs/user-register.log'), 'days' => 90, ], ],
stack, single, dailyはデフォルトの設定項目で、user-register
が追記した項目です。
new Logger()
した時の引数に相当します。Monologでは複数のchannelを登録し、一度に複数の出力先にログを吐き出すことが可能です(このへんがまだ理解が浅く、正しい解釈なのか不安です…)。一番上のstack
だけは少し特殊で、複数のchannelを記述して一括登録することが可能です(channelsが配列になっているのはそのためのようです)。$log_level
に相当します。$log_path
に相当します。$days
に相当します。アプリケーションでは以下のように記述することで、最初のコードと同様にstorage/logs/user-register-[YYYY-MM-DD].log
にログが出力されます。コード量が目に見えて減りました!複雑な仕様でなければ、設定ファイルのへ記述で済ませてしまうのがベターだと思います。
use Illuminate\Support\Facades\Log; protected function create(array $data) { $user = User::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => Hash::make($data['password']), ]); Log::setDefaultDriver('user-register'); Log::info(sprintf('ユーザーID:%sが登録されました。', $user->id)); return $user; }
上述のPSR-3で定義されているログレベルはあくまでも目安です。今回の例では「正常にユーザー登録が完了した」ときのログですのでやerrorやwarningではおかしいですが、noticeなのか、infoなのかは要件次第になるでしょう。
以下のページでログレベル一覧および一例が完結にまとまっていましたので、紹介いたします。
「ログの出し分けをしたい」という要件から始まって、Laravelのログ出力について調査したのですが、一度理解してしまえば実に簡単です。豊富な出力先を選べるのもいいですね。