Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XDebug documentation #931

Open
Radiergummi opened this issue Jul 22, 2024 · 10 comments
Open

XDebug documentation #931

Radiergummi opened this issue Jul 22, 2024 · 10 comments
Labels
enhancement New feature or request

Comments

@Radiergummi
Copy link

Describe you feature request

We'd like to use FrankenPHP for our Laravel application (running in Docker), but using it with XDebug isn't as straight-forward as the website claims it is:

  • Sometimes requests appear to be hanging in the frankenphp-worker.php script created by Octane (with no breakpoints set at all)
  • Breakpoints set in the IDE don't propagate to the running application—HTTP endpoints will be served without invoking breakpoints. Restarting the container fixes this, but...
  • ...removing breakpoints requires another container restart, which takes a few seconds again
  • Even when setting MAX_REQUESTS=1 in the environment, a breakpoint triggered and then removed will be triggered again on a subsequent request, and only on the third request will it no longer be triggered.

In combination, that makes debugging hard to use, which has encouraged some of our developers to go back to dd()—ugh!

Hence, I would kindly like to ask for two thinks:

  1. Improved (that is, any kind of) documentation on debugging, XDebug setup, and debugging caveats that might apply.
  2. Possibly better support for breakpoints set and unset via the XDebug protocol; I'm really not competent in this regard, but my gut says the FrankenPHP worker needs to either reload if breakpoints are modified, or otherwise account for that. When using the built-in PHP debug server, this works without a hitch, so this must be possible in general.

We're using PHP 8.3, Xdebug 3.3.2, Laravel 11 with current Octane, and the latest FrankenPHP Docker image (as a base image for our own).

@Radiergummi Radiergummi added the enhancement New feature or request label Jul 22, 2024
@Radiergummi
Copy link
Author

Radiergummi commented Jul 22, 2024

On browsing the XDebug issue tracker, there's a related issue:

0002161: Breakpoints not updated when process is running
When a PHP is process is already running and you add a new breakpoint, it will never be triggered unless a script is restarted.
https://bugs.xdebug.org/view.php?id=2161

Following that, Derick is just now implementing support for control sockets, allowing IDEs to inject new breakpoints into running PHP processes—such as the FrankenPHP worker.
IIUC, that means step debugging with XDebug was never actually possible without restarting FrankenPHP after configuring breakpoints?
Adding this information to the website would have saved us, and probably others too, a lot of time. At least to me it means that I'll revert from FrankenPHP back to the built-in webserver for now; not being able to use breakpoints in local development without restarting the server is a non-starter.

Edit: This is in no way meant to dismiss the amazing work of all FrankenPHP contributors. I'd just like to suggest clarifying the documentation on XDebug to make it clear step debugging doesn't really work for now, as the whole debugging story feels a little under-documented right now.

@dunglas
Copy link
Owner

dunglas commented Jul 22, 2024

There are a workaround for that: not using the worker-mode or setting the max number of requests to handle with the worker mode to 1 (which is very similar to disabling the worker mode entirely). It's what we do in Symfony Docker for instance (the worker mode is disabled in dev, and enabled in production).

@Radiergummi
Copy link
Author

Radiergummi commented Jul 23, 2024

By setting max requests to 1, the synchronisation between the IDE and FrankenPHP is off-by-one—after setting a breakpoint, you need to request the old code once, the worker restarts and the breakpoint becomes active; after disabling the breakpoint, you again need to do an additional request, which triggers the (now-gone) breakpoint again, and only after that things are back to normal.

However, disabling the worker mode is the way to go. This isn't as straightforward in Laravel Octane, which doesn't seem to anticipate someone might want to do this. By using a custom Dockerfile adapted from the one included with Octane, it's doable though.
If someone happens to stumble upon this, here's our solution:

(worker) {
	worker "{$APP_PUBLIC_PATH}/frankenphp-worker.php" {$CADDY_SERVER_WORKER_COUNT}
}

{
	{$CADDY_GLOBAL_OPTIONS}

	admin {$CADDY_SERVER_ADMIN_HOST}:{$CADDY_SERVER_ADMIN_PORT}

	frankenphp {
		{$CADDY_SERVER_FRANKENPHP_OPTIONS:import worker}
	}

	{$CADDY_GLOBAL_EXTRA_DIRECTIVES}
}

# (Rest of the default config below)

All it requires you to do locally is set the CADDY_SERVER_FRANKENPHP_OPTIONS environment variable to an empty string locally, using your Dockerfile or compose stack or whatever.

Thank you for pointing me in the right direction, the Symfony repository was very helpful. This is probably a Laravel issue after all, but I'm weary of Taylor silently dismissing PRs. This issue can be closed then, I guess. Again, thank you!

@dunglas
Copy link
Owner

dunglas commented Jul 23, 2024

As the co-author of the FrankenPHP support for Octane, I'm probably the one to blame! IMHO a docs PR on Octane should to the trick. Or maybe an additional (temporarily) debug flag?

@Radiergummi
Copy link
Author

The issue is, in my opinion, that the default Caddyfile included in Octane always uses the worker mode. I don't know how others solve this, but I try to keep our development environment as close to production as possible, and thus also want to use Octane locally.

I think the most Laravel-y thing would be to enable worker mode only if APP_ENV is not local, or probably check APP_DEBUG is true?

@dunglas
Copy link
Owner

dunglas commented Jul 23, 2024

Actually the issue occurs only when using Xdebug, maybe could we detect if XDebug is enabled or something like that.

@Radiergummi
Copy link
Author

@dunglas just so I can understand this correctly; from the default Octane config, FrankenPHP will start in worker mode, correct? So for changes made to the code to become live in development, users must set the maximum number of requests handled by workers to 1.
If that is true, what benefit does the worker mode offer for development, if Symfony Docker doesn't use it here either?

@withinboredom
Copy link
Collaborator

Worker mode is an optimization, for now anyway. As more and more devs get used to working with it (like these changes to xdebug) this will become less truer over time. Generally, you disable optimizations (like a compiled container, etc) during development to make it easier/faster to get feedback loops and iterate.

For now, there are things you have to manually do (kinda like not that long ago, we had to manually disable compiled DI containers in dev, now it's automated, most of the time). Things get better, all the time.

@Radiergummi
Copy link
Author

Right; that matches my understanding. So, maybe to rephrase my intent—couldn't we, then, update the Octane integration such that it would only enable worker mode if the application is running in production?
This would improve the development workflow for Laravel users, and work out of the box, without any userland modifications necessary.

@withinboredom
Copy link
Collaborator

I assume they accept PRs, so I assume it would be possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants