コンテンツへスキップ

ロギング

導入

アプリケーション内で何が起こっているかをより深く理解するために、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ドライバー。
lightbulb

`monolog`および`custom`ドライバーの詳細については、高度なチャネルのカスタマイズに関するドキュメントを参照してください。

チャネル名の設定

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

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

チャネルの前提条件

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

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

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

さらに、`daily`チャネルの保持ポリシーは、`LOG_DAILY_DAYS`環境変数で設定するか、`days`設定オプションを設定することで設定できます。

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

Papertrailチャネルの設定

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

Slackチャネルの設定

`slack`チャネルには、`url`設定オプションが必要です。この値は、`LOG_SLACK_WEBHOOK_URL`環境変数で定義できます。このURLは、Slackチームで設定した着信Webhookの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'],
'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つのチャネル(`syslog`と`slack`)を集約していることに注意してください。そのため、メッセージをログに記録すると、これらのチャネルの両方がメッセージをログに記録する機会を持ちます。しかし、以下で説明するように、これらのチャネルが実際にメッセージをログに記録するかどうかは、メッセージの重大度/「レベル」によって決まる可能性があります。

ログレベル

上記の例で`syslog`と`slack`チャネルの設定に存在する`level`設定オプションに注意してください。このオプションは、チャネルによってログに記録されるためにメッセージが満たす必要がある最小「レベル」を決定します。Laravelのロギングサービスを制御するMonologは、RFC 5424仕様で定義されているすべてのログレベルを提供します。重大度の降順で、これらのログレベルは:**緊急**、**警告**、**クリティカル**、**エラー**、**警告**、**通知**、**情報**、**デバッグ**です。

そこで、`debug`メソッドを使用してメッセージをログに記録するとします。

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

設定を考慮すると、`syslog`チャネルはメッセージをシステムログに書き込みます。ただし、エラーメッセージが`critical`以上ではないため、Slackに送信されません。ただし、`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
{
/**
* 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
]);
 
// ...
}
}
lightbulb

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

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

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

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

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

Monologにはさまざまな利用可能なハンドラーがあり、Laravelはそれぞれに組み込みのチャンネルを含んでいません。場合によっては、対応する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がデフォルトのフォーマッタとして使用されます。ただし、formatterformatter_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' => [
// Simple syntax...
Monolog\Processor\MemoryUsageProcessor::class,
 
// With options...
[
'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
{
/**
* Create a custom Monolog instance.
*/
public function __invoke(array $config): Logger
{
return new Logger(/* ... */);
}
}

Pailを使用したログメッセージの追跡

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

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

インストール

exclamation

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