本文へ移動
Laravel Tips

ログ

アプリの動きを記録するログの設定と書き方を説明します。チャンネルとドライバの一覧・スタック・ログレベル・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 オプションを足します。

php
'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 のログチャンネルを決めます。

php
'deprecations' => [
    'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
    'trace' => env('LOG_DEPRECATIONS_TRACE', false),
],

'channels' => [
    // ...
]

または、deprecations という名前のログチャンネルを作ります。この名前のチャンネルがあれば、非推奨の警告の記録には、必ずそれが使われます。

php
'channels' => [
    'deprecations' => [
        'driver' => 'single',
        'path' => storage_path('logs/php-deprecation-warnings.log'),
    ],
],

ログのスタックを作る#

前に書いたとおり、stack ドライバを使うと、複数のチャンネルを、1つのログチャンネルにまとめられます。本番のアプリでありそうな設定の例で、使い方を見てみます。

php
'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 メソッドでメッセージを記録するとします。

php
Log::debug('An informational message.');

この設定では、syslog チャンネルは、メッセージをシステムのログに書きます。でも、このメッセージは critical 以上ではないので、Slack へは送られません。一方、emergency のメッセージは、どちらのチャンネルの最低のレベルよりも重いので、システムのログにも Slack にも送られます。

php
Log::emergency('The system is down!');

ログのメッセージを書く#

ログは、Log のファサード(クラス名と :: で呼べる窓口)で書きます。前に書いたとおり、ロガー(ログを書く係)は、RFC 5424 で決められた、8つのログレベルを持っています。emergency・alert・critical・error・warning・notice・info・debug です。

php
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
<?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)
        ]);
    }
}

付け足しの情報(コンテキスト)#

ログのメソッドには、付け足しの情報(コンテキスト)の配列を渡せます。この情報は、整えられて、ログのメッセージといっしょに表示されます。

php
use Illuminate\Support\Facades\Log;

Log::info('User {id} failed to login.', ['id' => $user->id]);

あるチャンネルの、このあとのログすべてに、同じ付け足しの情報を入れたいことがあります。たとえば、アプリに届くリクエストごとに付く、リクエスト ID を記録したいときです。Log ファサードの withContext メソッドを呼びます。

php
<?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
<?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 メソッドを使うと、設定ファイルで決めたチャンネルを取り出して、記録できます。

php
use Illuminate\Support\Facades\Log;

Log::channel('slack')->info('Something happened!');

複数のチャンネルをまとめた、その場限りのログのスタックを作りたいなら、stack メソッドを使います。

php
Log::stack(['single', 'slack'])->info('Something happened!');

その場で作るチャンネル#

アプリの logging の設定ファイルになくても、動かす時点で設定を渡して、その場限りのチャンネルを作ることもできます。Log ファサードの build メソッドに、設定の配列を渡します。

php
use Illuminate\Support\Facades\Log;

Log::build([
  'driver' => 'single',
  'path' => storage_path('logs/custom.log'),
])->info('Something happened!');

その場で作ったチャンネルを、その場で作るログのスタックに入れたいこともあります。stack メソッドに渡す配列に、そのチャンネルのオブジェクトを入れればできます。

php
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」する)ことができます。これらのクラスを置く、決まった場所はありません。アプリの中に、好きなフォルダを作って置けます。

php
'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
<?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 オプションで決められます(省略できます)。

php
'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 のオプションで、ハンドラに渡すフォーマッタを変えられます。

php
'browser' => [
    'driver' => 'monolog',
    'handler' => Monolog\Handler\BrowserConsoleHandler::class,
    'formatter' => Monolog\Formatter\HtmlFormatter::class,
    'formatter_with' => [
        'dateFormat' => 'Y-m-d',
    ],
],

自分のフォーマッタを持てる Monolog のハンドラを使うなら、formatter オプションの値を default にできます。

php
'newrelic' => [
    'driver' => 'monolog',
    'handler' => Monolog\Handler\NewRelicHandler::class,
    'formatter' => 'default',
],

Monolog のプロセッサ#

Monolog は、メッセージを記録する前に、加工することもできます。自分でプロセッサ(加工する係)を作るか、Monolog が用意しているプロセッサを使えます。

monolog ドライバのプロセッサを変えたいときは、チャンネルの設定に processors の値を足します。

php
'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 のオブジェクトを作るファクトリ(作る係)のクラスの名前を書きます。

php
'channels' => [
    'example-custom-channel' => [
        'driver' => 'custom',
        'via' => App\Logging\CreateCustomLogger::class,
    ],
],

custom ドライバのチャンネルを設定したら、Monolog のオブジェクトを作るクラスを書きます。このクラスに必要なのは __invoke メソッドだけです。このメソッドは、チャンネルの設定の配列を1つだけ引数に受け取り、Monolog のロガー(ログを書く係)のオブジェクトを返します。

php
<?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 を入れます。

bash
composer require --dev laravel/pail

使い方#

ログを流し読みするには、pail コマンドを動かします。

bash
php artisan pail

出力を詳しくして、省略(…)を防ぐには、-v オプションを使います。

bash
php artisan pail -v

いちばん詳しく出して、例外のスタックトレース(エラーまでの呼び出しの道筋)も出すには、-vv オプションを使います。

bash
php artisan pail -vv

流し読みをやめるには、いつでも Ctrl+C を押します。

ログを絞り込む#

オプション 説明
--filter 種類・ファイル・メッセージ・スタックトレースの内容で絞り込む
--message メッセージだけで絞り込む
--level ログレベルで絞り込む
--user その ID の人がログインしている間に書かれたログだけ出す
-v 出力を詳しくして、省略を防ぐ
-vv いちばん詳しく出して、スタックトレースも出す

--filter#

--filter オプションで、ログの種類・ファイル・メッセージ・スタックトレースの内容を、絞り込めます。

bash
php artisan pail --filter="QueryException"

--message#

メッセージだけで絞り込みたいときは、--message オプションを使います。

bash
php artisan pail --message="User created"

--level#

--level オプションで、ログレベル(上の「ログレベル」の8段階)で絞り込めます。

bash
php artisan pail --level=error

--user#

ある人がログインしている間に書かれたログだけ見たいときは、--user オプションに、その人の ID を渡します。

bash
php artisan pail --user=1

関連するページ#

公式ドキュメント(英語)

2026年10月5日時点の内容をもとに、日本語でまとめています。

ページの一覧