Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Buzz Profiler Bundle Laravel Package

juliendidier/buzz-profiler-bundle

juliendidier/buzz-profiler-bundle adds a dedicated Symfony web profiler panel for the Buzz HTTP client, so you can inspect every outgoing request, response, headers, and timing directly in the toolbar and profiler. A lightweight way to debug HTTP calls without leaving your Symfony app.

View on GitHub
Deep Wiki
Context7

Getting Started

First, the reality check. juliendidier/buzz-profiler-bundle is a Symfony 2 bundle, not a Laravel package. It registers itself through AppKernel, hooks Symfony's data_collector service tag, and renders a Twig panel in the Web Debug Toolbar via assets:install. There is no service provider, no facade, and no Laravel extension point it can attach to. If your composer.json has laravel/framework in it, you will not get a toolbar icon by installing this. What you can take from it is the pattern: a profiler panel that records every outbound HTTP call (method, URL, status, headers, body, duration). Laravel already ships that pattern natively.

If you are actually on legacy Symfony 2.x with Buzz:

composer require juliendidier/buzz-profiler-bundle
php app/console assets:install --symlink
php app/console cache:clear --env=dev
// app/AppKernel.php
if (in_array($this->getEnvironment(), ['dev', 'test'])) {
    $bundles[] = new Juliendidier\BuzzProfilerBundle\BuzzProfilerBundle();
}

Then load any page that makes an outbound Buzz call and click the toolbar icon to see the request list grouped by client instance.

If you are on Laravel — look here first, in this order:

  1. Laravel Telescope (already installed if you ran composer require laravel/telescope). Open /telescope → Requests tab. The ClientWatcher records URL, method, status, headers, payload, and duration for anything sent through Illuminate\Support\Facades\Http. This is a superset of what the bundle does.
  2. Clockwork (itsgoingd/clockwork) if you prefer an in-browser timeline over a separate Telescope UI.
  3. Laravel Debugbar for the toolbar-icon feel; it has a "Timeline"/"Messages" panel you can push HTTP timings into.
  4. Http::recorded() in tests if all you wanted was a debug-time view of what went out.

First use case to validate the setup: make one slow third-party call (a payment provider sandbox, an enrichment API) from a controller, hit the page, and confirm you can see duration and status without adding a Log::info. If that works, the tooling is wired correctly.

Implementation Patterns

Pattern 1 — The Laravel equivalent of the profiler panel (event listeners)

The bundle's core is "observe every Buzz call without touching call sites." In Laravel you get the same with HTTP client events, which fire for every Http:: call globally:

// app/Providers/HttpObservabilityServiceProvider.php
use Illuminate\Http\Client\Events\{RequestSending, ResponseReceived, ConnectionFailed};
use Illuminate\Support\Facades\Event;

public function boot(): void
{
    Event::listen(ResponseReceived::class, function (ResponseReceived $e) {
        $response = $e->response;
        $request  = $response->transferStats?->getRequest() ?? $response->toPsrResponse()->getRequest();

        Log::channel('http')->debug('outbound', [
            'method'   => $request->getMethod(),
            'uri'      => (string) $request->getUri(),
            'status'   => $response->status(),
            'ms'       => round($response->transferStats?->getTransferTime() * 1000),
            'client'   => $e->request->attributes->get('client_name'), // see Pattern 4
        ]);
    });

    Event::listen(ConnectionFailed::class, fn ($e) => Log::channel('http')->warning('outbound failed', [
        'uri' => $e->request->url(),
        'err' => $e->exception->getMessage(),
    ]));
}

This is the day-to-day lever: one listener, zero call-site edits, every Http:: call visible.

Pattern 2 — Grouping by "client instance" (the bundle's best idea)

The bundle groups calls by Buzz client instance so you can compare, e.g., the billing client against the CRM client. Reproduce it with named clients and tag the request:

// config/services.php or a dedicated config/http.php
'clients' => [
    'billing' => ['base_uri' => env('BILLING_URL'), 'timeout' => 5],
    'crm'     => ['base_uri' => env('CRM_URL'),     'timeout' => 2],
],
Http::globalRequestMiddleware(function ($request) {
    // attribute is set by the wrapper below; default when missing
    return $request;
});

function billing(): PendingRequest {
    return Http::baseUrl(config('clients.billing.base_uri'))
        ->timeout(config('clients.billing.timeout'))
        ->withOptions(['client_name' => 'billing']); // surfaced as attribute in listener
}

Then your profiler/log view can pivot duration by client_name — which is exactly the "is it us, the vendor, or the network?" question the bundle exists to answer.

Pattern 3 — Timing and slow-call budget as a standing guard

The bundle shows duration; the day-to-day win is turning that into a threshold you notice:

Http::globalMiddleware(function ($handler) {
    return function ($request, $options) use ($handler) {
        $start = hrtime(true);
        return $handler($request, $options)->then(function ($response) use ($start, $request) {
            $ms = (hrtime(true) - $start) / 1e6;
            if ($ms > 1000) {
                Log::warning('slow outbound', ['uri' => (string) $request->getUri(), 'ms' => (int) $ms]);
            }
            return $response;
        });
    };
});

Register this in a service provider's boot(). Keep the threshold configurable and off in production (see Gotchas).

Pattern 4 — Redaction at the collector boundary, not at call sites

The biggest operational risk with any HTTP profiler is bearer tokens landing in a profiler cache. In Laravel, redact centrally:

// TelescopeServiceProvider::register() — Telescope 4.x+
Telescope::hideRequestHeaders(['authorization', 'cookie', 'x-api-key']);
Telescope::hideRequestParameters(['password', 'token', 'secret', 'card_number']);

For your own listener, whitelist rather than blacklist:

'headers' => collect($request->getHeaders())
    ->only(['accept', 'content-type', 'user-agent'])
    ->map(fn ($v) => $v[0] ?? null)
    ->all(),

Pattern 5 — Test-time inspection (the quiet killer feature)

Http::fake() + Http::recorded() is the closest thing Laravel has to "replay the profiler for this request" and it's better than the toolbar for CI:

Http::fake(['api.vendor.test/*' => Http::response(['ok' => true], 200)]);

$this->post('/checkout')->assertOk();

Http::assertSent(fn ($req) => $req->url() === 'https://api.vendor.test/charge'
    && $req->hasHeader('Idempotency-Key'));

Pattern 6 — Porting the collector to a Telescope watcher (only if you must)

If your team insists on a bespoke panel, the port is: DataCollector → a class implementing Laravel\Telescope\Watchers\Watcher with register($telescope) hooking the same events as Pattern 1, plus a format() that returns the entry array Telescope renders. Budget a day; don't port the Twig template, Telescope's Vue UI already renders it.

Integration tips

  • Wire the listener/middleware in a dedicated service provider (HttpObservabilityServiceProvider) so it can be conditionally registered by environment.
  • Gate on config('app.debug') and an explicit env flag (HTTP_PROFILING=true), because APP_DEBUG gets flipped on in staging more often than anyone admits.
  • If you're on a Guzzle-only codebase (not Http::), use Guzzle history middleware — $stack->push(Middleware::history($container)) — and render $container into Debugbar's timeline. Same idea, different client.

Gotchas and Tips

Installation / bootstrap

  • Assets aren't installed automatically. On Symfony, a missing assets:install yields a toolbar panel that throws, which degrades the whole debug toolbar — not just this panel. Always run assets:install after composer update.
  • Silent no-op is the classic failure. Bundle registered but the Buzz listener not wired → empty panel. An empty panel looks identical to "no outbound calls were made," which is dangerous false confidence. Sanity-check by making one known Buzz call before trusting the panel.
  • Cache must be cleared (cache:clear --env=dev) after enabling; Symfony 2 caches the container aggressively and the data_collector tag won't be picked up otherwise.

Environment gating

  • This is a dev-only tooling artifact. Register it inside the in_array($env, ['dev','test']) block in AppKernel, not unconditionally. The Symfony profiler writes per-request files to var/cache/<env>/profiler.
  • On Laravel, the same rule applies to your listener: if (! config('app.debug')) return; at the top of boot(). Under load, HTTP capture serializes payloads to storage per request — large uploads or streamed responses cause memory spikes and disk growth.

Security

  • Assume full request/response bodies are captured. Buzz payloads routinely carry bearer tokens, API keys, cookies, and PII. If the collector stores them unredacted, they sit in plaintext in var/cache/*/profiler and are renderable in the UI. Verify redaction before enabling anywhere shared, and treat the profiler cache directory as a sensitive path in your .gitignore/CI artifact rules.
  • Laravel equivalent: confirm Telescope::hideRequestHeaders(...) is actually applied — it's easy to configure redaction and then add a second collector (Debugbar, Clockwork) that bypasses it.

Dependency / compatibility

  • Expect Composer deadlock on modern stacks. The bundle pins Symfony 2 API signatures; Buzz (kriswallsmith/buzz) predates PSR-18/PSR-17 and does not interoperate with modern clients. Assume it cannot coexist with PHP 8 + Symfony 4+ in the same dependency graph. Do not attempt an in-place upgrade — swap the client, then remove the bundle.
  • 15 stars / 0 dependents = no community backstop. Any defect (PHP deprecation, Twig incompatibility, a header needing redaction) becomes your internal backlog. Time-box the dependency to the duration of a client migration; don't adopt it as standing infrastructure.
  • Buzz itself is abandoned, so a failure could originate in the bundle, in Buzz, in the curl adapter, or in the Symfony 2 runtime — with no upstream to escalate to. Budget debugging time accordingly.

Debugging tips

  • If the panel is blank, check three things in order: (1) is the collector tagged data_collector, (2) is the Buzz client actually the instance the listener subscribed to (not a manually new'd client), (3) is the profiler enabled for that environment (framework.profiler in config_dev.yml).
  • dump() the raw collector data via app.request.attributes->get('_profiler')-style inspection before blaming the template; the rendering layer fails more quietly than the collector.
  • On Laravel, if Http:: calls don't appear in Telescope, check config/telescope.php → watchers.client.enabled and the ignore list — an over-broad ignore pattern silently swallows entries.

Extension points to borrow from the bundle

  • The data_collector tag + a Twig template is the whole architecture; on Laravel the analogues are a Telescope\Watchers\Watcher plus the built-in Vue entry renderer.
  • The group-by-client-instance view is worth copying regardless of stack: tag every request with a logical client name at the wrapper level (Pattern 2) so the profiling view answers "which vendor is slow?" in one glance rather than a grep through a log file.
  • The request count badge in the toolbar is a cheap early-warning signal — N+1 outbound calls per page render is a common, invisible perf bug. On Laravel, a Debugbar "Messages" counter or a Telescope filter of > 10 requests/response gives you the same tripwire.

Bottom line for a Laravel developer: don't install it, don't port the templates. Copy the two ideas that matter — central capture of outbound calls with duration and status and grouping by logical client — and implement them with Telescope's ClientWatcher plus Http events. You get the same debugging visibility, on a maintained dependency, in an afternoon.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core