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

Swoole Blackfire Laravel Package

upscale/swoole-blackfire

Integrates Blackfire profiling with Swoole workers, enabling per-request profiling in long-running Laravel Octane applications. Helps Blackfire traces work correctly across persistent PHP workers instead of only the initial request.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install as a dev dependency: composer require --dev upscale/swoole-blackfire. You don't want this in production images.
  • Confirm prerequisites before writing any code:
    • PHP swoole extension loaded (php -m | grep swoole).
    • The Blackfire probe extension loaded (php -m | grep blackfire), not just the blackfire CLI/agent.
    • A reachable Blackfire agent (default 127.0.0.1:8307) and BLACKFIRE_SERVER_ID / BLACKFIRE_SERVER_TOKEN (or client id/token) in the environment. The agent, not the package, is what accepts the profile.
  • Look at src/ first. The entry point is an invokable Profiler in the Upscale\Swoole\Blackfire namespace that wraps a Swoole onRequest handler. The README's minimal example is roughly:
use Swoole\Http\Server;
use Swoole\Http\Request;
use Swoole\Http\Response;
use Upscale\Swoole\Blackfire\Profiler;

$server = new Server('0.0.0.0', 8080);
$server->on('request', new Profiler(function (Request $req, Response $res) {
    $res->end('ok');
}));
$server->start();
  • First real use case: install the Blackfire browser extension, run your Swoole server, and click "Profile" on a page. Because Swoole bypasses PHP's RINIT/RSHUTDOWN, the probe extension will not auto-start on the X-Blackfire-Query header the way it does under FPM — the package exists specifically to bridge that gap by enabling/disabling the probe manually around each request.

Implementation Patterns

  • Middleware, not a global. Keep the Profiler as the outermost onRequest handler. Everything you want in the profile (routing, Laravel/Octane dispatch, DB I/O, rendering) must happen inside the wrapped closure.
  • Gate on the header. The wrapper should only call blackfire_probe_enable() when the incoming request actually carries a Blackfire query header. On every other request it should be effectively a no-op — verify this by load-testing with the header absent.
  • Name your transactions. A raw URI with IDs is useless in the Blackfire UI. Either pass a name resolver into the Profiler (check the constructor signature) or compute the route name inside your handler and set it before the probe stops. Prefer something like GET /orders/{id} over /orders/12345.
  • Balance enable/stop for every request. The probe is process-global, and Swoole workers are long-lived. Each profiled request must enable and then stop the probe before returning the response.
  • Laravel Octane / similar frameworks: register the Profiler at the Swoole-server level, not as a Laravel middleware. A Laravel middleware runs too late and stops too early to capture the full request lifecycle, and Octane's own request sandboxing can interfere with the probe's state.
  • Custom spans for hotspots. The package only gives you the transaction boundary. For deep analysis use blackfire_span_start('db:users') / blackfire_span_stop() inside the handler to mark sub-operations; those show up alongside the automatic function calls.
  • CLI/cron coroutines started via Server::task() or a timer are outside the onRequest wrapper. Don't expect a profile from them; instrument them by hand or use the standard blackfire run CLI integration in a separate process to avoid colliding with the HTTP probe.

Gotchas and Tips

  • Leaked transactions are the #1 failure mode. If your handler throws before the probe is stopped, the next request will hit blackfire_probe_enable(): probe is already enabled. Wrap the handler in try { ... } finally { /* stop */ }, or file a patch/vendor the package if its stop path isn't exception-safe.
  • Coroutine concurrency is unsafe. The probe is not coroutine-aware. Two coroutines enabling it in the same worker at the same time will corrupt the profile. In practice this means don't profile concurrently — profile one request at a time, or dedicate a small worker pool to profiling and route profiled traffic there.
  • Header case sensitivity. Swoole normalizes header keys to lowercase in $request->header, while Blackfire tooling and proxies may send X-Blackfire-Query. If profiling silently never triggers, var_dump($request->header) to confirm the key the wrapper is looking for.
  • Config is read at worker start. Changing Blackfire agent connection settings in php.ini requires a full worker restart; reload may not pick it up. In dev, restart the Swoole master process.
  • Never enable in production. Keep the package in require-dev, gate instantiation behind an env check (APP_ENV=local), and don't ship the Blackfire token in images that run outside your local machine.
  • Don't rewrite the query string. Any upstream middleware that strips or normalizes headers (e.g., an nginx proxy) will break the profile handshake. Keep the X-Blackfire-Query value intact end-to-end.
  • Version pinning matters. With few dependents and moderate activity, pin a semver range (^1.0) and be ready to vendor or fork if the API doesn't match your Swoole version. Read the source — it's small enough to audit in a few minutes, and that's the fastest way to learn its actual extension points (constructor arguments, name resolver, stop behavior).
  • The agent is the debugging surface. If the wrapper enables the probe but no profile shows up in the UI, check the agent log (blackfire agent:status) and the BLACKFIRE_LOG_LEVEL setting before assuming a package bug.
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.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels