> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Laravel Telescope hands-on techniques

> Practical patterns for getting the most out of Telescope in local development. N+1 detection, tag-based tracking, custom watchers, using the Dump watcher, and know-how not covered in the official docs.

For basic installation and configuration, see the [guide page](/en/telescope). This page introduces practical local-development patterns not covered in the official docs.

Telescope is **local-development only**. Use [Laravel Pulse](/en/pulse) or [Laravel Nightwatch](/en/blog/nightwatch-introduction) for production monitoring.

***

## Systematically finding N+1 problems

Here's a practical workflow for N+1 debugging with Telescope. Rather than merely noticing "the same SELECT is being repeated," you can run through the whole cycle including post-fix verification.

```mermaid theme={null}
sequenceDiagram
    participant Browser
    participant Laravel
    participant Telescope
    participant DB

    Browser->>Laravel: GET /posts
    Laravel->>DB: SELECT * FROM posts (1 query)
    loop For each post
        Laravel->>DB: SELECT * FROM users WHERE id = ? (N queries)
    end
    Laravel-->>Browser: Response
    Laravel-->>Telescope: Record query history
    Note over Telescope: Same SELECT N times<br>tagged as slow
```

<Steps>
  <Step title="Find slow requests in Requests">
    Open `/telescope` and, on the Requests tab, identify long-running requests.
  </Step>

  <Step title="Inspect the executed SQL in Queries">
    Opening the request details shows every SQL query executed during that request. If similar SELECTs repeat, that's an N+1.
  </Step>

  <Step title="Fix with eager loading">
    Add `with()` to the code and check queries again. If the query count drops significantly, you're done.
  </Step>
</Steps>

```php theme={null}
// Code that causes N+1
$posts = Post::all();
foreach ($posts as $post) {
    echo $post->user->name; // An extra query per post
}

// Solved with eager loading
$posts = Post::with('user')->get();
```

You can complete this whole workflow in the browser without adding `dd()` calls or extra logging to your code.

***

## Tracking specific requests with tags

Telescope has a **tags** feature. Attaching arbitrary tags to entries with `Telescope::tag()` lets you quickly filter the dashboard to just entries with a tag.

This is extremely useful when you want to trace only the activity related to a specific user or order ID.

```php theme={null}
use Laravel\Telescope\IncomingEntry;
use Laravel\Telescope\Telescope;

// Override the tags method in TelescopeServiceProvider
Telescope::tag(function (IncomingEntry $entry) {
    if ($entry->type === 'request') {
        return array_filter([
            'status:' . $entry->content['response_status'],
            auth()->check() ? 'user:' . auth()->id() : null,
        ]);
    }

    return [];
});
```

Now, typing `user:42` in the Search box on `/telescope/requests` lists only requests from user 42.

### Auto-tagging models

The `tags` method on `TelescopeServiceProvider` can add a specific model ID to every entry.

```php theme={null}
// TelescopeServiceProvider
Telescope::tag(function (IncomingEntry $entry) {
    return $entry->tags();
});
```

Additionally, implementing the `HasTags` contract on a model automatically adds tags when that model is recorded.

```php theme={null}
use Laravel\Telescope\Contracts\EntriesRepository;

class Order extends Model implements \Laravel\Telescope\Contracts\HasTags
{
    public function telescopeTags(): array
    {
        return ['order:' . $this->id];
    }
}
```

***

## Using the Dump watcher

Using `dump()` can inject output into HTML responses and make API debugging awkward. The Telescope Dump watcher separates `dump()` output from the browser response and records it in the dashboard.

Usage is simple: open the "Dump" tab in `/telescope` and then call `dump()`.

```php theme={null}
// Controller
public function index()
{
    $users = User::with('posts')->get();
    dump($users->first()->toArray()); // Appears in Telescope's dump tab
    return response()->json($users);
}
```

It's captured only while the page is open, so you only monitor when you need to. Unlike `dd()`, it doesn't halt execution, which is handy when debugging across a stream of consecutive requests.

***

## Comfortable email debugging with Mailpit integration

Combining the Mail watcher with the local SMTP server [Mailpit](https://mailpit.axllent.org/) dramatically improves email development.

```ini theme={null}
# .env
MAIL_MAILER=smtp
MAIL_HOST=127.0.0.1
MAIL_PORT=1025
```

Telescope's Mail tab lets you preview both HTML and text of sent emails. In Mailpit you can view received emails in the browser and also check attachments and spam scores.

<Tip>
  To avoid accidentally sending emails externally during testing, always use a local SMTP such as Mailpit or MailHog during local development.
</Tip>

***

## Debugging events and listeners

Debugging event-driven code is often tricky. Chasing "is the event firing?" and "which listeners run?" through logs is tedious.

Telescope's Events watcher lists dispatched events together with their listeners.

If a listener isn't firing, check the event entry on the Events tab.

* Event is dispatched but no listeners appear → the listener isn't registered (check `EventServiceProvider`)
* The event isn't dispatched at all → check where `event()` is called

```php theme={null}
// A local verification flow instead of writing a test
event(new OrderShipped($order));
// → Check that OrderShipped appears on /telescope/events
// → Check that the listener SendShippingConfirmation is invoked
```

***

## Debugging queued jobs

Debugging async processing purely from logs makes it hard to pin down issues. Telescope's Jobs watcher records everything from dispatch to execution result.

Clicking a failed job entry shows the stack trace and exception message. You can inspect failures in Telescope in addition to the `queue:failed` table, so you can identify the root cause quickly.

```php theme={null}
// While debugging jobs, running synchronously with the sync driver is easier to trace
// .env
QUEUE_CONNECTION=sync
```

With the sync driver, the job runs synchronously within the request, and job execution results appear in the Requests watcher too.

***

## Debugging the HTTP client

When debugging communication with external APIs, the HTTP Client Watcher is useful. Requests made with the `Http::` facade and their responses are recorded.

```php theme={null}
$response = Http::get('https://api.example.com/users');
// → View it on /telescope/client-requests
```

Response body, status code, and duration are visible at a glance. You can inspect the response in the dashboard without writing `dd($response->json())`.

***

## Summary

| Technique           | Benefit                                                 |
| ------------------- | ------------------------------------------------------- |
| N+1 workflow        | Systematically find and fix query issues without `dd()` |
| Tagging             | Filter recordings for a specific user or model quickly  |
| Dump watcher        | Inspect dump output without polluting API responses     |
| Mailpit integration | Comfortable local email development                     |
| Events watcher      | Visualize event and listener firing                     |
| Jobs + sync         | Debug async processing by running it synchronously      |
| HTTP client         | Record and inspect external API communication           |

<Columns cols={2}>
  <Card title="Laravel Telescope guide" icon="telescope" href="/en/telescope">
    See the guide page for installation and detailed watcher settings.
  </Card>

  <Card title="Laravel Nightwatch" icon="moon" href="/en/blog/nightwatch-introduction">
    Monitor production with Nightwatch.
  </Card>
</Columns>


## Related topics

- [Getting started with Laravel Nightwatch](/en/blog/nightwatch-introduction.md)
- [Laravel Telescope](/en/telescope.md)
- [Search](/en/search.md)
- [BlueskyManager and HasShortHand](/en/packages/laravel-bluesky/bluesky-manager.md)
- [Laravel Pulse](/en/pulse.md)
