Monitoring PHP Applications with NGINX Amplify

by

[ngx_snippet name=’table-style-blog’]

Introduction

PHP is consistently in the top five programming languages for the Web, and many websites are built on PHP applications like WordPress, Drupal, or Joomla. Every day, millions of developers create new applications or extensions to the existing ones using PHP. NGINX and PHP is a popular combination, and we’ve created a two‑part blog series for maximizing PHP performance.

Monitoring a PHP application can be a daunting task. Logs should be checked, specialized settings should be implemented, and related metrics should be collected and well understood. It’s easy to get lost in the process, especially if you’ve just started with something like WordPress, and you’re still learning how to build your website.

It’s common to see NGINX deployed with a PHP application. In this case, NGINX typically works as a local web accelerator, and PHP‑FPM serves as the application server. This setup has proven extremely useful to offload SSL termination, content caching, authentication, and other aspects of HTTP security, from the PHP application to NGINX.

Recognizing that it would be convenient to also monitor PHP‑FPM metrics together with the NGINX metrics, we’ve recently enabled it in NGINX Amplify. (If you haven’t tried it yet, sign up today for the beta.)

If the Amplify Agent is run next to the PHP‑FPM master process, the agent can detect the PHP‑FPM master process automatically, determine its configuration, and start to collect thePHP‑FPM metrics.

If everything is set up properly, you’ll immediately have a set of out-of-the-box graphs for PHP‑FPM in Amplify.

The PHP‑FPM metrics displayed on the Graphs page are cumulative across all automatically detected pools. If you need per-pool graphs, please use the Dashboards to create custom graphs.

Let’s check it all out in more detail.

PHP-FPM Metrics in Amplify

Below is the list of the PHP‑FPM metrics currently supported in Amplify.

Metric in Amplify Description PHP‑FPM Status Metric
php.fpm.conn.accepted The number of requests accepted by the pool accepted conn
php.fpm.queue.current The number of requests in the queue of pending connections listen queue

php.fpm.queue.max The maximum number of requests in the queue of pending connections since FPM has started max listen queue
php.fpm.queue.len The size of the socket queue of pending connections listen queue len
php.fpm.proc.idle The number of idle processes idle processes
php.fpm.proc.active The number of active processes active processes
php.fpm.proc.total The number of idle + active processes total processes
php.fpm.proc.max_active The maximum number of active processes since FPM has started max active processes
php.fpm.proc.max_child The number of times the process limit has been reached max children reached
php.fpm.slow_req The number of requests that exceeded request_slowlog_timeout value slow requests

The agent should run in the same process environment as PHP‑FPM and be able to find the PHP‑FPM processes with ps(1); otherwise, the PHP‑FPM metric collection won’t work. For example, if the agent is run on the host system, but the PHP application is run inside a Docker container on that host, you should add the agent to that Docker container.

When the agent finds a PHP‑FPM master process, it automatically detects the path to the PHP‑FPM configuration. When the PHP‑FPM configuration is found, the agent will look up the pool definitions and the corresponding pm.status_path directives.

The agent will find all pools and status URIs currently configured. The agent then queries the PHP‑FPM pool status(es) via FastCGI. There’s no need to define an HTTP proxy in your NGINX configuration that will point to the PHP‑FPM status URIs. The agent doesn’t use HTTP, and hence does not depend on NGINX to provide an HTTP proxy to the PHP‑FPM status URI.

Setting Up the Agent for PHP-FPM Monitoring

To start monitoring PHP‑FPM, follow the steps below:

  1. Make sure that your PHP‑FPM status is enabled for at least one pool. If it’s not, uncomment the pm.status_path directive for the pool, then restart PHP‑FPM.

  2. Update the agent to the most recent version.

  3. Check that the following options are included in /etc/amplify-agent/agent.conf:

    [extensions]
    phpfpm = True
  4. Restart the agent.

The agent should be able to detect the PHP‑FPM master and the workers, obtain the access to the PHP‑FPM status, then collect the metrics.

Using PHP-FPM with a TCP Socket

If your PHP‑FPM is configured to use a TCP socket, first make sure you can query the PHP‑FPM metrics manually with cgi-fcgi(1). Double‑check that your TCP socket configuration is secure – ideally, with the PHP‑FPM pool(s) listening on 127.0.0.1, and listen.allowed_clients enabled as well.

Check that you can query the PHP‑FPM status for the pool from the command line,

$ SCRIPT_NAME=/status SCRIPT_FILENAME=/status QUERY_STRING= REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9090

and that the above command (or alike) returns the proper set of PHP‑FPM metrics:

Expires: Thu, 01 Jan 1970 00:00:00 GMT
Cache-Control: no-cache, no-store, must-revalidate, max-age=0
Content-Type: text/plain

pool: www
process manager: dynamic
start time: 26/Jul/2016:12:51:05 -0400
start since: 29458594
accepted conn: 757839
listen queue: 0
max listen queue: 0
listen queue len: 0
idle processes: 1
active processes: 1
total processes: 2
max active processes: 1
max children reached: 0
slow requests: 0

The cgi-fcgi(1) utility has to be installed separately (usually from the libfcgi-dev package). This tool is not required for the agent to collect and report PHP‑FPM metrics. However, it can be indispensable to quickly diagnose possible issues with the PHP‑FPM metric collection.

Using PHP-FPM with a Unix Domain Socket

If you have a single PHP‑FPM instance, check that NGINX, the Amplify Agent, and the PHP‑FPM workers are all run under the same user ID (for example, www-data). If there are multiple pools configured with different user IDs, make sure the agent’s user ID is included in the group IDs of the PHP‑FPM workers. This is required in order for the agent to access the PHP‑FPM pool socket(s) when querying for metrics via FastCGI.

First, check that the listen socket for the PHP‑FPM pool you want to monitor, and for which you enabled pm.status_path, is properly configured with listen.owner and listen.group.

listen.owner = www-data
listen.group = www-data
listen.mode = 0660

Next, verify that the PHP‑FPM listen socket for the pool is properly created and has the right permissions.

$ ls -la /var/run/php5-fpm.sock
srw-rw—- 1 www-data www-data 0 Jul 26 2016 /var/run/php5-fpm.sock

Finally, query the PHP‑FPM status for the pool from the command line, and see if it returns the list of PHP‑FPM metrics.

$ $ SCRIPT_NAME=/status SCRIPT_FILENAME=/status QUERY_STRING= REQUEST_METHOD=GET cgi-fcgi -bind -connect /var/run/php5-fpm.sock

If everything is set up properly, the agent will be collecting the PHP‑FPM metrics, and you’ll see the predefined graphs on the Graphs page momentarily.

What to Monitor in PHP-FPM

If you’re running a PHP‑based application like WordPress, it’s very important to regularly check the following, and adjust the PHP‑FPM settings (and sometimes also the NGINX and the operating system settings as well), to ensure your website works well:

  • Number of PHP‑FPM workers. Amplify metrics like php.fpm.proc.max_child and other PHP‑FPM related metrics can be helpful. If your PHP‑FPM consistently lacks workers to process incoming requests, it’ll take more time for the end user to open the website (if it opens at all!)
  • Slow requests. PHP‑FPM has a useful feature that enables logging and monitoring of the requests that take too long (how long is actually configurable). Such monitoring is not on by default, so it makes sense to check your PHP‑FPM pool configuration file, and set slowlog and request_slowlog_timeout variables accordingly. The corresponding metric in Amplify is php.fpm.slow_req.
  • Connection queues. When an incoming request can’t be instantly accepted (for example, there’s no idle worker available to process the request), it’ll wait in a connection queue. The actual settings and behavior depend on the OS configuration, so it’s worth it to periodically check the associated PHP‑FPM metrics in Amplify, such as php.fpm.queue.max.

Troubleshooting

Here’s a list of caveats to look for if the PHP‑FPM metrics aren’t being collected:

  • No status URI enabled for any of the pools
  • Agent can’t connect to the TCP socket (when using PHP‑FPM with a TCP socket)
  • Agent can’t parse the PHP‑FPM configuration – please report issues like this, and we’ll investigate
  • Different user IDs used by the agent and the PHP‑FPM workers, or lack of a single group (when using PHP‑FPM with a Unix domain socket)
  • Wrong permissions configured for the PHP‑FPM listen socket (when using PHP‑FPM with a Unix domain socket)
  • The agent and the PHP‑FPM instance are not in the same process environment (for example, the agent is installed on the host system, and the PHP‑FPM instance is inside a Docker container)

If checking the above issues didn’t help, please enable the agent debug log, restart the agent, wait a few minutes, and then create an issue via Intercom. Please attach the log to the Intercom chat. We’d be happy to help.

Conclusion

We hope it’ll be convenient for you to see the PHP‑FPM metrics in Amplify, and have a broader view into the application behavior. With metrics for NGINX, the operating system, and now the PHP‑FPM metrics, monitoring a LEMP stack with Amplify becomes easier.

We’re planning to monitor even more application stack components in Amplify soon, so please keep in touch. If you have any suggestions, let us know!

Many thanks for using Amplify! If you haven’t tried it yet, sign up for the beta today!