runtime icon indicating copy to clipboard operation
runtime copied to clipboard

feat: add middleware to FrankenPhpSymfony

Open Scarbous opened this issue 3 months ago • 6 comments

We use tideways in our projects. We want to use this middleware to enable the request based profiling.

https://support.tideways.com/documentation/setup/installation/frankenphp.html#code-changes-to-frankenphp_handle_request-callback

Scarbous avatar Oct 22 '25 07:10 Scarbous

FYI, in Symfony 7.4, support for FrankenPHP will work out of the box, no php-runtime package will be required.

nicolas-grekas avatar Oct 22 '25 08:10 nicolas-grekas

Thank you @nicolas-grekas, I will add the middleware PR also for the runtime in symfony.

Scarbous avatar Oct 22 '25 08:10 Scarbous

Is it necessary to use low-level middleware, but not to decorate Symfony's kernel instance, which would provide a generic solution?

andrew-demb avatar Oct 22 '25 11:10 andrew-demb

@andrew-demb I have considered using Symfony events, but I would like to be able to wrap the entire handle process.

I want to use a middleware for tideways like this:

class TidewaysMiddleware implements MiddlewareInterface
{
    public function wrap(callable $handler, array $server): void
    {
        if (!$this->checkTideways()) {
            $handler();
            return;
        }

        \Tideways\Profiler::start();
        try {
            $handler();
        } catch (\Throwable $e) {
            \Tideways\Profiler::logException($e);
            throw $e;
        } finally {
            \Tideways\Profiler::stop();
        }
    }

    private function checkTideways(): bool
    {
        return !class_exists('Tideways\Profiler') && !\Tideways\Profiler::isEnabled();
    }
}

Scarbous avatar Oct 22 '25 13:10 Scarbous

I’m actually working on exactly the same thing 😅 On my side, I’m using a simple Listener with very high and very low priorities to make sure it runs first at the beginning of the request and last at the end:

class TidewaysListener
{
    #[AsEventListener(RequestEvent::class, priority: PHP_INT_MAX)]
    public function beforeRequest(RequestEvent $event): void
    {
        Profiler::start();
    }

    #[AsEventListener(event: KernelEvents::TERMINATE, priority: PHP_INT_MIN)]
    public function terminateRequest(TerminateEvent $event): void
    {
        Profiler::stop();
    }
}

From my tests, there’s no need to manually handle \Tideways\Profiler::logException — it already integrates with Symfony’s ErrorHandler natively.

ppelisset avatar Oct 22 '25 15:10 ppelisset

@Scarbous I'm talking about the kernel's decorator, not kernel events. It will cover the full handle process, and will be generic, not just for frankenphp

andrew-demb avatar Oct 22 '25 19:10 andrew-demb