Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

s.spaan's avatar
Level 41

Telescope log Guzzle outgoing requests

Hi All,

Do any of you guys know of a package which can log all outgoing Guzzle requests to Telescope?

Or how can i create this myself? Is it possible to create a custom Watcher for telescope (i know i can create a Guzzle Handler stack which could log it, i have never done it however.).

Hope someone already have created the package, and i just can't find it.

Thanks!

Sonny

0 likes
4 replies
skauk's avatar

I used this package to do the same with DebugBar. You can look into how it's done and come up with something similar for Telescope. I think many would find this kind of plugin useful.

Talv's avatar

@s.spaan did you ever find an answer to this or write anything, im looking for something exactly the same!

s.spaan's avatar
Level 41

@talv Telescope does not have the option to create a custom Watcher; i added it a bit hacky but working for my case;

I added a custom handlerStack to the guzzle call and catch the Exceptions in the main Exception handler. To see them in the Request tab.

use GuzzleHttp\Client;
use App\Guzzle\GuzzleHandlerStack;

$guzzle = new Client([
  'base_uri' => 'https://example.com/api/',
  'handler'  => GuzzleHandlerStack::create(),
]);

$response = $guzzle->post('suburi', [
	'json' => $data
]);

// etc

GuzzleHandlerStack.php

namespace App\Guzzle;

use GuzzleHttp\HandlerStack;
use Laravel\Telescope\Telescope;
use Laravel\Telescope\IncomingEntry;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;

class GuzzleHandlerStack
{
	public static function create()
	{
		$stack = HandlerStack::create();
		$stack->unshift(self::telescope_request_logger());
		
		return $stack;
	}
	
	public static function telescope_request_logger()
	{
		return function (callable $handler) {
			return function (RequestInterface $request, array $options) use ($handler) {
				$promise = $handler($request, $options);
				
				return $promise->then(
					function (ResponseInterface $response) use ($request, $options) {
						$startTime = defined('SOME_TIMER') ? SOME_TIMER : null;
						
						$entry = IncomingEntry::make([
							'uri'             => (string)$request->getUri(),
							'method'          => $request->getMethod(),
							'headers'         => $response->getHeaders(),
							'payload'         => json_decode((string)$request->getBody()),
							'response_status' => $response->getStatusCode(),
							'response'        => json_decode((string)$response->getBody()),
							'duration'        => $startTime ? floor((microtime(true) - $startTime) * 1000) : null,
							'memory'          => round(memory_get_peak_usage(true) / 1024 / 1025, 1),
						]);
						
						$entry->tags(['guzzle']);
						
						Telescope::recordRequest($entry);
						
						return $response;
					}
				);
			};
		};
	}
}

In App\Exceptions\Handler.php:



namespace App\Exceptions;

use Exception;
use Laravel\Telescope\Telescope;
use Laravel\Telescope\IncomingEntry;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ServerException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;

class Handler extends ExceptionHandler
{
  
  // removed the rest for clarity
  
  /**
	 * Report or log an exception.
	 *
	 * This is a great spot to send exceptions to Sentry, Bugsnag, etc.
	 *
	 * @param Exception $exception
	 * @return void
	 * @throws Exception
	 */
	public function report(Exception $exception)
	{
		if ($exception instanceof ClientException) {

			$startTime = defined('SOME_TIMER') ? SOME_TIMER : null;
			
			$entry = IncomingEntry::make([
				'uri'             => (string)$exception->getRequest()->getUri(),
				'method'          => $exception->getRequest()->getMethod(),
				'headers'         => $exception->getResponse()->getHeaders(),
				'payload'         => (string)$exception->getRequest()->getBody(),
				'response_status' => $exception->getResponse()->getStatusCode(),
				'response'        => json_decode((string)$exception->getResponse()->getBody()),
							'duration'        => $startTime ? floor((microtime(true) - $startTime) * 1000) : null,
				'memory'          => round(memory_get_peak_usage(true) / 1024 / 1025, 1),
			]);
			
			$entry->tags(['guzzle']);
			
			Telescope::recordRequest($entry);
		}
		
		if ($exception instanceof ServerException) {
			try {
				
			$startTime = defined('SOME_TIMER') ? SOME_TIMER : null;

$entry = IncomingEntry::make([
					'uri'             => (string)$exception->getRequest()->getUri(),
					'method'          => $exception->getRequest()->getMethod(),
					'headers'         => $exception->getResponse()->getHeaders(),
					'payload'         => (string)$exception->getRequest()->getBody(),
					'response_status' => $exception->getResponse()->getStatusCode(),
					'response'        => json_decode((string)$exception->getResponse()->getBody()),
							'duration'        => $startTime ? floor((microtime(true) - $startTime) * 1000) : null,
					'memory'          => round(memory_get_peak_usage(true) / 1024 / 1025, 1),
				]);
				
				$entry->tags(['guzzle']);
				
				Telescope::recordRequest($entry);
        
			} catch (Exception $e) {
				// Do nothing with this exception..
			}
		}
		
		parent::report($exception);
	}
  
  // removed the rest for clarity
  
}

Or see the gist: https://gist.github.com/spaantje/9718360e04185fc707a98eff19ce05cf

1 like

Please or to participate in this conversation.