Article by: Kyle Tryon
本ブログの内容
- サンプルプロジェクトのセットアップ
- Monolog を使った Laravel のログ記録
- Laravel をデバッグするために使うべきツール
- Laravel アプリのパフォーマンス問題をトラブルシュートし修正する
- 本番環境で Sentry を使って Laravel をデバッグ・ロギングする
- Laravel をよりスマートにデバッグする
ロジックエラー、失敗した HTTP リクエスト、気付かれずに消えるバックグラウンドジョブ。ソフトウェアはあらゆる「楽しい」形で壊れます。強靭なシステムと脆いシステムの違いは、エラーを完全に回避できるかどうかではありません。何が問題だったのかを、いかに素早く、明確に把握し、修正できるかにかかっています。
Laravel はしっかりとした基盤を提供します。構造化ログ、リアルタイムでの内部観察、そして組み込みのパフォーマンス監視。開発やステージング環境では、dd()、Log::debug()、Monolog、Telescope、Debugbar、Xdebug といったツールを使って、内部を覗き込むことができます。しかし、本番環境はまったく別物です。
本番環境でフロントエンドとバックエンド両方のエラー、遅延、そして再現が難しいエッジケースにわたる完全な可視性を確保するために、Sentry は Laravel アプリに統合され、必要な時に必要なコンテキストを、異なるサービスを横断して提供します。
このガイドでは、いくつかの Laravel デバッグツールについて説明します。それぞれが何をするのか、どのような場面で使うべきか、そしてログを掘り返したり環境ごとに何が悪かったのかを推測したりせずに、適切なインサイトを得る方法を解説します。
前提条件
すでにお使いのコンピュータに Laravel 12 がインストールされている場合は、それを使用できます。
ただし、このガイドでは別のアプローチを取り、Docker コンテナ内でサンプルを実行します。Docker を使うことで、この記事内のコードはあらゆるオペレーティングシステム上で実行でき、セキュアなサンドボックス内で個人ファイルから安全に分離され、特定のバージョンの Laravel、Node、PHP をインストールする必要もありません。
また、このガイドでは Git がインストールされていることを前提としていますが、必要であればサンプルリポジトリを手動でダウンロードして解凍することもできます。
サンプルプロジェクトのセットアップ
Laravel のロギングやデバッグツールが実際にどのように動作するかを見るために、ここでは Laravel で構築されたサンプルの決済 API を使用します。このプロジェクトでは、ユーザーが通貨間で送金、受け取り、両替を行うことができ、その最小限の設計によってビジネスロジックではなく可観測性に焦点を当てています。コードベースは GitHub で確認できます。
まず、プロジェクトをクローンします。
以下のコマンドを実行して、Laravel 12 がインストールされた Docker ターミナルを起動します。以降、このガイドではこの Docker ターミナル上で作業を進めます。もし Docker を使わずに、Laravel を直接お使いのコンピュータで実行したい場合は、この手順をスキップしてください。
次に、以下のコマンドを実行して依存関係をインストールし、環境をセットアップします。
続いて、アプリを起動します。
http://localhost:8000 にアクセスして、アプリが動作していることを確認してください。

Laravel ウェルカム画面
このアプリは Web サイトではなく決済 API なので、表示されるのは Laravel のプレースホルダー画面だけです。
アプリの仕組みとしては、ユーザー間の決済を表す HTTP リクエストを受け取り、その情報をデータベースに保存するだけです。動作の詳細を確認するには、app/Http/Controllers/Api/PaymentController.php ファイルを参照してください。サンプルの決済データでデータベースを埋めるための関数は、app/Http/Controllers/DummyDataController.php にあります。
Monolog を使った Laravel のログ記録
デフォルトで、Laravel は Monolog を使用します。Monolog は強力な PHP のロギングライブラリで、複数のログフォーマット、出力先、重大度レベルをサポートしています。Laravel はこのライブラリを Log::info() や Log::debug() といったクリーンなAPI でラップしているため、Monolog の仕組みを理解しなくてもすぐにログ記録を始められます。
ここでは、Laravel アプリケーションでリクエストが200ミリ秒を超えた場合にログを作成する方法を見ていきます。その際、長いクエリを検出するために Laravel のネイティブなデータベースツールを使用します。
ターミナルで Ctrl + C を押して、実行中のアプリを停止してください。
次に、app/Providers/AppServiceProvider.php の内容を以下のコードに書き換えます。
もしそのファイルが読み取り専用であるためにパーミッションの問題がある場合は、Docker の外側で新しいターミナルを開き、sudo chown -R $USER . を実行してファイルパーミッションを修正してください。
データベースは、各受信 HTTP リクエストの所要時間を測定し、リクエストが長すぎる場合には laravel.log に警告をログします。ログエントリには、URL、メソッド、ユーザーID、IP アドレス、メモリ使用量メトリクスといったメタデータが含まれます。
ここでは、ロギングを実演するために所要時間を1ミリ秒に設定していますが、より実用的なしきい値は500ミリ秒です。
アプリを呼び出しましょう。これにより、新しいミドルウェアでログエントリが作成されます。
アプリを再起動します。
ホスト上の新しいターミナルで(まだアプリが実行中の Docker 内ではなく)、アプリを呼び出してダミーのログデータを生成します。

同じホストのターミナルで、次のコマンドを実行してログを表示します。
ログ出力には、1件のスローログが検出されたことが示されています。

チャンネルを使ってログの出力先を制御する
Laravel のロギングシステムはチャンネルベースです。各チャンネルは、ドライバ(例:stack、daily、slack、syslog)と、ログがどのように、どこに書き込まれるかの設定を定義します。ロギングチャンネルは config/logging.php で定義およびカスタマイズします。
デフォルトのチャンネルは通常 stack で、これにより複数のチャンネルを1つにまとめることができます。
.env ファイルでアクティブなロギングチャンネルを変更することで、ログの書き込み先(例:ログファイルや Slack のチャンネル)を指定できます。
スタックを使用することで、ログを同時に複数の出力先へ書き込むことができます。たとえば、デバッグ出力をファイルに書き込みつつ、重大なエラーを Slack や Sentry に送信することができます。
Laravel をデバッグするために使うべきツール
ロギングは「何が問題だったか」を把握するのに役立ちますが、「なぜそうなったのか」までは必ずしも教えてくれません。問題をより深く理解するには、リクエストをトレースしたり、クエリを調べたり、失敗の原因を理解するためのデバッグツールが必要です。
Laravel は、ローカルでのデバッグやより深い問題調査に使えるさまざまなツールを提供しています。
- dd() と dump() 関数:変数、オブジェクト、実行フローをその場で確認する
- Laravel Telescope:SQLクエリの追跡、リクエスト時間の計測、ジョブが失敗した理由の把握など、より深い可視性を得る
- Laravel Debugbar:レンダリングされたビュー、ルートの詳細、クエリ実行時間、メモリ使用量を追跡する
Laravel に組み込まれたデバッグ関数 — dd() と dump()
デバッグの最初のステップは、変数に何が入っているかを確認することが多いです。Laravel はそのための2つの組み込みヘルパーを提供しています。
- dump():変数の内容を出力しますが、実行は続行します。
- dd()(“dump and die” の略):データを出力し、リクエストを終了します。
たとえば、支払い作成リクエストに関する情報をログに記録し、例外の詳細をより適切に分析・処理するために catch ブロック内で dd() を使うことができます。
app/Http/Controllers/Api/PaymentController.php の store 関数を次のコードに書き換えます。
これで、API クライアントを使って支払いを作成する POST リクエストを送信すると、レスポンスパネルに出力が表示されます。
ホスト上のターミナルで(Docker ターミナルではなく)、以下のコマンドを実行してアプリ経由で支払いを送信します。
コマンドの出力は分かりにくいものになります。これは、dump コマンドがアプリを実行しているターミナルやログファイルではなく、ブラウザにデバッグ情報を返すためです。
Insomnia のようなビジュアルリクエスト送信ツールを使うと、出力を分かりやすく整形できます。

Insomnia でリクエストを送信
dd() と dump() 関数は Symfony の VarDumper コンポーネントによって動作しているため、複雑なオブジェクトやコレクションであってもクリーンで読みやすい出力が得られます。
とはいえ、dd() や dump() を本番コードに含めるべきではありません。これらのツールは実行を停止させ、内部情報を漏らし、ログにも残りません。本番環境で安全に調査するには、Log::debug() のような構造化ロギングを使用する方が適しています。
Laravel Debugbar を効果的に使用する
Laravel Debugbar はアプリケーションにビジュアルなツールバーを追加し、デバッグ情報をブラウザ上に直接表示します。Debugbar は Laravel と密接に統合されており、裏側で何が起きているのかを即座にフィードバックしてくれます。フロントエンド寄りの開発や、開発中のページ上でクエリ、ルート、リクエスト時間を直接確認したい場合に最適です。
Composer を使ってこのパッケージをインストールできます。
Dockerターミナルで Ctrl + C を押して、実行中のアプリを停止してください。
次に、以下のコマンドを実行して Debugbar をインストールし、アプリを再起動します。

インストールが完了すると、Debugbar は自動的に有効化され、アプリがレンダリングするすべてのページ下部にフローティングバーとして表示されます。下の画像は、http://127.0.0.1:8000 で実行中の Laravel アプリケーションのルートページを示しています。

Laravel Debugbar
ページのコンテンツがレンダリングされる前に、このページで実行されたクエリを確認できます。

Laravel Debugbar SQL クエリ
Debugbar はローカル開発に非常に役立ちます。特に、Eloquent のパフォーマンス問題に対処するとき、ルートの挙動を理解しようとするとき、あるいはコンポジションの問題をデバッグするときに便利です。Laravel の組み込みヘルパーと同様に、Debugbar は本番環境で使用することを意図したものではありません。開発用の依存関係にとどめ、ローカル環境以外では無効にしておきましょう。
Laravel Telescope のセットアップ方法
Laravel Telescope は公式のデバッグ支援ツールで、アプリケーションの実行時の挙動を深く可視化してくれます。ローカル開発中やステージング環境でのデバッグ時に有用で、Telescope はバックエンド用のダッシュボードとして機能し、受信リクエスト、キューに入ったジョブ、例外、ログ、データベースクエリをリアルタイムで表示します。
Docker ターミナルで Ctrl + C を押して、実行中のアプリを停止してください。
次に、以下のコマンドを実行して Telescope をインストールします。
Telescope の UI パネルは http://localhost:8000/telescope で確認できます。

Telescope UI
有効化すると、Telescope は自動的に次のような詳細を記録します。
- HTTP リクエスト(ヘッダー、ペイロード、ステータスコードを含む)
- データベースクエリ(バインディングと実行時間付き)
- ログ
- スケジュールされたタスク
- キューに入ったジョブ
- モデルイベント
Telescope を使うことで、コードを変更せずに状況を調査でき、状況を理解し判断するために十分なコンテキストを得られます。たとえば、以下は /api/v1/payments への POST リクエストの詳細ビューです。

リクエスト詳細ビュー
Telescope は機密データを公開してしまうため、セキュリティが確保されていない限り本番環境で実行するのは避けてください。仮にセキュリティを確保したとしても、Telescope は本番環境向けに最適化されていません。Telescope はすべてをログに記録するため、パフォーマンスのオーバーヘッドを引き起こす可能性があります。
VS Code で Laravel をデバッグするためのベストプラクティス
低レベルでの調査やコードを一行ずつステップ実行する場合、Xdebug は VS Code で Laravel アプリケーションをデバッグする最も強力な選択肢であり続けています。Xdebug を 使えば、エディタから直接ブレークポイントを設定したり、変数を監視したり、実行フローを制御したりできます。
Laravel は標準で Xdebug をサポートしており、Laravel Sail、DDEV、その他のコンテナ環境を使用している場合、Xdebug の有効化は通常コンフィグフラグを切り替えるだけです。
VS Code で Xdebug をセットアップすると、次のことができます。
- コントローラメソッドやジョブハンドラ内で実行を一時停止し、行ごとに何が起きているかを確認
- オブジェクト、クロージャ、サービスコンテナのバインディングを調査
- リクエストからレスポンスまでのライフサイクルにわたる実行時の状態を監視
PHP でのロギングとデバッグに関する記事で、Xdebug と VS Code を使ったデバッグの詳細を確認できます。
Laravel アプリのパフォーマンス問題をトラブルシュートし修正する
Laravel のロギングおよびデバッグツールは、開発中に特に役立つパフォーマンス問題の発見にも活用できます。
- Monolog:ミドルウェア、リスナー、その他パフォーマンスが重要な領域にロギングを追加し、遅い SQL クエリを追跡してボトルネックを特定します。
- Laravel Telescope:パフォーマンスに影響するコンポーネントを監視します。たとえば「Queries」ページでは、それぞれのクエリにかかる時間を確認し、遅いものを特定して詳細を掘り下げ、遅延の原因を理解することができます。

Laravel Telescope Queries ページ
- Laravel Debugbar:Web ページの裏側で何が起きているかを調査できます。タイムラインビューを使って、クエリのパフォーマンスを分析し、イベントを追跡し、ページの各部分がレンダリングに要する時間を確認できます。

Laravel Debugbar タイムライングラフ
ただし、これらのツールが最も効果を発揮するのは、すでにパフォーマンス問題に気付いていて、それをローカルでデバッグしているときです。本番環境でのトラブルシューティングには異なるアプローチが必要です。Monolog は問題をログに記録できますが、リアルタイムで通知することはできません。Telescope や Debugbar は深い洞察を提供しますが、すべてを追跡するため、本番環境で安全に実行するようには設計されていません。
本番環境でパフォーマンス問題をトラブルシュートし、修正するには次のことが必要です。
- プロセスが遅いときにアラートを受け取ること
- スタックトレースや例外のコンテキストをリアルタイムで確認すること
- どの環境が影響を受けているかを追跡すること
- 何人のユーザーがどのくらいの頻度で、どのエンドポイントやビューで影響を受けているかを確認して影響度を測定すること
本番環境で Sentry を使って Laravel をデバッグ・ロギングする
効果的なデバッグには、アプリケーションがいつ壊れたのか、なぜそうなったのか、そしてどのようなコンテキストで失敗に至ったのかを把握することが必要です。ここで Sentry がそのギャップを埋めます。Sentry は未処理の例外を捕捉し、類似するエラーを集約し、完全なスタックトレースを表示し、さらに環境、ルート、ユーザー、リリースバージョンといったコンテキストを自動的に付加します。
Sentry を Laravel アプリケーションに統合するのは、Sentry Laravel SDK を使えば簡単です。より高度な統合オプションやプラットフォーム対応については、完全な PHP SDK ドキュメントを参照してください。
Sentry をインストールしてエラーを監視する
Laravel アプリに Sentry をインストールするには、Sentry Laravel ガイドで提供されているコードスニペットを使用します。
Docker ターミナルで Ctrl + C を押して、実行中のアプリを停止してください。
次に、以下のコマンドを実行して Sentry SDK をインストールします。
未処理の例外を Sentry で捕捉できるようにするために、bootstrap/app.php の内容を次のコードに書き換えてください。
作業している決済ゲートウェイは Web サイトではなく API であるため、上記のコードには Sentry Laravel ガイドには含まれていない1行が追加されています。
api: __DIR__.’/../routes/api.php’,
次に、Sentry で新しい Laravel プロジェクトを作成し、Sentry ダッシュボードでプロジェクトの DSN を控えてください。
Docker ターミナルで以下のコマンドを実行し、YOUR_DSN をプロジェクトの DSN に置き換えて Sentry を設定します。
すべてのプロンプトには yes と答えてください。
これにより、config/sentry.php ファイルが作成され、.env ファイルに SENTRY_LARAVEL_DSN という変数名で DSN が追加され、Sentry にテストエラーが送信されます。
次に、以下のコマンドを実行して Sentry にもう一度テストエラーを送信し、設定を確認します。

Sentry 設定テスト
Sentry の Web インターフェースのサイドバーで Issues をクリックします。Issues ページにテストエラーが表示されます。

Sentry でテスト Issue を確認
Sentry はアプリケーションを監視し、新しい問題をすべてログに記録するように設定されました。
エラーを手動で報告
キャッチした例外を Sentry に手動で報告することもできます。
たとえば、app/Http/Controllers/Api/PaymentController.php 内で、dump 関数を使って変更した支払い作成エンドポイントを考えてみましょう。
dump() を使う代わりに、例外を Sentry に報告することができます。
Sentry のエラーレポートを実装するために、store 関数を次のコードに書き換えてください。
これで、支払いを作成するリクエストを送信すると500エラーが発生し、Sentry がその例外を捕捉します。
Docker ターミナルでアプリを起動してください。
ホスト上のターミナルで、curl を使ってアプリを呼び出し、エラーを発生させます。
ブラウザで Sentry の Issues ページをリフレッシュして、エラーを確認してください。

Sentry による支払いエラーの捕捉
Issues をクリックすると、例外に関する詳細情報を確認できます。
エラーを引き起こした行を含む詳細なトレースがページ上部に表示されます。

Issues トレース
スクロールダウンすると、リクエストに関する情報(ボディ、ヘッダー、サーバーレスポンスタイムなどのメトリクス)が表示されます。

Sentry トレースビュー
基本的な例外トラッキングが動作するようになったら、エラーの整理方法や表示方法をさらにカスタマイズできます。
Sentry では、環境(local、staging、production)、認証済みのユーザーID、特定のアプリケーションの状態などのカスタムデータで Issue にタグを付けることができます。これにより、特にマルチテナントやマルチサービスシステムにおいて、Issue を効果的にグループ化・フィルタリングできます。
構造化ログの送信
Sentry は、アプリからのログを構造化フォーマットで保存できます。
この機能の概要や Laravel でのセットアップ方法については、ドキュメントを参照してください。
このセクションでは、Laravel で 構造化ログを設定する方法を説明します。
config/logging.php の53行目あたりで、channels 配列に新しい sentry_logs チャンネルを追加し、次のコードスニペットと一致させてください。
.env ファイルで、LOG_STACK 設定に ,sentry_logs を追加して新しいドライバを有効化し、さらに Sentry のログ設定を有効にしてください。
以下の行を参考にしてください。

app/Http/Controllers/Api/PaymentController.php 内の store 関数を最後にもう一度変更し、Sentry にいくつかのログを送信するようにします。
コントローラーファイルの先頭付近の using セクションに、次の行を追加してください。
ファイルの下の方で、store 関数を次のコードに書き換えてください。
この新しいコードは、プレーンテキストと構造化プロパティの両方を info 重大度レベルでログに記録します。
Docker ターミナルで Ctrl + C を押してアプリを停止してください。
アプリを再起動します。
▶️ ホスト上のターミナルで(Docker ターミナルではなく)、以下のコマンドを実行してアプリを経由し、支払いを送信します。
▶️ Sentry がログを受信するまで少し待ってから、Sentry の Web インターフェースで Logs タブに移動し、ログの詳細を確認してください。

Laravel の Sentry 構造化ログ
Sentry のログは、テキスト、プロパティ、重大度レベル、タイムスタンプ、あるいは通貨のような構造化プロパティでフィルタリングでき、エラーに関する詳細情報を探し出すことができます。
ログインを処理する
Sentry がログイン中のユーザーをイベントに自動的に関連付けるようにするには、.env ファイルに次の設定を追加してください。
認証がいつ、どのようにログに記録されるかをより細かく制御したい場合は、Laravel の Authenticated イベントをリッスンしてユーザーを手動で設定してください。
今回のサンプル決済 API では認証を使用していないため、ログに記録する認証アクティビティはありません。しかし、認証を利用する Laravel アプリに Sentry の認証ログを追加する場合は、app/Providers/AppServiceProvider.php の内容を次のコードに書き換えてください
イベントにカスタムタグを追加する
Sentry では、イベントにカスタムタグを追加して拡張できます。カスタムタグはインデックス化されたキーと値のペアで、Issue をグループ化、検索、フィルタリングするのに利用できます。タグでは、ロケール、顧客階層、デプロイバージョン、リクエストの送信元といった詳細を追跡できます。
イベントの拡張についての詳細は、Sentry の Laravel ドキュメントを参照してください。
パフォーマンスの低下を自動検出する
Sentry では、プロジェクト内の特定のイベントに関連するパフォーマンス問題を追跡することもできます。たとえば、遅いデータベースクエリや N+1 リクエストについて Sentry からアラートを受け取るように設定できます。
Sentry のアラートを細かく調整するには、ダッシュボードで Settings → Projects → [Your Project] → Performance に移動してください。すべての設定オプションは Performance Issues – Detector Threshold Settings にあります。

Sentry のパフォーマンス設定
本番環境と開発環境の両方における Laravel の一般的な問題に対する解決策は、Sentry Laravel Answers ページで確認できます。より広範な PHP のエラーハンドリングに関するガイダンスについては、Sentry PHP Answers ハブをご覧ください。
クリーンアップ
ここまでの手順で使ったものを片付けたい場合は、以下の方法でサンプルリポジトリを削除・除去できます。
まず、exit と入力して Docker ターミナルを閉じます。
その後、以下のコマンドを実行してシステムからすべてのDockerイメージを削除し、サンプルリポジトリを削除します。
Laravel をよりスマートにデバッグする
Laravel の監視とデバッグのアプローチは、開発者に優しい設計になっています。変数を出力するために dd() を使う場合でも、失敗したリクエストを分析するために Telescope を使う場合でも、生産性を支援するために設計されたツールを利用しているのです。
しかし、これらのツールのほとんどは開発環境向けに最適化されています。確かに Telescope を本番環境で構成することは可能ですが、セキュリティ対策、アクセス管理、パフォーマンスへの影響への対応が必要になります。Laravel の dd() や dump() 関数は即座の可視性を提供しますが、誤った状況で使用すればデータ漏洩や実行停止を招きます。Monolog は監査証跡に不可欠な構造化ロギングを提供しますが、リアルタイムの洞察やアラート機能は備えていません。
本番環境では、リアルタイムの可視性、迅速な対応、環境やユーザーセッションをまたいだ Issues のグルーピングが求められるため、こうした制約が顕在化します。ユーザーが報告する前に不具合を検知する必要があり、そこで Sentry の優位性が際立ちます。Sentry は Laravel にシームレスに統合され、フロントエンドとバックエンドの両方にわたる豊富なコンテキストを捕捉し、エラーデータと並列して扱える構造化ログによってロギング環境を拡張します。これにより、重大度でフィルタリングしたり、プロパティを横断的に検索したり、ログをスタックトレース、ユーザー ID、リリースと関連付けたりすることが可能になります。
Original Page: Debugging and logging in Laravel applications
IchizokuはSentryと提携し、日本でSentry製品の導入支援、テクニカルサポート、ベストプラクティスの共有を行なっています。Ichizokuが提供するSentryの日本語サイトについてはこちらをご覧ください。またご導入についての相談はこちらのフォームからお気軽にお問い合わせください。