Request IDs
Every request OxPHP processes gets a unique identifier for tracing and log correlation. The ID appears in response headers and access logs, so you have one value to follow a request across every layer of your stack.
How it works
OxPHP assigns an ID to each incoming request before anything else runs. If the client already sent an X-Request-ID header (say, from a load balancer or API gateway), OxPHP validates that value and keeps it. To pass validation the header must be 1–64 characters long and contain only alphanumerics, hyphens (-), underscores (_), or dots (.). Anything that fails is replaced with a freshly generated ID.
When no valid X-Request-ID arrives, OxPHP generates a 20-character lowercase hexadecimal ID such as 67890abc12341a2b0042. The value encodes a timestamp, a process-unique value, and a monotonic counter, so collisions across containers and restarts are extremely unlikely.
From there the ID travels with the request:
- It goes out in the
X-Request-IDresponse header on every response. - When access logging is enabled, it appears in the
request_idfield of every access log entry. - PHP scripts can read it via
oxphp_request_id().
Response header
Every HTTP response from OxPHP includes the X-Request-ID header:
HTTP/1.1 200 OK
X-Request-ID: 67890abc12341a2b0042
Content-Type: text/html; charset=utf-8When an upstream load balancer or gateway provides an X-Request-ID on the incoming request, OxPHP echoes the same value back in the response, so traceability holds end to end across your infrastructure.
Reading the request ID from PHP
Read the current request ID with oxphp_request_id():
<?php
$requestId = oxphp_request_id();
// Include in application logs for correlation
$logger->info('Processing order', [
'request_id' => $requestId,
'order_id' => $orderId,
]);Forward the request ID to downstream services to keep traceability across API calls:
<?php
$requestId = oxphp_request_id();
$ch = curl_init('https://api.example.com/users');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"X-Request-ID: $requestId",
]);
$response = curl_exec($ch);
curl_close($ch);Access log entries
When access logging is enabled, every log entry includes the request_id field:
{
"timestamp": "2026-02-11T12:34:56.789Z",
"level": "INFO",
"fields": {
"request_id": "67890abc12341a2b0042",
"method": "GET",
"path": "/api/users",
"status": 200,
"duration_us": 1234,
"remote_ip": "10.0.0.1",
"message": "request completed"
}
}Filter your log aggregator by request_id to trace the full lifecycle of a single request, including any PHP errors or application log entries that reference the same ID.
Troubleshooting
The `X-Request-ID` header is missing from responses
This is unexpected. OxPHP adds the header to every response, so if it is missing, an intermediate proxy is probably stripping it.
Check: Test directly against OxPHP without any proxy in the path:
curl -v http://localhost:8080/ 2>&1 | grep -i x-request-idAn upstream ID is not being preserved
The incoming X-Request-ID value may be failing validation. OxPHP rejects IDs that are empty, longer than 64 characters, or contain characters other than alphanumerics, hyphens, underscores, or dots.
Check: Inspect the value your upstream sends and verify it meets the character and length requirements. Common failures include values with slashes, spaces, or brace characters.
`oxphp_request_id()` returns an empty string
This function is only available within OxPHP. If you run the same PHP code under PHP-FPM or CLI, the function is not defined. Guard calls with a compatibility check:
<?php
$requestId = function_exists('oxphp_request_id')
? oxphp_request_id()
: ($_SERVER['HTTP_X_REQUEST_ID'] ?? uniqid('', true));See also
- Access Logging — every log entry includes the
request_idfield - PHP Functions — full reference for
oxphp_request_id()and other built-in functions