GitPedia

Telescope guzzle watcher

Telescope Guzzle Watcher provide a custom watcher for intercepting http requests made via guzzlehttp/guzzle php library. The package uses the on_stats request option for extracting the request/response data. The watcher intercept and log the request into the Laravel Telescope HTTP Client Watcher.

From huzaifaarain·Updated March 20, 2026·View on GitHub·

Telescope Guzzle Watcher provide a custom watcher for intercepting http requests made via [guzzlehttp/guzzle](https://github.com/guzzle/guzzle) php library. The package uses the [on_stats](https://docs.guzzlephp.org/en/stable/request-options.html#on-stats) request option for extracting the request/response data. The watcher intercept and log the request into the [Laravel Telescope](https://laravel.com/docs/telescope) [HTTP Client Watcher](https://laravel.com/docs/telescope#http-client-watcher). The project is written primarily in PHP, distributed under the MIT License license, first published in 2023. Key topics include: guzzle, http, laravel, php, telescope.

Latest release: v4.1.0
March 20, 2026View Changelog →

We Stand With Palestine, Pakistan Stand With Palestine

StandWithPalestine

Telescope Guzzle Watcher

Latest Version on Packagist
GitHub Tests Action Status
Total Downloads


Telescope Guzzle Watcher provide a custom watcher for intercepting http requests made via guzzlehttp/guzzle php library. The package uses the on_stats request option for extracting the request/response data. The watcher intercept and log the request into the Laravel Telescope HTTP Client Watcher.

Once the installation and configurations are completed, you will be able to see the request logs under telescope/client-requests

Table of Contents

Requirements

Installation

Install the package via Composer:

bash
composer require muhammadhuzaifa/telescope-guzzle-watcher

Laravel's package auto-discovery will register the service provider for you. No manual provider entry is required unless auto-discovery is disabled.

After the package is installed, publish the configuration file so that you can tweak the watcher defaults:

bash
php artisan vendor:publish --tag="telescope-guzzle-watcher-config"

The published file lives at config/telescope-guzzle-watcher.php.

How It Works

  1. Client Hijacking via the Container – The package binds GuzzleHttp\Client in the service container to a custom Guzzle Client Factory. Every time a client is resolved from the container, the factory injects an on_stats callback that forwards request and response information to Telescope.
  2. Transfer Stats Hook – Guzzle fires the on_stats callback when a request completes (successfully or not). The watcher converts the raw PSR-7 request/response objects into Laravel's Illuminate\Http\Client\Request and Response wrappers so that Telescope can index the payload.
  3. Telescope Recording – When Telescope is actively recording, the watcher forwards each HTTP transfer to the client-requests panel, applying configuration such as tag extraction, payload truncation, and header redaction.

Because the watcher is a first-class Telescope watcher, it benefits from all Telescope filters, tags, and search capabilities right out of the box.

Configuration Reference

The configuration file ships with the following options:

KeyTypeDefaultDescription
except_request_headersarray<string>[]Header names (case-insensitive) that should be hidden from Telescope for outgoing requests. Useful for API keys or authorization tokens.
except_response_headersarray<string>[]Header names that should be hidden from Telescope responses.
enable_uri_tagsbooltrueWhen true, the watcher will explode the request URI into segments and push them as Telescope tags (host, followed by each non-empty path segment).
exclude_words_from_uri_tagsarray<string>[]List of words that should be excluded from the tag list after it is generated. Matching is case-insensitive.
size_limit`intnull`null

Tweak these settings in config/telescope-guzzle-watcher.php and cache your configuration if your deployment workflow requires it (php artisan config:cache).

Registering the Watcher

Tell Telescope to use this watcher by updating your config/telescope.php file:

php
// config/telescope.php return [ 'watchers' => [ // ... other watchers ... \MuhammadHuzaifa\TelescopeGuzzleWatcher\Watchers\TelescopeGuzzleWatcher::class => true, ], ];

Set the value to true to enable it or to a configuration array if you want to supply watcher-specific options in-line (for example, to disable it per-environment using a closure).

Resolving Guzzle Clients

For the watcher to intercept traffic you must resolve Guzzle clients through Laravel's service container:

php
// Correct – the factory will wire up on_stats and Telescope logging $client = app(\GuzzleHttp\Client::class); // Optional custom configuration $client = app(\GuzzleHttp\Client::class, [ 'config' => [ 'base_uri' => 'https://api.example.com', 'timeout' => 5, ], ]); // Avoid instantiating Guzzle manually if you want Telescope coverage $client = new \GuzzleHttp\Client(); // no Telescope logging

If you already provide an on_stats callback, the factory will wrap it so both Telescope and your callback execute.

Using Multiple Clients

The watcher supports any number of clients or middleware stacks as long as they are resolved through the container. A few patterns you may find useful:

  • Per-service bindings:

    php
    $this->app->bind('billing-client', function () { return app(\GuzzleHttp\Client::class, [ 'config' => [ 'base_uri' => config('services.billing.url'), 'headers' => ['Accept' => 'application/json'], ], ]); });
  • Custom middleware: resolve the client as normal, then push additional middleware. Telescope will continue to receive the transfer statistics.

Integration Example: HubSpot PHP SDK

The HubSpot PHP SDK ships with a Pluggable HTTP client stack. To hook it into Telescope you only need to hand it a Guzzle client from the container.

  1. Install the SDK

    bash
    composer require hubspot/api-client
  2. Bind a HubSpot client that reuses the Telescope-aware Guzzle client

    php
    use HubSpot\Factory\HubSpotFactory; use HubSpot\Discovery\Discovery; $this->app->singleton(Discovery::class, function ($app) { $guzzle = $app->make(\GuzzleHttp\Client::class, [ 'config' => [ 'base_uri' => 'https://api.hubapi.com', 'timeout' => 10, ], ]); return HubSpot\Factory::createWithAccessToken( 'your-access-token', $guzzle ); });

    Adjust the configuration array to include proxies, retry middleware, or any other Guzzle options your integration needs.

  3. Use the client

    php
    use HubSpot\Discovery\Discovery; Route::get('/hubspot/contacts', function (Discovery $hubspot) { return $hubspot->crm()->contacts()->basicApi()->getPage()->toArray(); });

    Each call will now appear in Telescope under Client Requests, tagged with api.hubapi.com and the path segments (unless you disable URI tagging).

Tip: HubSpot APIs enforce rate limits. Telescope will record both successful responses and 429 errors so you can diagnose throttling in development.

Testing & Verification

  1. Run a request through your application that uses the container-resolved Guzzle client.
  2. Visit https://your-app.test/telescope/client-requests (or the path configured for Telescope) to verify the entry.
  3. Adjust configuration options and clear caches as needed.

Automated testing tips:

  • The package itself is tested with Orchestra Testbench. If you write integration tests, boot Telescope or fake it appropriately to avoid polluting production storage.
  • You can disable Telescope during certain tests with Telescope::withoutRecording(fn () => /* perform requests */); if you only want to test the client behavior.

Troubleshooting

  • No entries appear: Confirm that Telescope is enabled (TELESCOPE_ENABLED=true) and that you are resolving Guzzle via the container. Telescope only records when Telescope::isRecording() returns true.
  • Entries missing payloads: Increase size_limit in the package config or ensure the response body is seekable. Streams that cannot be rewound will be labeled as Stream Response by Telescope.
  • Headers still visible: Remember that header names are case-insensitive; ensure you use the exact header key (for example, Authorization) in the except_* arrays.
  • Existing on_stats logic not firing: The factory preserves your callback. If you replace the client configuration elsewhere, make sure you merge with the container-provided config instead of instantiating a fresh client.

Changelog

Please see CHANGELOG for more information on what has changed recently.

Credits

Other Projects

  • Laravel Pulse Guzzle Recorder
    • Laravel Pulse Guzzle Recorder provide a custom recorder for intercepting http requests made via guzzlehttp/guzzle php library and log them into the Laravel Pulse Slow Outgoing Requests section.

License

The MIT License (MIT). Please see License File for more information.

Contributors

Showing top 12 contributors by commit count.

View all contributors on GitHub →

This article is auto-generated from huzaifaarain/telescope-guzzle-watcher via the GitHub API.Last fetched: 6/28/2026