メインコンテンツまでスキップ

ロギング

はじめに

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

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

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

設定

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

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

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

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

NameDescription
custom指定されたファクトリを呼び出してチャネルを作成するドライバ
daily毎日ローテーションする RotatingFileHandler ベースの Monolog ドライバ
errorlogErrorLogHandler ベースの Monolog ドライバ
monolog任意のサポートされている Monolog ハンドラを使用できる Monolog ファクトリドライバ
papertrailSyslogUdpHandler ベースの Monolog ドライバ
single単一のファイルまたはパスベースのロガーチャネル (StreamHandler)
slackSlackWebhookHandler ベースの Monolog ドライバ
stack"マルチチャネル" チャネルを作成するためのラッパー
syslogSyslogHandler ベースの Monolog ドライバ
注記

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

チャネル名の設定

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

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

チャネルの前提条件

単一および毎日のチャネルの構成

single および daily チャネルには、bubblepermissionlocking の 3 つのオプションの構成があります。

<div class="overflow-auto">

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

</div>

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

<div class="overflow-auto">

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

</div>

<a name="configuring-the-papertrail-channel"></a>
#### Papertrail チャンネルの構成

`papertrail` チャンネルには `host``port` の構成オプションが必要です。これらは `PAPERTRAIL_URL` および `PAPERTRAIL_PORT` 環境変数を介して定義できます。これらの値は [Papertrail](https://help.papertrailapp.com/kb/configuration/configuring-centralized-logging-from-php-apps/#send-events-from-php-app) から取得できます。

<a name="configuring-the-slack-channel"></a>
#### Slack チャンネルの構成

`slack` チャンネルには `url` の構成オプションが必要です。この値は `LOG_SLACK_WEBHOOK_URL` 環境変数を介して定義できます。この URL は、Slack チームで構成した [着信ウェブフック](https://slack.com/apps/A0F7XDUAZ-incoming-webhooks) の URL と一致する必要があります。

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

<a name="logging-deprecation-warnings"></a>
### 廃止予告のログ記録

PHP、Laravel、および他のライブラリは、しばしばユーザーに、いくつかの機能が廃止され、将来のバージョンで削除されることを通知します。これらの廃止警告をログに記録したい場合は、お好みの `deprecations` ログチャンネルを `LOG_DEPRECATIONS_CHANNEL` 環境変数またはアプリケーションの `config/logging.php` 構成ファイル内で指定できます。
    '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'], // [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メッセージを記録すると、システムログとSlackの両方に送信されます。なぜなら、emergencyレベルは両方のチャネルの最小レベル閾値を上回っているからです:

    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
]);

// ...
}
}

注記

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

特定のチャネルに書き込む

アプリケーションのデフォルトチャネル以外にメッセージをログに記録したい場合があります。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 インスタンスが作成された後にカスタマイズ(または "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 メソッドのみが必要で、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構成オプションを使用してどのハンドラがインスタンス化されるかを指定します。オプションで、ハンドラが必要とする任意のコンストラクタパラメータを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',
],


<a name="monolog-processors"></a>
#### Monolog Processors

Monolog can also process messages before logging them. You can create your own processors or use the [existing processors offered by Monolog](https://github.com/Seldaek/monolog/tree/main/src/Monolog/Processor).

If you would like to customize the processors for a `monolog` driver, add a `processors` configuration value to your channel's configuration:

'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は、標準の tail コマンドとは異なり、SentryやFlareを含む任意のログドライバーと連携するよう設計された、Laravelアプリケーションのログファイルに直接アクセスできるパッケージです。さらに、Pailには、探している内容を迅速に見つけるのに役立つ便利なフィルターが用意されています。

インストール

警告

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