muhammadhuzaifa / 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.
Installs: 200 060
Dependents: 1
Suggesters: 0
Security: 0
Stars: 98
Watchers: 3
Forks: 6
Open Issues: 2
pkg:composer/muhammadhuzaifa/telescope-guzzle-watcher
Requires
- php: ^8.4
- guzzlehttp/guzzle: ^7.9
- illuminate/contracts: ^12.0
- laravel/telescope: ^5.11
- spatie/laravel-package-tools: ^1.92
Requires (Dev)
- driftingly/rector-laravel: ^2.0
- laravel/pint: ^1.24
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^10.4
- phpstan/phpstan: ^2.1
- rector/rector: ^2.1
README
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.
Once the installation and configurations are completed, you will be able to see the request logs under telescope/client-requests
Table of Contents
Requirements
- PHP ^8.4
- Laravel 12.x
- Laravel Telescope ^5.11
- Guzzle ^7.9
Installation
Install the package via Composer:
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:
php artisan vendor:publish --tag="telescope-guzzle-watcher-config"
The published file lives at config/telescope-guzzle-watcher.php
.
How It Works
- 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 anon_stats
callback that forwards request and response information to Telescope. - 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'sIlluminate\Http\Client\Request
andResponse
wrappers so that Telescope can index the payload. - 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:
Key | Type | Default | Description |
---|---|---|---|
except_request_headers |
array<string> |
[] |
Header names (case-insensitive) that should be hidden from Telescope for outgoing requests. Useful for API keys or authorization tokens. |
except_response_headers |
array<string> |
[] |
Header names that should be hidden from Telescope responses. |
enable_uri_tags |
bool |
true |
When 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_tags |
array<string> |
[] |
List of words that should be excluded from the tag list after it is generated. Matching is case-insensitive. |
size_limit |
`int | null` | 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:
// 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:
// 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:
$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.
-
Install the SDK
composer require hubspot/api-client
-
Bind a HubSpot client that reuses the Telescope-aware Guzzle client
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.
-
Use the client
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 withapi.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
- Run a request through your application that uses the container-resolved Guzzle client.
- Visit
https://your-app.test/telescope/client-requests
(or the path configured for Telescope) to verify the entry. - 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 whenTelescope::isRecording()
returnstrue
. - 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 asStream Response
by Telescope. - Headers still visible: Remember that header names are case-insensitive; ensure you use the exact header key (for example,
Authorization
) in theexcept_*
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.