Laravel Telescopeで開発中のデバッグとモニタリングを効率化する方法

Laravel Telescopeで開発中のデバッグとモニタリングを効率化する方法

Laravel Telescopeは、リクエスト、例外、ログ、DBクエリ、ジョブ、メール、通知、キャッシュ操作、スケジュール実行などを一元的に確認できる開発支援ツール。dd() やログ出力だけでは追い切れない「どのリクエストで」「どのSQLが」「どのジョブが」「どの例外で」問題になったのかを、時系列でまとめて確認できる。開発中の不具合切り分け、性能劣化の初期発見、想定外の副作用の可視化に強く、特に複数人で開発するLaravel案件では、デバッグの再現性を上げやすい。

Telescopeが向いている場面

Telescopeが特に有効なのは、以下のような状況。
・フォーム送信後にどこで失敗しているのか分からない
・APIレスポンスが遅いが、DBなのか外部通信なのか切り分けたい
・キューに積んだジョブが動かない、もしくは失敗している
・通知、メール、イベント、キャッシュの動作確認をまとめて見たい
・「開発環境では再現するが、ログだけでは情報が足りない」ケース
逆に、本番運用の主監視ツールとして使うというより、開発・検証中の観測強化に向いている。

インストールと初期セットアップ

まずはパッケージを追加し、インストールコマンドとマイグレーションを実行する。

composer require laravel/telescope

php artisan telescope:install
php artisan migrate

その後、通常は /telescope でダッシュボードにアクセスできる。
エラー発生条件として多いのは、マイグレーション未実行、DB接続エラー、APP_ENV や provider 登録が想定と違って Telescope が有効化されていないケース。

ローカル専用で使う構成

Telescopeは本番常時有効より、まずローカル専用に寄せる方が安全。ローカル限定にしたい場合は開発依存として入れ、アプリ起動時に local 環境だけ登録する構成にすると扱いやすい。

composer require laravel/telescope --dev

// app/Providers/AppServiceProvider.php(例)
public function register(): void
{
    if ($this->app->environment('local') && class_exists(\Laravel\Telescope\TelescopeServiceProvider::class)) {
        $this->app->register(\Laravel\Telescope\TelescopeServiceProvider::class);
        $this->app->register(\App\Providers\TelescopeServiceProvider::class);
    }
}

発生しやすい問題は、--dev で入れたのに provider 側の制御が無く、環境によって読まれたり読まれなかったりする状態。

まず見るべき画面:Requests・Exceptions・Queries

Telescopeを入れた直後に優先的に使うのは、Requests、Exceptions、Queries の3つ。
・Requests:どのURLに、どのヘッダ・入力・レスポンスが返ったか
・Exceptions:どの例外が、どのリクエストで発生したか
・Queries:どのSQLが、何msかかって実行されたか
この3つだけでも、フォーム送信失敗、API 500、一覧遅延の原因特定がかなり速くなる。

Request Watcher:入力とレスポンスのズレを確認する

Request Watcherでは、リクエストURL、メソッド、ヘッダ、入力値、セッション、レスポンス内容などを確認できる。
例えば「フロントから正しい値を送ったつもりなのにバリデーションで落ちる」ケースでは、ここを見ると入力名のズレやJSON構造の違いがすぐ分かる。
エラー発生条件として多いのは、巨大レスポンスを記録しすぎて確認しづらくなること。必要に応じてレスポンスサイズ上限を調整する。

// config/telescope.php(例)
'watchers' => [
    \Laravel\Telescope\Watchers\RequestWatcher::class => [
        'enabled' => env('TELESCOPE_REQUEST_WATCHER', true),
        'size_limit' => env('TELESCOPE_RESPONSE_SIZE_LIMIT', 64),
    ],
],

Query Watcher:遅いSQLとN+1の発見

一覧画面やAPIの遅延原因として多いのが、重いクエリやN+1。TelescopeのQuery Watcherでは、SQL本文、バインド値、実行時間が見えるため、「何が遅いのか」をSQL単位で把握しやすい。
例えば、ループの中で関連モデルへアクセスしてしまい、同じようなSQLが大量に並んでいれば、N+1の可能性が高い。
遅いクエリ判定の閾値も調整できる。

// config/telescope.php(例)
'watchers' => [
    \Laravel\Telescope\Watchers\QueryWatcher::class => [
        'enabled' => env('TELESCOPE_QUERY_WATCHER', true),
        'slow' => 50,
    ],
],

発生しやすい問題は、開発中に select * や不要な eager load を多用し、一覧が遅いのに気づかず進んでしまうこと。

Exception Watcher:例外の入口をRequestと結びつける

Exception Watcherは、例外メッセージだけでなく「どのリクエスト文脈で発生したか」を追いやすいのが強い。
通常のログだけだと、例外とリクエストの関係が見えにくいが、Telescopeではリクエスト履歴と組み合わせて確認しやすい。
特に、認証切れ、権限不足、Null参照、SQL例外、外部APIエラーのような“種類の違う失敗”が混ざる画面では役に立つ。

Job Watcher:キュー投入・実行・失敗の流れを見る

メール送信、通知、CSV生成、外部連携などをジョブキューで処理している場合、Job Watcherが重要になる。
・ジョブがちゃんと dispatch されたか
・どのキューに入ったか
・完了したか、失敗したか
・どのジョブが多く滞留しているか
を確認できる。
発生条件として多いのは、ジョブ自体は投入されているのにワーカー未起動で処理されないケース、もしくは同じジョブが失敗を繰り返しているケース。

Log Watcher:logger() の出力を時系列で追う

TelescopeのLog Watcherを使うと、logger()->info()logger()->error() で出した内容が、リクエスト単位でまとめて追いやすくなる。
ログファイルを grep するよりも、Telescope内でそのリクエストに関係するログだけを見られるのが利点。
デバッグ中はログレベルを下げて詳細を拾うこともできる。

// config/telescope.php(例)
'watchers' => [
    \Laravel\Telescope\Watchers\LogWatcher::class => [
        'enabled' => env('TELESCOPE_LOG_WATCHER', true),
        'level' => 'debug',
    ],
],

ただし、debugレベルを広く取りすぎるとノイズが増えるため、開発中だけに限定する方が扱いやすい。

Mail・Notification Watcher:送信内容の確認に使う

開発中は、メールや通知が「送られたか」だけでなく、「どんな本文・どんな宛先で送られたか」を確認したいことが多い。
Mail Watcherでは、送信されたメールをブラウザ上でプレビューできるため、Mailhogや実メール送信に頼らず確認しやすい。
Notification Watcherも、どの通知が、どのチャネルで送られたかを追える。

発生しやすい問題は、メール送信自体は通っているのに、本文データが想定と違うケース。Telescopeなら本文確認まで一気にできる。

Model Watcher:Eloquentの変更を追う

Model Watcherを有効にすると、createdupdated などのEloquentイベントに応じて、どのモデルがどう変わったかを確認できる。
例えば「保存されたはずなのにDBに反映されていない」「意図しない更新が起きた」というとき、モデルイベントベースで追いやすい。
記録対象イベントは絞れるため、ノイズを減らしながら使うのが実務向き。

// config/telescope.php(例)
'watchers' => [
    \Laravel\Telescope\Watchers\ModelWatcher::class => [
        'enabled' => env('TELESCOPE_MODEL_WATCHER', true),
        'events' => ['eloquent.created*', 'eloquent.updated*'],
        'hydrations' => true,
    ],
],

Filter機能:残すべき情報だけを絞り込む

開発が進むと、全リクエスト・全ログ・全ジョブを記録するとノイズが増える。Telescopeにはフィルタの仕組みがあり、「例外があるものだけ」「遅いクエリを含むものだけ」など、価値の高い情報だけを残す運用ができる。
これを使わずに何でも保存すると、DBの telescope_entries がすぐ肥大化する。

Data Pruning:データ肥大化を防ぐ

Telescopeは内部テーブルに情報を蓄積するため、放置するとレコード数が急増する。公式でも prune コマンドの定期実行が推奨されている。
ローカルだけなら気にしなくて済むこともあるが、共有の検証環境で使うなら必須。

// スケジュール定義の例
use Illuminate\Support\Facades\Schedule;

Schedule::command('telescope:prune')->daily();

発生条件として多いのは、「便利だから」と staging で長期間有効にした結果、telescope_entries が膨らみ、逆に確認しにくくなること。

本番で使うかどうかの判断

Telescopeは本番監視ツールというより、開発・検証中の観測支援に向く。
本番で常時フル有効にすると、情報量と負荷が増えやすい。
もし本番で使うなら、
・認可を強く制限する
・watcherを必要最低限に絞る
・保存対象も限定する
・短期間だけ有効化する
といった運用が前提になる。

よくあるエラーと原因

/telescope が404
発生条件:インストール未完了、provider未登録、ローカル限定設定で local 以外を見ている
・Telescope画面は出るがデータが無い
発生条件:watcher無効、設定キャッシュが古い、リクエスト自体が想定環境で流れていない
・DBエラーでTelescope自体が動かない
発生条件:マイグレーション未実行、接続先不整合、権限不足
・重すぎる
発生条件:watcherを全部有効、debugログ大量、Request/Responseサイズが大きすぎる

まとめ:Telescopeを開発効率に直結させる使い方

・まずは Requests、Exceptions、Queries の3つを主力にする
・ジョブ、メール、通知、モデル変更は必要な画面だけ深掘りする
・Log Watcherは debug にしすぎず、開発中だけ絞って使う
・フィルタと prune を入れて、情報量を制御する
・本番常用より、ローカル/検証環境での観測強化ツールとして使う