ログ
アプリの動きを記録するログの設定と書き方を説明します。チャンネルとドライバの一覧・スタック・ログレベル・Monolog の変更・Pail でログを見る方法まで引けます。
ログは、アプリの中で何が起きているかを残しておく「記録」です。動きがおかしいとき、あとから記録を読んで、原因を探せます。航空機の「飛行記録」のようなものです。
Laravel には、ログを書くためのしっかりしたしくみがあります。ファイルやシステムのエラーログに書いたり、Slack(仕事で使うチャットサービス)に送ってチーム全員に知らせたりできます。
Laravel のログは「チャンネル」が土台です。1つのチャンネルは、ログを書く方法を1つ表します。たとえば、single チャンネルは、1つのログファイルに書き、slack チャンネルは、ログのメッセージを Slack へ送ります。メッセージは、重さ(重大さ)に応じて、複数のチャンネルに書くこともできます。
中では、Monolog というライブラリ(PHP の部品)を使っています。Monolog には、ログを扱う係(ハンドラ)がたくさんそろっています。Laravel では、そのハンドラを簡単に設定でき、組み合わせて、アプリに合ったログのしくみを作れます。
設定#
アプリのログの動きを決める設定は、すべて config/logging.php に入っています。このファイルで、アプリのログのチャンネルを設定します。使えるチャンネルと、そのオプションを、一度見ておくとよいでしょう。よく使うオプションを、下で見ていきます。
ふつう、Laravel は、メッセージを記録するときに、stack チャンネルを使います。stack チャンネルは、複数のログチャンネルを、1つにまとめます。スタックの作り方は、下の「ログのスタックを作る」で説明します。
使えるチャンネルドライバ#
ログのチャンネルは、それぞれ「ドライバ」で動きます。ドライバが、ログのメッセージを、どのように、どこへ記録するかを決めます。次のドライバは、どの Laravel アプリでも使えます。多くのドライバは、すでにアプリの config/logging.php に項目があるので、中を見て確かめておくとよいでしょう。
| 名前 | 説明 |
|---|---|
custom |
決めた「ファクトリ」(作る係)を呼んで、チャンネルを作るドライバ |
daily |
RotatingFileHandler を使う Monolog のドライバ。毎日ファイルを替える |
monthly |
RotatingFileHandler を使う Monolog のドライバ。毎月ファイルを替える |
errorlog |
ErrorLogHandler を使う Monolog のドライバ |
monolog |
Monolog のハンドラなら何でも使える、ファクトリのドライバ |
single |
1つのファイル(かパス)に書くチャンネル(StreamHandler) |
slack |
SlackWebhookHandler を使う Monolog のドライバ |
stack |
「複数のチャンネルを持つ」チャンネルを作りやすくするまとめ役 |
syslog |
SyslogHandler を使う Monolog のドライバ |
補足
monolog と custom のドライバのくわしいことは、下の「Monolog のチャンネルを作り変える」で説明します。
チャンネルの名前を決める#
ふつう、Monolog は、いまの環境(production や local など)と同じ「チャンネルの名前」で作られます。この名前を変えるには、チャンネルの設定に name オプションを足します。
'stack' => [
'driver' => 'stack',
'name' => 'channel-name',
'channels' => ['single', 'slack'],
],
チャンネルごとに必要な設定#
single・daily・monthly チャンネルの設定#
single・daily・monthly のチャンネルには、省略できる設定のオプションが3つあります。bubble・permission・locking です。
| 名前 | 説明 | 初期値 |
|---|---|---|
bubble |
処理したあと、メッセージをほかのチャンネルへも回すか | true |
locking |
ログファイルに書く前に、鍵をかけようとするか | false |
permission |
ログファイルのパーミッション(使ってよい人の決まり) | 0644 |
さらに、daily と monthly のチャンネルでは、古いログをどこまで残しておくか(保存の決まり)を、max_files の設定で決められます。daily では、LOG_DAILY_DAYS の環境変数(環境ごとに変える設定値)でも決められます。
Papertrail チャンネルの設定#
papertrail チャンネルには、host と port のオプションが必要です。PAPERTRAIL_URL と PAPERTRAIL_PORT の環境変数で決められます。値は、Papertrail から取れます。
Slack チャンネルの設定#
slack チャンネルには、url オプションが必要です。この値は、LOG_SLACK_WEBHOOK_URL の環境変数で決められます。Slack のチームに設定した、Incoming Webhook(外からメッセージを送り込む窓口)の URL に合わせます。
ふつう、Slack には、critical レベル以上のログだけが届きます。これは、LOG_LEVEL の環境変数か、Slack のログチャンネルの設定の配列にある level オプションで変えられます。
非推奨の警告を記録する#
PHP や Laravel、ほかのライブラリは、使っている機能が「非推奨」(deprecated。今後のバージョンで、なくなる予定の機能)になったと、よく知らせてきます。この警告を記録したいときは、LOG_DEPRECATIONS_CHANNEL の環境変数か、アプリの config/logging.php で、deprecations のログチャンネルを決めます。
'deprecations' => [
'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
'trace' => env('LOG_DEPRECATIONS_TRACE', false),
],
'channels' => [
// ...
]
または、deprecations という名前のログチャンネルを作ります。この名前のチャンネルがあれば、非推奨の警告の記録には、必ずそれが使われます。
'channels' => [
'deprecations' => [
'driver' => 'single',
'path' => storage_path('logs/php-deprecation-warnings.log'),
],
],
ログのスタックを作る#
前に書いたとおり、stack ドライバを使うと、複数のチャンネルを、1つのログチャンネルにまとめられます。本番のアプリでありそうな設定の例で、使い方を見てみます。
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['syslog', 'slack'],
'ignore_exceptions' => false,
],
'syslog' => [
'driver' => 'syslog',
'level' => env('LOG_LEVEL', 'debug'),
'facility' => env('LOG_SYSLOG_FACILITY', LOG_USER),
'replace_placeholders' => true,
],
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => env('LOG_SLACK_USERNAME', 'Laravel Log'),
'emoji' => env('LOG_SLACK_EMOJI', ':boom:'),
'level' => env('LOG_LEVEL', 'critical'),
'replace_placeholders' => true,
],
],
この設定を順に見ていきます。まず、stack チャンネルは、channels オプションで、syslog と slack の2つのチャンネルをまとめています。そのため、メッセージを記録するとき、この2つのチャンネルのどちらにも、記録するチャンスがあります。ただ、あとで見るように、本当に記録するかどうかは、メッセージの重さ(「レベル」)で決まることがあります。
ログレベル#
上の例の、syslog と slack のチャンネルの設定にある、level オプションを見てください。このオプションは、そのチャンネルが記録するメッセージの、いちばん低い「レベル」を決めます。これより低いレベルのメッセージは、そのチャンネルには記録されません。Laravel のログのしくみを動かす Monolog は、RFC 5424(ログの決まりを書いた文書)で決められたログレベルを、すべて使えます。重い順に、次の8つです。
| レベル | 説明 |
|---|---|
emergency |
緊急。システムが使えない |
alert |
すぐ対応が必要 |
critical |
重大な問題 |
error |
エラー |
warning |
警告 |
notice |
気をつけておくこと |
info |
ふつうの情報 |
debug |
調べるための細かい情報 |
たとえば、debug メソッドでメッセージを記録するとします。
Log::debug('An informational message.');
この設定では、syslog チャンネルは、メッセージをシステムのログに書きます。でも、このメッセージは critical 以上ではないので、Slack へは送られません。一方、emergency のメッセージは、どちらのチャンネルの最低のレベルよりも重いので、システムのログにも Slack にも送られます。
Log::emergency('The system is down!');
ログのメッセージを書く#
ログは、Log のファサード(クラス名と :: で呼べる窓口)で書きます。前に書いたとおり、ロガー(ログを書く係)は、RFC 5424 で決められた、8つのログレベルを持っています。emergency・alert・critical・error・warning・notice・info・debug です。
use Illuminate\Support\Facades\Log;
Log::emergency($message);
Log::alert($message);
Log::critical($message);
Log::error($message);
Log::warning($message);
Log::notice($message);
Log::info($message);
Log::debug($message);
どのメソッドを呼んでも、そのレベルでメッセージを記録できます。ふつう、メッセージは、logging の設定ファイルで決めた、初期のログチャンネルに書かれます。
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;
class UserController extends Controller
{
/**
* Show the profile for the given user.
*/
public function show(string $id): View
{
Log::info('Showing the user profile for user: {id}', ['id' => $id]);
return view('user.profile', [
'user' => User::findOrFail($id)
]);
}
}
付け足しの情報(コンテキスト)#
ログのメソッドには、付け足しの情報(コンテキスト)の配列を渡せます。この情報は、整えられて、ログのメッセージといっしょに表示されます。
use Illuminate\Support\Facades\Log;
Log::info('User {id} failed to login.', ['id' => $user->id]);
あるチャンネルの、このあとのログすべてに、同じ付け足しの情報を入れたいことがあります。たとえば、アプリに届くリクエストごとに付く、リクエスト ID を記録したいときです。Log ファサードの withContext メソッドを呼びます。
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Response;
class AssignRequestId
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
$requestId = (string) Str::uuid();
Log::withContext([
'request-id' => $requestId
]);
$response = $next($request);
$response->headers->set('Request-Id', $requestId);
return $response;
}
}
付け足しの情報を、「すべての」ログチャンネルで共有したいときは、Log::shareContext() メソッドを呼びます。このメソッドは、すでに作られたすべてのチャンネルと、このあと作られるチャンネルに、付け足しの情報を渡します。
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Response;
class AssignRequestId
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
$requestId = (string) Str::uuid();
Log::shareContext([
'request-id' => $requestId
]);
// ...
}
}
補足
キュー(時間のかかる仕事の順番待ちの列)に入れた仕事(ジョブ)を処理している間も、ログの付け足しの情報を共有したいときは、ジョブのミドルウェアが使えます。くわしくはキューを見てください。
決めたチャンネルに書く#
アプリの初期のチャンネルではなく、別のチャンネルに記録したいことがあります。Log ファサードの channel メソッドを使うと、設定ファイルで決めたチャンネルを取り出して、記録できます。
use Illuminate\Support\Facades\Log;
Log::channel('slack')->info('Something happened!');
複数のチャンネルをまとめた、その場限りのログのスタックを作りたいなら、stack メソッドを使います。
Log::stack(['single', 'slack'])->info('Something happened!');
その場で作るチャンネル#
アプリの logging の設定ファイルになくても、動かす時点で設定を渡して、その場限りのチャンネルを作ることもできます。Log ファサードの build メソッドに、設定の配列を渡します。
use Illuminate\Support\Facades\Log;
Log::build([
'driver' => 'single',
'path' => storage_path('logs/custom.log'),
])->info('Something happened!');
その場で作ったチャンネルを、その場で作るログのスタックに入れたいこともあります。stack メソッドに渡す配列に、そのチャンネルのオブジェクトを入れればできます。
use Illuminate\Support\Facades\Log;
$channel = Log::build([
'driver' => 'single',
'path' => storage_path('logs/custom.log'),
]);
Log::stack(['slack', $channel])->info('Something happened!');
| メソッド | 説明 |
|---|---|
Log::emergency など8つのレベル |
そのレベルでメッセージを書く |
Log::withContext |
あるチャンネルの、このあとのログに、付け足しの情報を入れる |
Log::shareContext |
すべてのチャンネルに、付け足しの情報を共有する |
Log::channel |
決めたチャンネルを取り出して書く |
Log::stack |
その場で、複数のチャンネルをまとめて書く |
Log::build |
設定の配列から、その場でチャンネルを作る |
Monolog のチャンネルを作り変える#
チャンネルの Monolog を変える#
すでにあるチャンネルに、Monolog をどう設定するかを、細かく決めたいことがあります。たとえば、Laravel に最初からある single チャンネルに、自分で作った Monolog の FormatterInterface(ログの書式を決める部品)を使いたいときです。
まず、チャンネルの設定に、tap の配列を書きます。tap の配列には、クラスの一覧を入れます。これらのクラスは、Monolog のオブジェクトが作られたあとに、それを作り変える(「tap」する)ことができます。これらのクラスを置く、決まった場所はありません。アプリの中に、好きなフォルダを作って置けます。
'single' => [
'driver' => 'single',
'tap' => [App\Logging\CustomizeFormatter::class],
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'debug'),
'replace_placeholders' => true,
],
チャンネルに tap を決めたら、Monolog のオブジェクトを作り変えるクラスを書きます。このクラスに必要なメソッドは、__invoke の1つだけです。__invoke は、Illuminate\Log\Logger のオブジェクトを受け取ります。Illuminate\Log\Logger は、メソッドの呼び出しを、中の Monolog のオブジェクトに、そのまま渡します。
<?php
namespace App\Logging;
use Illuminate\Log\Logger;
use Monolog\Formatter\LineFormatter;
class CustomizeFormatter
{
/**
* Customize the given logger instance.
*/
public function __invoke(Logger $logger): void
{
foreach ($logger->getHandlers() as $handler) {
$handler->setFormatter(new LineFormatter(
'[%datetime%] %channel%.%level_name%: %message% %context% %extra%'
));
}
}
}
補足
「tap」のクラスは、すべてサービスコンテナ(クラスを作って渡してくれる道具箱)から作られます。そのため、コンストラクタ(クラスを作るときに動く部分)に必要な部品は、自動で渡されます。
Monolog のハンドラのチャンネルを作る#
Monolog には、たくさんのハンドラがあります。でも、Laravel は、そのすべてにチャンネルを用意しているわけではありません。そこで、Laravel にドライバがない Monolog のハンドラを、そのまま使うだけのチャンネルを作りたいこともあります。そうしたチャンネルは、monolog ドライバで簡単に作れます。
monolog ドライバを使うときは、handler オプションで、どのハンドラを使うかを決めます。ハンドラに必要な、コンストラクタの引数があれば、handler_with オプションで決められます(省略できます)。
'logentries' => [
'driver' => 'monolog',
'handler' => Monolog\Handler\SyslogUdpHandler::class,
'handler_with' => [
'host' => 'my.logentries.internal.datahubhost.company.com',
'port' => '10000',
],
],
Monolog のフォーマッタ#
monolog ドライバを使うと、ふつう、Monolog の LineFormatter が、書式を決める部品(フォーマッタ)として使われます。formatter と formatter_with のオプションで、ハンドラに渡すフォーマッタを変えられます。
'browser' => [
'driver' => 'monolog',
'handler' => Monolog\Handler\BrowserConsoleHandler::class,
'formatter' => Monolog\Formatter\HtmlFormatter::class,
'formatter_with' => [
'dateFormat' => 'Y-m-d',
],
],
自分のフォーマッタを持てる Monolog のハンドラを使うなら、formatter オプションの値を default にできます。
'newrelic' => [
'driver' => 'monolog',
'handler' => Monolog\Handler\NewRelicHandler::class,
'formatter' => 'default',
],
Monolog のプロセッサ#
Monolog は、メッセージを記録する前に、加工することもできます。自分でプロセッサ(加工する係)を作るか、Monolog が用意しているプロセッサを使えます。
monolog ドライバのプロセッサを変えたいときは、チャンネルの設定に processors の値を足します。
'memory' => [
'driver' => 'monolog',
'handler' => Monolog\Handler\StreamHandler::class,
'handler_with' => [
'stream' => 'php://stderr',
],
'processors' => [
// 簡単な書き方
Monolog\Processor\MemoryUsageProcessor::class,
// オプションを付ける書き方
[
'processor' => Monolog\Processor\PsrLogMessageProcessor::class,
'with' => ['removeUsedContextFields' => true],
],
],
],
ファクトリで自分のチャンネルを作る#
Monolog の作り方も設定も、すべて自分で決めたチャンネルを作りたいなら、config/logging.php のチャンネルの設定で、ドライバを custom にします。設定には via オプションを入れ、Monolog のオブジェクトを作るファクトリ(作る係)のクラスの名前を書きます。
'channels' => [
'example-custom-channel' => [
'driver' => 'custom',
'via' => App\Logging\CreateCustomLogger::class,
],
],
custom ドライバのチャンネルを設定したら、Monolog のオブジェクトを作るクラスを書きます。このクラスに必要なのは __invoke メソッドだけです。このメソッドは、チャンネルの設定の配列を1つだけ引数に受け取り、Monolog のロガー(ログを書く係)のオブジェクトを返します。
<?php
namespace App\Logging;
use Monolog\Logger;
class CreateCustomLogger
{
/**
* Create a custom Monolog instance.
*/
public function __invoke(array $config): Logger
{
return new Logger(/* ... */);
}
}
Pail でログを流し読みする#
アプリのログを、リアルタイムで流し読み(tail)したいことがよくあります。たとえば、問題を調べているときや、ある種類のエラーを見張っているときです。
Laravel Pail は、Laravel アプリのログファイルを、コマンドライン(ターミナルで文字を打って操作する画面)から簡単に見られるパッケージ(部品)です。ふつうの tail コマンドとちがい、Pail はどのログドライバでも使えます。Laravel Nightwatch・Sentry・Flare でも使えます。さらに、探したいものをすばやく見つけるための、便利なフィルタ(絞り込み)もあります。
入れ方#
注意
Laravel Pail には、PCNTL という PHP の拡張(PHP に機能を足す部品)が必要です。
Composer(PHP のパッケージを入れる道具)で、プロジェクトに Pail を入れます。
composer require --dev laravel/pail
使い方#
ログを流し読みするには、pail コマンドを動かします。
php artisan pail
出力を詳しくして、省略(…)を防ぐには、-v オプションを使います。
php artisan pail -v
いちばん詳しく出して、例外のスタックトレース(エラーまでの呼び出しの道筋)も出すには、-vv オプションを使います。
php artisan pail -vv
流し読みをやめるには、いつでも Ctrl+C を押します。
ログを絞り込む#
| オプション | 説明 |
|---|---|
--filter |
種類・ファイル・メッセージ・スタックトレースの内容で絞り込む |
--message |
メッセージだけで絞り込む |
--level |
ログレベルで絞り込む |
--user |
その ID の人がログインしている間に書かれたログだけ出す |
-v |
出力を詳しくして、省略を防ぐ |
-vv |
いちばん詳しく出して、スタックトレースも出す |
--filter#
--filter オプションで、ログの種類・ファイル・メッセージ・スタックトレースの内容を、絞り込めます。
php artisan pail --filter="QueryException"
--message#
メッセージだけで絞り込みたいときは、--message オプションを使います。
php artisan pail --message="User created"
--level#
--level オプションで、ログレベル(上の「ログレベル」の8段階)で絞り込めます。
php artisan pail --level=error
--user#
ある人がログインしている間に書かれたログだけ見たいときは、--user オプションに、その人の ID を渡します。
php artisan pail --user=1
関連するページ#
公式ドキュメント(英語)
2026年10月5日時点の内容をもとに、日本語でまとめています。