Apache Web Server Generate Unique ID for Every Request
A unique identifier for each request is super useful when you want to trace requests of your web application for debugging. For instance if you have a logging system, you can search through a particular request ID to debug logs representing everything that happened throughout the lifetime of a request.
mod_unique_id
The Apache HTTP Server makes this possible with the mod_unique_id
server module. Once enabled, httpd
starts setting an environment variable called UNIQUE_ID
for every incoming request.
If you’re running a PHP web site/application then this is how you can retrieve it:
// Prints `Xq543Ab3gAxREC-cR-KlHAAAAAg`
echo $_SERVER['UNIQUE_ID'];
The documentation page explains how the identifier is as unique as possible in detail. To summarize, encodes the following data points:
- 32-bit IP Address.
- 32 bit process ID (pid generated by the operating system).
- 32 bit timestamp, UTC in seconds (when the request was received).
- A 16 bit counter in case of timestamp and pid reuse.
- 32 bit thread index to identify threads (and differ across them).
All the information above is encoded like base64, only difference being in the characters used – [A-Za-z0-9@-]
is replaced with [A-Za-z0-9+/]
.
Logging
If you want the unique request IDs to end up in your access logs then just add %{UNIQUE_ID}e
to the LogFormat
.
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" %{UNIQUE_ID}e" combined
CustomLog /var/log/apache2/access.log combined
Headers
Sometimes it is desired to set a request header with the unique ID for reasons like third party compatibility, legacy code, etc. This can be achieved with the mod_headers
module. Once enabled, all you’ve to do is set the header with the environment variable’s value.
# In server config, virtual host, directory, file, location or .htaccess
RequestHeader set "X-Request-Id" "%{UNIQUE_ID}e"
Now with every request, httpd
will add a request header called X-Request-Id
containing the unique ID generated by mod_unique_id
module. Reading it in PHP is super easy:
echo $_SERVER['HTTP_X_REQUEST_ID'];
// or
echo getallheaders()['X-Request-Id'];