Skip to content
William Desportes edited this page Mar 28, 2025 · 13 revisions

How to use xhprof to send samples to the phpMyAdmin team

Using phpMyAdmin docker image

Note

Last tested on: 28/03/2025

Warning

You must have a volume mounted to be able to get the profiles on your host file system

And depending on how the container runs you might also need to run: chmod 777 build/profiles/

Enter the container: docker exec -u root -it containerName bash

# See (below): Install the `xhprof` extension using pecl
# Setup the built extension
echo 'extension=xhprof.so' > /usr/local/etc/php/conf.d/docker-php-ext-xhprof.ini
# Install nano (or any other editor)
apt update && apt install nano -y
# Edit the index file
nano index.php
# Apply (below): Patch your `index.php` file
# Install graphviz (if you host xhprof web UI in the container build folder)
# apt update && apt install graphviz -y
exit
  • The restart the container: docker restart containerName
  • Browse and test phpMyAdmin, each request should build a profile

Install the xhprof extension using pecl

pecl update-channels
pecl install xhprof

Install the xhprof extension using apt

(You may need to add the DEB sury repo: https://gist.github.com/janus57/37b079a383dd0507149bd94fd35053d1)

apt install php-xhprof
# More specific
apt install php8.0-xhprof

Detect where ini files are loaded for the CLI

Run php --ini and it will say Scan for additional .ini files in

Example:

php --ini
Configuration File (php.ini) Path: /etc/php/8.4/cli
Loaded Configuration File:         /etc/php/8.4/cli/php.ini
Scan for additional .ini files in: /etc/php/8.4/cli/conf.d

Activate the extension (for the CLI)

Run echo 'extension=xhprof.so' > /etc/php/7.4/cli/conf.d/docker-php-ext-xhprof.ini to activate the extension. Note: /etc/php/7.4/cli/conf.d is a path given by php --ini

Activate the extension (for php-fpm)

Run echo 'extension=xhprof.so' > /etc/php/7.4/fpm/conf.d/docker-php-ext-xhprof.ini to activate the extension. Note: /etc/php/7.4/fpm/conf.d is a path given by phpinfo(); on a web page in the "Scan this dir for additional .ini files" line

Restart your web-server

No phpMyAdmin is not an app that "runs". That said you need to restart your php-fpm worker pool or your apache2 webserver. It will read the new extension file config and load it.

Examples:

  • service apache2 restart
  • docker restart phpfpm74 (where phpfpm74 is the container name)
  • service php7.2-fpm restart
  • /etc/init.d/php7.2-fpm restart

Patch your index.php file

Add this to the start of the file after declare(strict_types=1);

class XhProfProfiling
{
    /** @var string */
    private $requestUuid;

    public function __construct()
    {
        $this->requestUuid = uniqid() . '.' . str_replace('+', '-', date('c'));
        if (! extension_loaded('xhprof')) {
            $this->log('The xhprof extension is not enabled');

            return;
        }

        xhprof_enable(XHPROF_FLAGS_CPU | XHPROF_FLAGS_MEMORY);
        $this->log('Loaded xhprof');
    }

    public function log(string $msg): void
    {
        // Enable this to print logs to error logs
        // error_log('[' . $this->requestUuid . '] ' . $msg);
    }

    public function __destruct()
    {
        global $route;

        if (! extension_loaded('xhprof')) {
            return;
        }

        $buildXhprofs = __DIR__ . '/build/profiles/';
        if (! is_dir($buildXhprofs)) {
            mkdir($buildXhprofs, 0777, true);
        }

        $xhprofData = xhprof_disable();
        $xhprofData = serialize($xhprofData);

        $this->requestUuid .= str_replace('/', '--', $route);

        $profilePath = $buildXhprofs . $this->requestUuid . '_capture.xhprof';
        $wrote = file_put_contents($profilePath, $xhprofData);
        $this->log('Wrote xhprof profile to "' . $profilePath . '": ' . ($wrote === false ? 'no' : 'yes'));

        $metaPath = $buildXhprofs . $this->requestUuid . '_metadata.json';
        $metadata = [
            'route' => $route,
            'method' => $_SERVER['REQUEST_METHOD'] ?? 'php ini bug',
            'params' => [
                'GET' => $_GET,
                'POST' => $_POST,
                'COOKIES' => $_COOKIE,
            ],
        ];

        // Replace tokens with "*"
        $ssoValue = $GLOBALS['cfg']['Server']['SignonSession'] ?? 'n/a';
        foreach (['phpMyAdmin', 'phpMyAdmin_https', $ssoValue] as $key) {
            if (! isset($metadata['params']['COOKIES'][$key])) {
                continue;
            }

            $metadata['params']['COOKIES'][$key] = str_repeat('*', strlen($metadata['params']['COOKIES'][$key]));
        }
        foreach (array_keys($metadata['params']) as $key) {
            if (! isset($metadata['params'][$key]['token'])) {
                continue;
            }

            $metadata['params'][$key]['token'] = str_repeat('*', strlen($metadata['params'][$key]['token']));
        }

        $metadata = (string) json_encode($metadata, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);

        $wrote = file_put_contents($metaPath, $metadata);
        $this->log('Wrote metadata to "' . $metaPath . '": ' . ($wrote === false ? 'no' : 'yes'));
    }
}

$keepMeInMemory = new XhProfProfiling();

Send us the profiles and metadata files

Please check that the metadata files have nothing private

They normally contain no private data (only the queries could be in the files)

They are in {phpMyAdmin}/build/profiles/

How to browse the profiling files

Download xhprof UI

Note

Last tested version of xhprof UI: 2.3.10

Only the folder xhprof_lib and xhprof_html are needed

xhprof_html/docs can be deleted to save disk space

Change the folder

You need to edit xhprof_html/index.php, xhprof_html/typeahead.php, xhprof_html/callgraph.php to change the profiles path.

Or set XHPROF_OUTPUT_DIR as an ENV variable of the webserver/docker container. Or set the ini value xhprof.output_dir.

- $xhprof_runs_impl = new XHProfRuns_Default();
+ $xhprof_runs_impl = new XHProfRuns_Default('/var/www/html/build/profiles');

Browse

Open your webserver URL, for example: xhprof-2.3.10/xhprof_html/index.php

Display graphs

Xhprof graphs need graphviz to display.

# Install graphviz
apt update && apt install graphviz -y
Clone this wiki locally