VOOZH about

URL: https://deepwiki.com/hypervel/telescope/7-extension-and-customization

⇱ Extension and Customization | hypervel/telescope | DeepWiki


Loading...
Last indexed: 7 February 2026 (146f77)
Menu

Extension and Customization

This document provides guidance for extending Telescope with custom functionality. It covers the primary extension points including custom watchers, entry filters, tags, lifecycle hooks, custom entry types, privacy controls, and storage drivers.

For information about configuring existing watchers, see Watcher Configuration. For details on the built-in watcher implementations, see Watchers System.

Extension Points Overview

Telescope provides multiple extension points that allow you to customize its behavior without modifying core code. The following diagram illustrates the primary extension mechanisms and where they hook into the recording lifecycle:


Sources: src/Telescope.php49-76 src/Telescope.php275-319 src/Telescope.php529-574 src/Telescope.php579-637


Creating Custom Watchers

Custom watchers allow you to monitor application events that are not covered by Telescope's built-in watchers. A watcher observes specific events and records them as Telescope entries.

Watcher Structure

All watchers extend the Watcher base class and implement a register() method that sets up event listeners. The following diagram shows the structure and lifecycle of a custom watcher:


Sources: src/Telescope.php123-135 src/Watchers/CacheWatcher.php18-40 src/TelescopeServiceProvider.php35-36

Implementation Steps

Step 1: Create Watcher Class

Create a new watcher class that extends Watcher:


Key Methods:

  • register(ContainerInterface $app) - Set up event listeners (required)
  • recordEvent($event) - Extract data and record the entry
  • Check Telescope::isRecording() before recording (prevents infinite loops)
  • Use IncomingEntry::make(array) to create entries
  • Call appropriate Telescope::record*() method to record the entry

Sources: src/Watchers/CacheWatcher.php28-40 src/Watchers/CacheWatcher.php59-85

Step 2: Register in Configuration

Add your watcher to the watchers array in config/telescope.php:

Configuration FormatDescription
CustomWatcher::class => trueSimple enable/disable
CustomWatcher::class => env('CUSTOM_WATCHER', true)Environment-controlled
CustomWatcher::class => ['enabled' => true, 'option' => 'value']With options

Example configuration:


Sources: config/telescope.php147-221

Step 3: Access Configuration Options

The watcher receives its configuration options through the $options property:


Sources: src/Watchers/CacheWatcher.php134-138

Example: CacheWatcher Analysis

The CacheWatcher provides a complete example of watcher implementation:


Key patterns demonstrated:

Sources: src/Watchers/CacheWatcher.php18-156

Custom Entry Types

If you need to record a new type of entry (beyond the built-in types like REQUEST, QUERY, CACHE, etc.), you can extend the EntryType constants and add a corresponding recording method:

  1. Define your custom type constant:

  1. Add a recording method to Telescope via extension (or use existing recordEvent()):

  1. Use in your watcher:

Sources: src/Telescope.php354-493


Filtering Entries

Telescope provides two levels of filtering: individual entry filtering and batch filtering. Filters determine which entries are recorded and stored.

Entry-Level Filters

Entry-level filters are applied immediately when an entry is recorded, before it is added to the queue. These filters receive an IncomingEntry object and return a boolean indicating whether to record the entry.


Sources: src/Telescope.php306-316

Adding Entry Filters

Register filters in your application's service provider (typically AppServiceProvider or TelescopeServiceProvider):


Filter execution: All filters must return true for the entry to be recorded. If any filter returns false, the entry is dropped.

Available methods on IncomingEntry:

  • isRequest(), isCommand(), isQuery(), isException(), etc. - Type checking src/IncomingEntry.php
  • hasTag($tag) - Check for specific tag
  • content property - Access entry data
  • type property - Access entry type string

Sources: src/Telescope.php529-534 src/Telescope.php49-56 src/Telescope.php306-316

Batch-Level Filters

Batch-level filters are applied when storing entries to the database. They receive a Collection of all entries in the current batch and return a boolean indicating whether to store the entire batch.


Sources: src/Telescope.php596-636

Adding Batch Filters

Register batch filters in your service provider:


Use cases for batch filters:

  • Drop entire request cycles that match criteria
  • Prevent recording in specific scenarios
  • Apply rate limiting (e.g., only record every Nth batch)
  • Conditional recording based on batch composition

Sources: src/Telescope.php539-544 src/Telescope.php54-56 src/Telescope.php599-601


Custom Tags

Tags provide a way to categorize and filter entries. Custom tags can be added to all entries through tag callbacks, allowing you to add metadata like user roles, tenant IDs, or feature flags.

Adding Tag Callbacks


Sources: src/Telescope.php302-304 src/Telescope.php569-574 src/Telescope.php74-75

Register tag callbacks in your service provider:


Tag callback return value: Each callback must return an array of strings. Tags are merged from all callbacks using Arr::collapse().

Tag naming conventions:

  • Use category:value format for structured tags (e.g., role:admin, tenant:123)
  • Use simple strings for boolean tags (e.g., slow-request, authenticated)
  • Keep tags lowercase and use hyphens for multi-word tags

Sources: src/Telescope.php302-304

Using Tags for Filtering

Tags added via tag callbacks are available in the entry's tags() array and can be used in filters:


Tags are also stored in the telescope_entries_tags table and can be queried through the web interface for filtering displayed entries.

Sources: src/Telescope.php302-304


Lifecycle Hooks

Telescope provides hooks that execute at specific points in the recording lifecycle, allowing you to perform additional actions when entries are recorded or stored.

Hook Execution Flow


Sources: src/Telescope.php313-315 src/Telescope.php627 src/Telescope.php59-68

After Recording Hook

The afterRecording hook executes immediately after an entry is added to the queue. This hook receives the Telescope instance and the IncomingEntry that was just recorded.

Use cases:

  • Real-time notifications
  • Logging to external systems
  • Triggering webhooks
  • Incremental counters

Example registration:


Important notes:

  • Only one afterRecording hook can be registered (subsequent calls replace the previous hook)
  • Hook executes within Telescope::withoutRecording() to prevent infinite loops
  • Keep hook logic lightweight to avoid slowing down request processing

Sources: src/Telescope.php549-554 src/Telescope.php313-315 src/Telescope.php61

After Storing Hooks

The afterStoring hooks execute after entries have been successfully stored to the database. These hooks receive the array of entries and the batch ID.

Use cases:

  • Data aggregation
  • External system synchronization
  • Batch processing
  • Analytics updates

Example registration:


Important notes:

  • Multiple afterStoring hooks are supported (all are executed)
  • Hooks execute within Telescope::withoutRecording() to prevent infinite loops
  • Hooks are called even if TerminableRepository::terminate() is invoked
  • Any exceptions in hooks are caught and reported via the exception handler

Sources: src/Telescope.php559-564 src/Telescope.php627 src/Telescope.php66-68


Privacy Controls

Telescope provides methods to hide sensitive data from being recorded. These controls apply globally to all entries.

Hiding Sensitive Data


Sources: src/Telescope.php673-707 src/Telescope.php78-96

Hiding Request Headers

Add header names to be redacted from request entries:


Default hidden headers:

  • authorization
  • php-auth-pw

Headers matching these names will be replaced with ******** in recorded entries.

Sources: src/Telescope.php673-681 src/Telescope.php78-83

Hiding Request Parameters

Add parameter names to be redacted from request payloads:


Default hidden parameters:

  • password
  • password_confirmation

Parameters are redacted from:

  • Query string parameters
  • POST body parameters
  • JSON request payloads

Sources: src/Telescope.php686-694 src/Telescope.php85-91

Hiding Response Parameters

Add parameter names to be redacted from response data:


Response parameters are redacted from:

  • JSON responses
  • Response body content

Sources: src/Telescope.php699-707 src/Telescope.php93-96

Watcher-Specific Privacy

Individual watchers can implement their own privacy controls. For example, CacheWatcher supports hiding specific cache keys:


When a cache key matches these patterns, its value is replaced with ********.

Sources: src/Watchers/CacheWatcher.php132-138 config/telescope.php150-153


Custom Storage Drivers

Telescope uses a repository pattern for storage, allowing you to implement custom storage backends beyond the default database driver.

Storage Architecture


Sources: src/TelescopeServiceProvider.php151-179 src/Storage/DatabaseEntriesRepository.php

Creating a Custom Repository

Step 1: Implement Repository Interface

Create a class that implements EntriesRepository:


Required methods:

  • store(Collection $entries): void - Store new entries
  • update(Collection $updates): ?Collection - Update existing entries, return pending updates
  • Optional: Implement ClearableRepository, PrunableRepository, TerminableRepository

Sources: src/Contracts/EntriesRepository.php src/Storage/DatabaseEntriesRepository.php

Step 2: Register Custom Driver

In your TelescopeServiceProvider (or a custom service provider), register the driver:


Sources: src/TelescopeServiceProvider.php151-179

Step 3: Configure Storage Driver

Update config/telescope.php to use your custom driver:


Driver selection: The TelescopeServiceProvider looks for a method named register{Driver}Driver() where {Driver} is the ucfirst version of the driver name.

Sources: src/TelescopeServiceProvider.php151-158 config/telescope.php61-68

Repository Method Details

MethodRequiredReturnPurpose
store(Collection $entries)YesvoidStore new entries in storage
update(Collection $updates)Yes?CollectionUpdate existing entries, return pending updates
find(string $id)No?EntryResultFind single entry by UUID
get(...)NoCollectionQuery entries with filters
clear()For ClearableRepositoryvoidDelete all entries
prune(DateTimeInterface $before)For PrunableRepositoryintDelete old entries
terminate()For TerminableRepositoryvoidCleanup after storage

The update() method can return a Collection of EntryUpdate objects that couldn't be immediately applied. These will be queued via the ProcessPendingUpdates job for later processing.

Sources: src/Telescope.php608-621 src/Contracts/EntriesRepository.php


Authorization Customization

Telescope includes an authorization system that controls access to the web interface. You can customize this authorization logic.

Default Authorization

The default authorization uses Laravel's Gate system. In your AuthServiceProvider or TelescopeServiceProvider, define a viewTelescope gate:


Sources: src/Http/Middleware/Authorize.php src/AuthorizesRequests.php

Custom Authorization Middleware

To implement completely custom authorization logic, you can replace the default Authorize middleware:

  1. Create a custom middleware:

  1. Update config/telescope.php to use your middleware:

Sources: config/telescope.php110-113


Complete Extension Example

The following example demonstrates multiple extension techniques working together:


This example shows how the various extension points can be combined to:

  • Add contextual tags for filtering
  • Filter unwanted entries
  • Send critical events to external systems
  • Maintain statistics
  • Protect sensitive data

Sources: src/Telescope.php529-707 src/TelescopeServiceProvider.php23-48

Refresh this wiki

On this page