Skip to content

ロギング

はじめに

アプリケーション内で何が起こっているかを詳しく知るために、Laravelはファイル、システムエラーログ、さらにはSlackにメッセージをログとして記録し、チーム全体に通知することができる堅牢なロギングサービスを提供しています。

Laravelのロギングは「チャンネル」に基づいています。各チャンネルは、ログ情報を書き込む特定の方法を表します。例えば、singleチャンネルは単一のログファイルにログを書き込み、slackチャンネルはログメッセージをSlackに送信します。ログメッセージは、その重大度に基づいて複数のチャンネルに書き込むことができます。

内部的には、LaravelはMonologライブラリを利用しており、さまざまな強力なログハンドラをサポートしています。Laravelはこれらのハンドラを簡単に設定できるようにし、アプリケーションのログ処理をカスタマイズするためにそれらを組み合わせることができます。

設定

アプリケーションのロギング動作を制御するすべての設定オプションは、config/logging.php設定ファイルに収められています。このファイルでは、アプリケーションのログチャンネルを設定できるため、利用可能な各チャンネルとそのオプションを確認してください。以下では、いくつかの一般的なオプションを紹介します。

デフォルトでは、Laravelはログメッセージを記録する際にstackチャンネルを使用します。stackチャンネルは、複数のログチャンネルを単一のチャンネルに集約するために使用されます。スタックの構築について詳しくは、以下のドキュメントを参照してください。

利用可能なチャンネルドライバ

各ログチャンネルは「ドライバ」によって動作します。ドライバは、ログメッセージが実際にどのように記録されるかを決定します。以下のログチャンネルドライバは、すべてのLaravelアプリケーションで利用可能です。これらのドライバのほとんどは、アプリケーションのconfig/logging.php設定ファイルに既に存在しているため、このファイルを確認して内容に慣れることをお勧めします。

名前 説明
custom 指定されたファクトリを呼び出してチャンネルを作成するドライバ。
daily 日次でローテーションするRotatingFileHandlerベースのMonologドライバ。
errorlog ErrorLogHandlerベースのMonologドライバ。
monolog サポートされている任意のMonologハンドラを使用できるMonologファクトリドライバ。
papertrail SyslogUdpHandlerベースのMonologドライバ。
single 単一のファイルまたはパスベースのロガーチャンネル(StreamHandler)。
slack SlackWebhookHandlerベースのMonologドライバ。
stack 「マルチチャンネル」チャンネルを作成するためのラッパー。
syslog SyslogHandlerベースのMonologドライバ。

Note

高度なチャンネルカスタマイズのドキュメントを参照して、monologおよびcustomドライバの詳細を学んでください。

チャンネル名の設定

デフォルトでは、Monologは現在の環境に一致する「チャンネル名」(例:productionまたはlocal)でインスタンス化されます。この値を変更するには、チャンネルの設定にnameオプションを追加できます。

'stack' => [
    'driver' => 'stack',
    'name' => 'channel-name',
    'channels' => ['single', 'slack'],
],

チャンネルの前提条件

SingleおよびDailyチャンネルの設定

singleおよびdailyチャンネルには、3つのオプションの設定オプションがあります:bubblepermission、およびlocking

名前 説明 デフォルト
bubble メッセージが処理された後、他のチャンネルにバブルアップするかどうかを示します。 true
locking ログファイルに書き込む前にロックを試みます。 false
permission ログファイルのパーミッション。 0644

さらに、dailyチャンネルの保持ポリシーは、LOG_DAILY_DAYS環境変数またはdays設定オプションを介して設定できます。

名前 説明 デフォルト
days 日次ログファイルを保持する日数。 7

Papertrailチャンネルの設定

papertrailチャンネルには、hostおよびport設定オプションが必要です。これらは、PAPERTRAIL_URLおよびPAPERTRAIL_PORT環境変数を介して定義できます。これらの値は、Papertrailから取得できます。

Slackチャンネルの設定

slackチャンネルには、url設定オプションが必要です。この値は、LOG_SLACK_WEBHOOK_URL環境変数を介して定義できます。このURLは、Slackチーム用に設定したインカミングウェブフックのURLと一致する必要があります。

デフォルトでは、Slackはcriticalレベル以上のログのみを受信します。ただし、これはLOG_LEVEL環境変数を使用するか、Slackログチャンネルの設定配列内のlevel設定オプションを変更することで調整できます。

非推奨警告のロギング

PHP、Laravel、およびその他のライブラリは、その機能の一部が非推奨になり、将来のバージョンで削除されることをユーザーに通知することがよくあります。これらの非推奨警告をログに記録したい場合は、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ドライバを使用すると、複数のチャンネルを単一のログチャンネルに結合できます。ログスタックの使用方法を説明するために、本番アプリケーションで見られる設定例を見てみましょう。

'channels' => [
    'stack' => [
        'driver' => 'stack',
        'channels' => ['syslog', 'slack'], // [tl! add]
        '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オプションを介して他の2つのチャンネル(syslogslack)を集約していることに注目してください。したがって、ログメッセージを記録する際に、これらの両方のチャンネルがメッセージをログに記録する機会を持ちます。ただし、以下で見るように、これらのチャンネルが実際にメッセージをログに記録するかどうかは、メッセージの重大度/「レベル」によって決まる場合があります。

ログレベル

上記の例のsyslogおよびslackチャンネル設定にあるlevel設定オプションに注意してください。このオプションは、メッセージがチャンネルによってログに記録されるために必要な最小「レベル」を決定します。Laravelのロギングサービスを提供するMonologは、RFC 5424仕様で定義されたすべてのログレベルを提供します。重大度の降順で、これらのログレベルは次のとおりです:emergencyalertcriticalerrorwarningnoticeinfo、およびdebug

したがって、debugメソッドを使用してメッセージをログに記録すると想像してください:

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

与えられた設定に基づき、syslogチャンネルはメッセージをシステムログに書き込みます。しかし、エラーメッセージがcritical以上でないため、Slackには送信されません。しかし、emergencyメッセージをログに記録する場合、emergencyレベルは両方のチャンネルの最小レベルのしきい値を超えているため、システムログとSlackの両方に送信されます:

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

ログメッセージの書き込み

Log ファサードを使用して、ログに情報を書き込むことができます。前述のように、ロガーはRFC 5424仕様で定義された8つのロギングレベルを提供します:emergencyalertcriticalerrorwarningnoticeinfodebug

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\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;

class UserController extends Controller
{
    /**
     * 指定されたユーザーのプロフィールを表示します。
     */
    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
{
    /**
     * 受信リクエストを処理します。
     *
     * @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
{
    /**
     * 受信リクエストを処理します。
     *
     * @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
        ]);

        // ...
    }
}

Note

キューに入れられたジョブを処理する際にログコンテキストを共有する必要がある場合は、ジョブミドルウェアを利用できます。

特定のチャンネルへの書き込み

アプリケーションのデフォルトチャンネル以外のチャンネルにメッセージをログに記録したい場合があります。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!');

Monologチャンネルのカスタマイズ

チャンネルのMonologのカスタマイズ

既存のチャンネルに対してMonologの設定を完全に制御したい場合があります。たとえば、Laravelの組み込みsingleチャンネルに対してカスタムのMonolog FormatterInterface実装を設定したい場合です。

まず、チャンネルの設定にtap配列を定義します。tap配列には、Monologインスタンスの作成後にカスタマイズ(または「タップ」)する機会を持つクラスのリストを含める必要があります。これらのクラスを配置する標準的な場所はありませんので、アプリケーション内にこれらのクラスを含むディレクトリを自由に作成できます:

'single' => [
    'driver' => 'single',
    'tap' => [App\Logging\CustomizeFormatter::class],
    'path' => storage_path('logs/laravel.log'),
    'level' => env('LOG_LEVEL', 'debug'),
    'replace_placeholders' => true,
],

チャンネルのtapオプションを設定したら、Monologインスタンスをカスタマイズするクラスを定義する準備が整いました。このクラスには、Illuminate\Log\Loggerインスタンスを受け取る__invokeメソッドが1つ必要です。Illuminate\Log\Loggerインスタンスは、基礎となるMonologインスタンスへのすべてのメソッド呼び出しをプロキシします:

<?php

namespace App\Logging;

use Illuminate\Log\Logger;
use Monolog\Formatter\LineFormatter;

class CustomizeFormatter
{
    /**
     * 指定されたロガーインスタンスをカスタマイズします。
     */
    public function __invoke(Logger $logger): void
    {
        foreach ($logger->getHandlers() as $handler) {
            $handler->setFormatter(new LineFormatter(
                '[%datetime%] %channel%.%level_name%: %message% %context% %extra%'
            ));
        }
    }
}

Note

すべての「tap」クラスはサービスコンテナによって解決されるため、必要なコンストラクタ依存関係は自動的に注入されます。

Monologハンドラチャンネルの作成

Monologにはさまざまな利用可能なハンドラがあり、Laravelにはそれぞれに対応する組み込みチャンネルが含まれていません。特定のMonologハンドラのインスタンスであるカスタムチャンネルを作成したい場合があります。これらのチャンネルは、monologドライバを使用して簡単に作成できます。

monologドライバを使用する場合、handler設定オプションを使用して、どのハンドラがインスタンス化されるかを指定します。必要に応じて、ハンドラが必要とするコンストラクタパラメータは、with設定オプションを使用して指定できます:

'logentries' => [
    'driver'  => 'monolog',
    'handler' => Monolog\Handler\SyslogUdpHandler::class,
    '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,
     'with' => [
         'stream' => 'php://stderr',
     ],
     'processors' => [
         // シンプルな構文...
         Monolog\Processor\MemoryUsageProcessor::class,

         // オプション付き...
         [
            'processor' => Monolog\Processor\PsrLogMessageProcessor::class,
            'with' => ['removeUsedContextFields' => true],
        ],
     ],
 ],

ファクトリを介したカスタムチャンネルの作成

Monologのインスタンス化と設定を完全に制御できる完全にカスタムなチャンネルを定義したい場合は、config/logging.php設定ファイルでcustomドライバタイプを指定できます。設定には、Monologインスタンスを作成するために呼び出されるファクトリクラスの名前を含むviaオプションを含める必要があります。

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

customドライバチャンネルを設定したら、Monologインスタンスを作成するクラスを定義する準備が整いました。このクラスには、Monologロガーインスタンスを返す必要がある単一の__invokeメソッドが必要です。このメソッドは、チャンネル設定配列を唯一の引数として受け取ります。

<?php

namespace App\Logging;

use Monolog\Logger;

class CreateCustomLogger
{
    /**
     * カスタムMonologインスタンスを作成する。
     */
    public function __invoke(array $config): Logger
    {
        return new Logger(/* ... */);
    }
}

Pailを使用したログメッセージのテイル

アプリケーションのログをリアルタイムでテイルする必要がある場合があります。例えば、問題のデバッグや、特定の種類のエラーのアプリケーションログの監視などです。

Laravel Pailは、コマンドラインから直接Laravelアプリケーションのログファイルに簡単にアクセスできるようにするパッケージです。標準のtailコマンドとは異なり、PailはSentryやFlareを含む任意のログドライバで動作するように設計されています。さらに、Pailは、探しているものをすばやく見つけるのに役立つ一連の便利なフィルタを提供します。

インストール

Warning

Laravel PailにはPHP 8.2+PCNTL拡張機能が必要です。

始めるには、Composerパッケージマネージャを使用してPailをプロジェクトにインストールします。

composer require laravel/pail

使用方法

ログのテイルを開始するには、pailコマンドを実行します。

php artisan pail

出力の冗長性を上げ、切り捨て(…)を避けるには、-vオプションを使用します。

php artisan pail -v

最大の冗長性と例外スタックトレースを表示するには、-vvオプションを使用します。

php artisan pail -vv

ログのテイルを停止するには、いつでもCtrl+Cを押します。

ログのフィルタリング

--filter

ログをタイプ、ファイル、メッセージ、スタックトレースの内容でフィルタリングするには、--filterオプションを使用します。

php artisan pail --filter="QueryException"

--message

ログをメッセージのみでフィルタリングするには、--messageオプションを使用します。

php artisan pail --message="User created"

--level

ログをログレベルでフィルタリングするには、--levelオプションを使用します。

php artisan pail --level=error

--user

特定のユーザーが認証されている間に書き込まれたログのみを表示するには、ユーザーのIDを--userオプションに指定します。

php artisan pail --user=1

ユーザーノート