Laravel Telescopeの使い方|インストール・設定・本番運用の判断基準
Laravel Telescopeは、リクエスト・SQL・キュー・例外・メールといったアプリ内部の出来事をブラウザ上で追えるLaravel公式のデバッグ支援パッケージです。導入自体はコマンド3行で終わりますが、そのまま本番に置くと、APP_ENV の設定次第でダッシュボードが誰でも開ける状態になり、記録条件を詰めなければ telescope_entries テーブルも膨らみます。この記事では最新版の対応バージョン、インストール手順、config/telescope.php で最初に触るべき設定、そして本番で使う場合の最低条件までを、公式ドキュメントとパッケージのソースで確認した値だけで整理します。公式ドキュメントの記述が5系の実装と食い違っている箇所も、実装側を正として示します。
まとめ
- Telescopeの最新版は5.22.0(2026年7月29日リリース)。Laravel 8.37〜13、PHP 8.0以上に対応します。
- 導入は
composer require laravel/telescope、php artisan telescope:install、php artisan migrateの3コマンドで、ダッシュボードは/telescopeに出ます。 - ローカル専用にするなら
--devで入れ、Laravel 11以降はbootstrap/providers.phpから TelescopeServiceProvider の登録を外して AppServiceProvider 側で環境判定して登録します。 telescope:pruneは既定で24時間より古いエントリーを削除します。日次スケジュール登録は必須と考えてください。- 本番で常時記録させる用途にはPulseやメトリクス基盤を充て、Telescopeは障害調査の期間限定で開ける運用が現実的です。
Telescopeの守備範囲と対応バージョン
TelescopeはLaravel公式の「デバッグアシスタント」で、アプリが処理したリクエストの中身をあとから遡って見るためのツールです。監視対象はウォッチャーという単位で分かれており、HTTPリクエスト、SQLクエリ、キューのジョブとバッチ、スケジュールタスク、例外、ログ、メール、通知、キャッシュ、Redis、Eloquentモデルのイベント、認可ゲートの判定結果、イベントとリスナー、外部HTTPクライアント呼び出し、Artisanコマンド、ビュー、dumpまでを記録します。
Telescope 5.xが対応するLaravelとPHPの範囲
Packagistのメタデータで確認できる各系列の対応範囲は次のとおりです。5.0.0が2024年3月12日にリリースされ、Laravel 11以降のサポートは5系だけに入っています。
| Telescope | 最新版 | 対応Laravel | 必要PHP |
|---|---|---|---|
| 5.x | 5.22.0(2026-07-29) | 8.37 / 9 / 10 / 11 / 12 / 13 | 8.0以上 |
| 4.x | 4.17.6(2024-02-08) | 8.37 / 9 / 10 | 8.0以上 |
| 3.x | 3.5.1(2020-07-28) | 6 / 7 | 7.2以上 |
表のPHP要件はTelescope単体のものです。Laravel 13本体がPHP 8.3以上を要求するため、13で使うなら実質8.3以上が必要になります。Laravel本体は13が2026年3月17日にリリースされ、12のバグ修正提供は2026年8月13日で終わります。Laravel 11のセキュリティ修正は2026年3月12日に終了済みなので、11のまま運用しているプロジェクトはTelescopeの版よりも先に本体の更新計画を立てるべき状況です。Laravel 11で入った構成変更の全体像はLaravel 11で導入された主な新機能とそのメリットについて詳しく解説にまとめています。
Debugbar・Tinkerとの使い分け
同じ「デバッグ」でも役割が違います。Debugbarは表示中のページに帯を重ねて、いま返したレスポンスのクエリやビューを即座に見るものです。Telescopeは記録をデータベースに残し、あとから別画面で遡ります。したがって、画面を開いた瞬間の重さを追うならDebugbar、非同期のジョブやスケジュールタスクのように画面を持たない処理を追うならTelescopeが向きます。導入と設定はLaravel Debugbarの使い方|導入・APP_DEBUG設定・SQL確認とv4改称対応で扱っています。対話的にモデルを叩いて確かめたい場面はphp artisan tinkerの使い方|Laravel Tinkerの基本コマンドとEloquent操作のほうが早く、3つは競合しません。
インストールとダッシュボード表示までの手順
標準インストールの3コマンド
Composerで取得し、設定ファイル・マイグレーション・サービスプロバイダを公開してから migrate します。
composer require laravel/telescope
php artisan telescope:install
php artisan migrate
telescope:install が実行するのは telescope-provider・telescope-config・telescope-migrations の3タグの公開と、サービスプロバイダの登録です。migrate 後は /telescope にアクセスすればダッシュボードが開きます。パスは設定で変更でき、既定値は 'path' => env('TELESCOPE_PATH', 'telescope') です。
ローカル専用インストールとLaravel 11以降の登録先
本番のコンテナにTelescopeを含めたくない場合は --dev で開発依存として入れます。ここでLaravel 11以降とそれ以前で手順が分岐します。Laravel 11でサービスプロバイダの登録先が bootstrap/providers.php に移ったため、config/app.php を編集するよう書いてある古い解説記事のとおりに進めても該当箇所が見つかりません。
composer require laravel/telescope --dev
php artisan telescope:install
php artisan migrate
telescope:install が bootstrap/providers.php に追記した TelescopeServiceProvider の行を削除し、代わりに App\Providers\AppServiceProvider の register() で環境を見て登録します。公式ドキュメントが示すコードは次のとおりで、パッケージ本体のプロバイダとアプリ側のプロバイダの2つを登録します。
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(TelescopeServiceProvider::class);
}
}
あわせて composer.json でパッケージの自動検出を止めます。これを忘れると --dev で入れた意味が薄れます。
"extra": {
"laravel": {
"dont-discover": [
"laravel/telescope"
]
}
},
この手順を踏んだあとに /telescope が404になる場合、原因はほぼ AppServiceProvider への登録漏れです。自動検出を止めた時点でパッケージのルートは読み込まれなくなるため、上のコードを入れるまでダッシュボードは存在しません。
config/telescope.phpで最初に決める設定
マスタースイッチ・パス・保存先
公開された設定ファイルの先頭から順に並ぶ4つが、事故を防ぐうえで最初に確認すべき項目です。
| キー | 既定値 | 役割 |
|---|---|---|
| enabled | env('TELESCOPE_ENABLED', true) |
全ウォッチャーの一括停止 |
| domain | env('TELESCOPE_DOMAIN') |
サブドメインに逃がす場合に指定 |
| path | env('TELESCOPE_PATH', 'telescope') |
ダッシュボードのURI |
| driver | env('TELESCOPE_DRIVER', 'database') |
保存先ドライバ |
storage.database.connection は既定で env('DB_CONNECTION', 'mysql') を見るため、何もしなければアプリ本体と同じDBにログが積まれます。Telescopeのテーブルだけ別接続に逃がしたいときはここを専用のコネクション名に変えます。書き込みは chunk が1000件単位です。
ウォッチャーの取捨選択と閾値
watchers 配列はすべて環境変数で個別に切り替えられます。負荷と情報量のバランスを決めるのは、真偽値ではなく閾値を持つ次の3つです。
Watchers\QueryWatcher::class => [
'enabled' => env('TELESCOPE_QUERY_WATCHER', true),
'ignore_packages' => true,
'ignore_paths' => [],
'slow' => 100,
],
Watchers\LogWatcher::class => [
'enabled' => env('TELESCOPE_LOG_WATCHER', true),
'level' => 'error',
],
- QueryWatcher の
'slow' => 100… 100ミリ秒を超えたクエリに slow タグを付けます。遅延の基準を厳しく見たいなら50などに下げます。 - LogWatcher の
'level' => 'error'… 既定では error 以上しか記録しません。debug ログを見たい場合は明示的に下げる必要があります。 - RequestWatcher の
'size_limit' => env('TELESCOPE_RESPONSE_SIZE_LIMIT', 64)… 判定式はintdiv(mb_strlen($content), 1000) <= 64で、これを超えたレスポンス本文は切り詰めではなく丸ごとPurged By Telescopeに置き換わります。対象はJSONとtext/plainのレスポンスだけで、HTMLは元からHTML Responseとしか残りません。上限直下のJSONはそのまま1行に格納されるため、レスポンスが大きいAPIではこの値を下げるとエントリー1件あたりの容量を確実に削れます。
記録対象から外すパスも初期値が入っています。ignore_paths には livewire*、nova-api*、pulse*、_boost*、.well-known* が並び、他のパッケージの通信でダッシュボードが埋まらないようになっています。逆に only_paths に api/* のように書くと、その範囲だけを記録できます。
主要ウォッチャーの読み方
リクエストとクエリの追跡
Requests画面ではヘッダー・セッション・レスポンス本文が残り、そこから同一バッチのクエリへ辿れます。Queries画面には、バインド値をプレースホルダへ埋め込んだ実行SQLと実行時間が並び、閾値を超えたものに slow タグが付きます。5.22.0のQueryWatcherはバインド値を独立した項目としては保存せず('bindings' => [])、SQL文字列へ展開して記録する実装です。
ここで挙動を1つ押さえてください。一覧画面は既定で family_hash(プレースホルダのままのSQLのmd5)が同じエントリーを1行に畳みます。全件を展開するオプションを渡しているのはJobs画面だけです。そのためN+1は一覧では見つからず、Requests画面で該当リクエストを開いて同一バッチの関連エントリーを見るか、一覧の行から family_hash で絞り込んで同じSQLの実行回数を数える形になります。
ジョブ・キュー・スケジュールの監視
JobWatcherはキュー投入されたジョブのペイロードと結果を、BatchWatcherはジョブバッチの構成を記録します。ScheduleWatcherはスケジュール実行されたコマンドとその出力を残すため、cronで動くはずのタスクが動いていないという調査に使えます。キューの失敗をあとから追える点が、画面上でしか動かないデバッグツールとの決定的な違いです。
例外・ログ・メールの確認
ExceptionWatcherは報告対象の例外をスタックトレース付きで保存します。MailWatcherはブラウザ上でメールのプレビューを表示し、.eml形式でダウンロードもできるため、実際に送信せずに本文とヘッダーを検証できます。通知はNotificationWatcherが受け持ち、メール通知はMail画面にも現れます。
Artisanコマンドと日常の運用
パッケージが提供するコマンドは6つです。src/Console 配下の実装で確認できます。
| コマンド | 役割 |
|---|---|
| telescope:install | 設定・マイグレーション・プロバイダの公開 |
| telescope:publish | 設定ファイルの再公開(--force で上書き) |
| telescope:prune | 古いエントリーの削除 |
| telescope:clear | 全エントリーの削除 |
| telescope:pause | 全ウォッチャーの記録停止 |
| telescope:resume | 記録の再開 |
公式ドキュメントはアップグレード時に telescope:publish で「アセットを再公開する」と書いていますが、5.22.0のPublishCommandが実際に呼ぶのは vendor:publish --tag=telescope-config だけです。5系はCSSとJSをパッケージ内の dist から読み込んで配信する構成のため、アセット公開用のタグ自体がソースに存在しません。アップグレード後に見た目が古いままだと悩む前に、ブラウザキャッシュを疑ってください。
telescope:pruneの既定値と例外の保持
prune は既定で24時間より古いエントリーを削除します。保持期間を延ばすなら hours オプションを渡します。
use Illuminate\Support\Facades\Schedule;
Schedule::command('telescope:prune --hours=48')->daily();
この記述の置き場所もLaravelの版で分かれます。Laravel 11以降は routes/console.php に、Laravel 10以前は app/Console/Kernel.php の schedule() メソッドに書きます。サービスプロバイダの登録先と同じく、古い解説記事のとおりに Kernel.php を探しても11以降のプロジェクトには存在しません。
実装のコマンドシグネチャには、公式ドキュメントのTelescopeページには載っていない keep-exceptions オプションがあります。付けると削除クエリに type が exception 以外という条件が加わるため、「調査用に例外だけ長く残し、リクエストやクエリは短期で捨てる」運用が1コマンドで組めます。
php artisan telescope:prune --hours=6 --keep-exceptions
pauseとresumeの挙動
telescope:pause はキャッシュに telescope:pause-recording というキーを30日間書き込むことで記録を止めます。つまり停止状態はキャッシュ依存で、キャッシュをクリアすると記録が再開します。キャッシュドライバが array の環境ではプロセスをまたいで保持されないため、この方法は使えません。負荷試験や大量バッチ投入の前に一時停止し、終わったら telescope:resume を実行する、という短時間の用途に向いた仕組みです。恒久的に止めたいなら TELESCOPE_ENABLED=false を使ってください。
telescope_entriesの肥大化を止める設計
Telescopeで最初に問題になるのは性能ではなくディスクです。マイグレーションが作るテーブルは3つで、実データはすべて telescope_entries.content の longText カラムに入ります。
| テーブル | 主な列 | 役割 |
|---|---|---|
| telescope_entries | sequence / uuid / batch_id / family_hash / content | エントリー本体 |
| telescope_entries_tags | entry_uuid / tag | タグ検索用(本体へのFKでカスケード削除) |
| telescope_monitoring | tag | 監視対象タグの登録 |
リクエスト本体に加えて、クエリ1本ごと、キャッシュ操作1回ごと、モデルイベント1件ごとに1行が積まれるため、行数はアクセス数の数倍から数十倍で増えます。ModelWatcherの既定は events が eloquent.* で hydrations も true です。公式ドキュメントの例が eloquent.created* と eloquent.updated* に絞っているのに対し、実際に公開される設定ファイルのほうが広い点に注意してください。hydrations はモデルの作成件数ではなく、1リクエスト中にDBの行からインスタンス化された件数を記録する項目です。
容量は「1日のリクエスト数 × 1リクエストあたりのエントリー数 × 1エントリーの平均サイズ」で概算し、そこから prune の保持時間を逆算してください。1エントリーの上限はレスポンス本文の size_limit(既定で約64キロバイト)に規定されます。
対策は3段構えです。第一にスケジューラーへの prune 登録。第二に不要なウォッチャーを環境変数でオフにすること。第三が入口での間引きで、TelescopeServiceProvider の filter に条件を書けば、そもそも保存しません。telescope:install が生成するスタブは次の条件で、ローカル以外では「報告対象の例外・失敗リクエスト・失敗ジョブ・スケジュールタスク・監視タグ付き」だけを残します。
Telescope::filter(function (IncomingEntry $entry) use ($isLocal) {
return $isLocal ||
$entry->isReportableException() ||
$entry->isFailedRequest() ||
$entry->isFailedJob() ||
$entry->isScheduledTask() ||
$entry->hasMonitoredTag();
});
この条件にある hasMonitoredTag() は、ダッシュボードのMonitoring画面で登録したタグ(telescope_monitoring テーブルに入ります)に一致したエントリーだけを通します。特定のモデル名やユーザーIDを登録しておけば、本番でもその範囲は全エントリーが残ります。逆に監視タグを1件も登録していなければ、この条件は常に不成立です。
ここで1点注意があります。公式ドキュメントのTelescopeページのFiltering節に載っている例と、実際に生成されるスタブの条件は一致していません。ドキュメント側は isSlowQuery() を含み isFailedRequest() を含まない構成です。ドキュメントを写経する前に、手元の app/Providers/TelescopeServiceProvider.php を開いて現状の条件を確認してください。
本番環境で使う判断基準
結論から言えば、Telescopeを本番で常時稼働させる構成は勧めません。全リクエストの内容をアプリと同じDBに書き続ける設計で、可用性の観点でも保守の観点でも割に合わないためです。継続的な監視は用途の合う道具に任せ、Telescopeは障害調査のために期間を区切って開けるものと位置づけるのが実務的です。
常時の性能監視やキューの詰まり検知には、同じくLaravel公式のPulse(1.0.0が2024年4月30日、最新の1.8.0が2026年7月29日リリース)や、メトリクス基盤への集約が向きます。外形的な指標をダッシュボード化する構成はLaravelでPrometheusとGrafana監視を実装:メトリクス収集・可視化・アラート設定で解説しています。
それでも本番にTelescopeを置く必要がある場合、最低限そろえるべき条件は次の3つです。
- 認可ゲートの実装 …
app/Providers/TelescopeServiceProvider.phpの gate() にある viewTelescope の定義は初期状態で空配列です。ここを埋めない限り、local以外の環境では誰も入れません。逆に、本番のAPP_ENVが local のまま公開されていればゲートが評価されず、誰でも開けます。デプロイ環境のAPP_ENVが production になっているかを先に確認してください。 - 機微情報の除外 … スタブの hideSensitiveRequestDetails() は local では何もせず、それ以外で
_tokenパラメータと cookie・x-csrf-token・x-xsrf-token ヘッダーを隠します。認証トークンやカード番号を独自パラメータで受けているなら、Telescope::hideRequestParameters()に追記が必要です。 - 保持期間の短縮 … 本番では hours を6や12まで詰め、keep-exceptions で例外だけ残す構成が扱いやすくなります。
調査が終わって撤去する場合は、composer remove の前に telescope_entries・telescope_entries_tags・telescope_monitoring の3テーブルを落とし、プロバイダの登録と設定ファイルを削除します。テーブルを残したままパッケージだけ消すと、肥大化したデータがDBに居座り続けます。
なお、E2Eテストで再現手順を固定できる不具合なら、Telescopeで追う前にテストコードへ落とすほうが再発防止まで届きます。手順はLaravelのテスト自動化をDuskで実装する方法|インストールからCI実行までを参照してください。
よくある質問
Telescopeとは何をするツールですか?
Laravelアプリが処理したリクエスト、SQL、キューのジョブ、例外、メールなどをデータベースに記録し、ブラウザのダッシュボードから遡って確認できるようにする公式パッケージです。エラー通知サービスではないため、アラート送信の機能は持ちません。
Laravel以外のPHPプロジェクトでも使えますか?
使えません。パッケージのcomposer.jsonが laravel/framework 本体(^8.37 から ^13.0)を要求しており、素のPHPやほかのフレームワークでは動きません。同種の情報を見たい場合は別のプロファイラを検討してください。
ダッシュボードを開くと403になるのはなぜですか?
環境がlocal以外のとき、Authorizeミドルウェアが viewTelescope ゲートを評価するためです。app/Providers/TelescopeServiceProvider.php の gate() でログインユーザーを許可する条件を書いてください。初期状態の配列は空で、誰も通らない設定になっています。
キューのジョブ監視だけに使えますか?
可能です。config/telescope.php の watchers で JobWatcher と BatchWatcher 以外を false にすれば、キュー関連だけを記録できます。環境変数でも制御でき、たとえば TELESCOPE_QUERY_WATCHER=false でクエリ記録を止められます。
DebugbarとTelescopeはどちらを入れるべきですか?
画面表示のたびにその場でSQLとビューを確認したいならDebugbar、非同期処理や過去のリクエストを遡りたいならTelescopeです。両方を同じローカル環境に入れても競合しませんが、記録量が増えるぶん prune 設定は必須になります。