Nginx – Add custom variables to nginx access log from PHP-FPM

nginxphp-fpm

With the log_format its possible to include a range of variables such as $http_user_agent:

http://nginx.org/en/docs/http/ngx_http_core_module.html#variables

But is it possible to include a variable from PHP-FPM?

For example, I would like to include the User ID and timing information in the access_log.

One possibility is to set a header in PHP, and then use $sent_http_XXX:

log_format inc_info '... [$sent_http_x_user_id] ...';
access_log /var/log/nginx/access.log inc_info;

<?php
  header('X-User-ID: ' . head(USER_ID));
?>

Where you should probably use proxy_hide_header to stop those headers being sent to the client.

But this header based approach doesn't work if the headers have already been sent. For example, I use register_shutdown_function() in PHP to log the processing time.


As an aside, if you did just want the processing time, then $upstream_response_time might be useful.


In comparison, this can be done in Apache via:

LogFormat "... [%{USER_ID}n] ..." inc_info
CustomLog /var/log/httpd/access_log inc_info

With the corresponding PHP:

if (function_exists('apache_note')) {
    apache_note('USER_ID', USER_ID);
}

Although apache_note() is only available in mod_php, and it does not work with PHP-FPM.

Best Answer

When using PHP-FPM, you can only send headers, then the content.

So I'm now using a separate log file, one created from PHP, and can be written to at any time - even after the headers and content has been sent.

This is especially useful when using fastcgi_finish_request(), which allows you to return a page to the user (maybe a "loading" page), as your script continues to process data.

To link the web server access log with this new log file, I generate a unique(ish) code for each request, send that as a header (to be logged in the Web Servers access logs), and record it in the PHP log file as well.

More info on the Apache version.