Skip to main content

Debug your extension

This page covers 3 ways to find what went wrong. Step through the site's code with XDebug, watch the full output of a command or read the logs of the background processes.

Step-debug with XDebug​

debug starts or restarts the webserver with XDebug on. start restarts it with XDebug off while XDEBUG is unset. The following commands turn XDebug on and off:

make debug # Restart with XDebug enabled
make start # Restart without XDebug

To step-debug the site:

  1. Install the XDebug PHP extension on your host, and confirm that php -v mentions with Xdebug.
  2. Turn XDebug on with the preceding command marked Restart with XDebug enabled. Confirm that the XDebug line of info shows enabled.
  3. Start listening for debug connections in your IDE.
  4. Open a page of the site. The request starts a debug session in your IDE.
  5. When you're done, remove XDEBUG from .env and your shell if you set it there.
  6. Turn XDebug off with the preceding command marked Restart without XDebug.

In make and Ahoy, debug has the aliases debug-on, xdebug and xdebug-on. start has the aliases debug-off and xdebug-off. debug leaves a webserver that already runs with XDebug as it is.

The server runs with xdebug.mode=debug and xdebug.start_with_request=yes, so every request starts a debug session. A browser extension that sets the XDebug trigger has no effect here. To skip debugging, stop listening in your IDE.

XDEBUG counts as unset only while it's empty or missing in your shell and in .env. Any other value turns XDebug on, 0 included. debug sets XDEBUG only for the server it starts and leaves .env as it is. When XDEBUG is set and the extension is missing, start stops with an error before it starts a server.

Code coverage stays on pcov, because the XDebug settings apply only to the webserver.

Command output​

The commands print their own progress as [TASK] and [ OK ] lines. They hide the output of the tools they run, such as Composer, npm ci and Drush, until a tool fails. Then the captured output of that tool appears. The output of your project's own commands always shows: npm run build and the lifecycle scripts.

To stream the output of the tools as they run, set DEBUG=1:

DEBUG=1 make build

DEBUG takes only 1, from your shell or .env, and works for every command that runs these tools. Composer and npm then stream their full output. Drush streams its progress, and the results it prints stay captured. scripts/eddy-tooling streams its Composer output too, on the runs that install the package. Without a wrapper, scripts/eddy-tooling reads DEBUG from your shell only.

Logs​

The processes that keep running after a command returns write their output to the .logs directory in the project root:

FileWritten by
.logs/php.logThe PHP webserver.
.logs/chromedriver.logThe chromedriver that FunctionalJavascript tests drive.
.logs/cloudflared.logThe public tunnel. Its process ID is in .logs/cloudflared.pid.

With the selenium backend, the browser's output stays in its Docker container. The container is named after the WebDriver port, such as selenium-4444. To read the output, run docker logs selenium-4444, with your own port in place of 4444. info prints the port, and so does vendor/bin/eddy-info webdriver-port (see eddy-info fields). When the download of a chromedriver fails, read .chromedriver/install.log for the details.

The test runs write their reports to .logs too:

  • .logs/test_results/phpunit/phpunit.xml - the JUnit report of the PHPUnit run.
  • .logs/coverage/phpunit and .logs/coverage/jest - the coverage reports (see Code coverage).
  • .logs/browser_output - the HTML pages and screenshots of Functional and FunctionalJavascript tests (see Test output). Drupal writes them to build/web/sites/simpletest/browser_output, and provision links that directory here.

reset removes the whole .logs directory.