skip to content

In Laravel Telescope's config/telescope.php, how are watchers switched on and tuned, and which defaults of the log, request and model watchers surprise people?

level: middleimportance: should knowfreq 30%

answer

  1. class => bool or options array
  2. TELESCOPE_*_WATCHER env switches
  3. log watcher level defaults to error
  4. request size_limit 64 KB
  5. ignore_paths and ignore_commands

basics

~20 s

Each watcher is a class key in the watchers array, set to a boolean or to an options array with enabled. Surprising defaults: the log watcher records only error and above, and the request watcher keeps at most 64 KB of response.

solid answer

~40 s

`config/telescope.php` has a `watchers` array keyed by watcher class. A simple watcher maps to a boolean (`Watchers\JobWatcher::class => env('TELESCOPE_JOB_WATCHER', true)`); a configurable one maps to an array with `enabled` and options. All eighteen watchers ship enabled. The defaults people trip on: the **log watcher**'s `level` is `error`, so `Log::info()` lines never show until you lower it; the **request watcher** keeps at most `size_limit` 64 KB of response and can skip `ignore_status_codes` or `ignore_http_methods`; the **model watcher** records `eloquent.*` events with `hydrations` on; the **dump watcher** captures `dump()` only while its dashboard screen is open unless `always` is true. Global `ignore_paths` (Livewire, Pulse and others by default), `only_paths` and `ignore_commands` limit what is recorded at all.

code

php · 25 lines
php
<?php

// config/telescope.php (excerpt)
use Laravel\Telescope\Watchers;

return [
    'ignore_paths' => ['livewire*', 'pulse*', 'health'],

    'watchers' => [
        Watchers\LogWatcher::class => [
            'enabled' => env('TELESCOPE_LOG_WATCHER', true),
            'level' => 'debug',          // default is 'error'
        ],
        Watchers\RequestWatcher::class => [
            'enabled' => env('TELESCOPE_REQUEST_WATCHER', true),
            'size_limit' => 64,          // KB of response kept
            'ignore_http_methods' => ['options'],
            'ignore_status_codes' => [],
        ],
        Watchers\EventWatcher::class => [
            'enabled' => env('TELESCOPE_EVENT_WATCHER', false),
            'ignore' => [],
        ],
    ],
];

go deeper

for a junior

Know that config/telescope.php lists watchers you can turn on or off, and that each has an environment variable switch.

for a middle

Explain boolean versus array watcher entries and the key options: log level, request size_limit, model events and hydrations, slow threshold.

for a senior

Tune watchers and ignore rules to control noise, storage and data exposure, and move Telescope storage to its own connection when needed.

for a principal

Set the rules for which data a recording tool may capture in each environment, and review them as new watchers and packages arrive.

## How watchers are declared A **watcher** is a class that listens for framework events and turns them into Telescope entries. `config/telescope.php` lists them in `watchers`, keyed by class: ```php 'watchers' => [ Watchers\JobWatcher::class => env('TELESCOPE_JOB_WATCHER', true), Watchers\LogWatcher::class => [ 'enabled' => env('TELESCOPE_LOG_WATCHER', true), 'level' => 'error', ], ], ``` - A **boolean** value simply turns the watcher on or off. - An **array** value needs `enabled` and adds watcher-specific options. - Every watcher reads an environment variable named `TELESCOPE_<NAME>_WATCHER`, so you can switch one off per environment without editing the file. The published config enables all eighteen: batch, cache, client request, command, dump, event, exception, gate, job, log, mail, model, notification, query, redis, request, schedule and view. ## Options worth knowing | Watcher | Option (default) | Effect | |---|---|---| | Log | `level` (`error`) | only `error`, `critical`, `alert`, `emergency` entries are recorded | | Request | `size_limit` (64) | response bodies over 64 KB are not stored in full | | Request | `ignore_http_methods`, `ignore_status_codes` (empty) | skip, for example, `OPTIONS` requests or 404s | | Model | `events` (`eloquent.*`), `hydrations` (true) | which model events are recorded; count of models loaded | | Query | `slow` (100), `ignore_packages` (true) | slow tag threshold in ms; skip vendor frames as caller | | Cache | `hidden`, `ignore` (empty) | mask values of listed keys, or skip keys | | Gate | `ignore_abilities`, `ignore_packages` (true) | skip listed abilities or checks from packages | | Command | `ignore` (empty) | commands not to record | | Dump | `always` (false) | capture dumps even when the dump screen is closed | | Client request | `ignore_hosts` (empty) | outgoing HTTP calls to skip | The log watcher default is the one most people meet first: with the published config, `Log::info('Order synced')` never appears in Telescope. Set `'level' => 'debug'` locally to see everything. ## Global scope options Outside the watchers array, a few keys decide whether recording starts at all: 1. **`enabled`** (`TELESCOPE_ENABLED`, true): when false, nothing is registered or recorded. 2. **`ignore_paths`**: request paths never recorded; defaults include `livewire*`, `nova-api*`, `pulse*`, `_boost*` and `.well-known*`. Telescope's own path is also excluded. 3. **`only_paths`**: when non-empty, only matching paths are recorded, for example `api/*`. 4. **`ignore_commands`**: Artisan commands never recorded; Telescope already skips `queue:work`, `queue:listen`, Horizon's commands and some migration commands. 5. **`path`** and **`domain`**: where the dashboard lives. 6. **`driver`** (`database`) and `storage.database.connection`: where entries are written; pointing Telescope at a separate connection keeps its writes off the main database. ## Environment-specific tuning Because every switch reads the environment, one config file can serve every machine: ```ini # local .env: see everything TELESCOPE_ENABLED=true # test runs: the skeleton's phpunit.xml already sets this TELESCOPE_ENABLED=false # a shared environment: quieter watchers TELESCOPE_EVENT_WATCHER=false TELESCOPE_MODEL_WATCHER=false TELESCOPE_CACHE_WATCHER=false ``` Options without an environment variable, such as the log `level`, can be wrapped in `env()` in the config file if they need to differ per machine. ## Choosing watchers deliberately - Locally, the defaults are fine; lower the log level and the slow threshold if they help. - Turn off watchers that are pure noise for your app, for example `TELESCOPE_EVENT_WATCHER=false` when framework events flood the list, or `TELESCOPE_MODEL_WATCHER=false` for bulk imports. - On any shared environment, each enabled watcher is both storage cost and potential exposure: cache values, request bodies, sessions, mail content and SQL with bindings all end up in `telescope_entries`. ## Why interviewers ask A candidate who has only clicked around the dashboard knows the screens. One who has configured it knows why an expected log line is missing, why a large response is truncated, and how to keep Telescope from recording its own or Livewire's traffic.

  • Log::info() calls never show up in Telescope, but exceptions do. What do you change?
    The log watcher's `level` option defaults to `error`, so lower-level entries are ignored. Set `'level' => 'debug'` (or `info`) on `Watchers\LogWatcher::class` in `config/telescope.php`. Exceptions still appear because the exception watcher records them separately.
  • How do you stop Telescope recording a health-check endpoint that a load balancer hits every few seconds?
    Add its path to `ignore_paths` in `config/telescope.php`, for example `'health'`. Requests matching an ignored path never start recording, so neither the request nor its queries are stored. `only_paths` is the inverse, for recording just one area such as `api/*`.

saying these in an interview costs you the question

  • Telescope's log watcher records every level by default.
  • Watchers must be registered manually in the service provider.
  • Disabling one watcher requires editing and redeploying config/telescope.php.
  • The request watcher stores full responses of any size.
  • ignore_paths also hides those requests' queries only from the dashboard, not storage.