diff --git a/.gitlab/generate-common.php b/.gitlab/generate-common.php index 7cb36765ea5..009673d1e91 100644 --- a/.gitlab/generate-common.php +++ b/.gitlab/generate-common.php @@ -104,7 +104,7 @@ function dockerhub_login() { SNAPSHOT_REGEX_PLACEHOLDERS: 'path:/\S+/dd-trace-php(?=/),httpbin:(?<=//)httpbin-integration:8080' request-replayer: - name: registry.ddbuild.io/images/mirror/datadog/dd-trace-ci:php-request-replayer-2.0@sha256:4f26c11d568d2401bdd35d592aeff003b89b289e525166ee5ad376066877e4ad + name: registry.ddbuild.io/images/mirror/datadog/dd-trace-ci:php-request-replayer-2.0 alias: request-replayer command: ["php", "-S", ":80", "index.php"] variables: diff --git a/dockerfiles/services/request-replayer/src/index.php b/dockerfiles/services/request-replayer/src/index.php index 43ec981cda0..c40105a0b97 100644 --- a/dockerfiles/services/request-replayer/src/index.php +++ b/dockerfiles/services/request-replayer/src/index.php @@ -76,6 +76,7 @@ function decodeDogStatsDMetrics($metrics) define('REQUEST_NEXT_RESPONSE_FILE', getenv('REQUEST_NEXT_RESPONSE_FILE') ?: ("$temp_location/response.json")); define('REQUEST_LOG_FILE', getenv('REQUEST_LOG_FILE') ?: ("$temp_location/requests-log.txt")); define('REQUEST_RC_CONFIGS_FILE', getenv('REQUEST_RC_CONFIGS_FILE') ?: ("$temp_location/rc_configs.json")); +define('REQUEST_RC_REQUESTS_FILE', getenv('REQUEST_RC_REQUESTS_FILE') ?: ("$temp_location/rc_requests.json")); define('REQUEST_METRICS_FILE', getenv('REQUEST_METRICS_FILE') ?: ("$temp_location/metrics.json")); define('REQUEST_METRICS_LOG_FILE', getenv('REQUEST_METRICS_LOG_FILE') ?: ("$temp_location/metrics-log.txt")); define('REQUEST_AGENT_INFO_FILE', getenv('REQUEST_AGENT_INFO_FILE') ?: ("$temp_location/agent-info.txt")); @@ -124,6 +125,16 @@ function logRequest($message, $data = '') unlink(REQUEST_METRICS_LOG_FILE); logRequest('Returned last metrics and deleted metrics log', $request); break; + case '/replay-rc-requests': + if (!file_exists(REQUEST_RC_REQUESTS_FILE)) { + logRequest('Cannot replay RC requests; RC requests log does not exist'); + break; + } + $request = file_get_contents(REQUEST_RC_REQUESTS_FILE); + echo $request; + unlink(REQUEST_RC_REQUESTS_FILE); + logRequest('Returned RC requests and deleted RC requests log', $request); + break; case '/clear-dumped-data': if (!file_exists(REQUEST_LATEST_DUMP_FILE) && !file_exists(REQUEST_METRICS_FILE) && !file_exists(REQUEST_RC_CONFIGS_FILE)) { logRequest('Cannot delete request log; request log does not exist'); @@ -146,6 +157,9 @@ function logRequest($message, $data = '') if (file_exists(REQUEST_AGENT_INFO_FILE)) { unlink(REQUEST_AGENT_INFO_FILE); } + if (file_exists(REQUEST_RC_REQUESTS_FILE)) { + unlink(REQUEST_RC_REQUESTS_FILE); + } logRequest('Deleted request log'); break; case '/next-response': @@ -164,13 +178,13 @@ function logRequest($message, $data = '') $request = file_get_contents('php://input'); logRequest("Requested remote config", $request); - if (file_exists(REQUEST_LATEST_DUMP_FILE)) { - $tracesStack = json_decode(file_get_contents(REQUEST_LATEST_DUMP_FILE), true); + if (file_exists(REQUEST_RC_REQUESTS_FILE)) { + $tracesStack = json_decode(file_get_contents(REQUEST_RC_REQUESTS_FILE), true); } else { $tracesStack = []; } $tracesStack[] = ['uri' => $_SERVER['REQUEST_URI'], 'headers' => getallheaders(), 'body' => $request]; - file_put_contents(REQUEST_LATEST_DUMP_FILE, json_encode($tracesStack)); + file_put_contents(REQUEST_RC_REQUESTS_FILE, json_encode($tracesStack)); $request = json_decode($request, true); $recentUpdate = @filemtime(REQUEST_RC_CONFIGS_FILE) > time() - 2; diff --git a/tests/ext/crashtracker_segfault_disabled.phpt b/tests/ext/crashtracker_segfault_disabled.phpt index 654a966632b..79e754a9182 100644 --- a/tests/ext/crashtracker_segfault_disabled.phpt +++ b/tests/ext/crashtracker_segfault_disabled.phpt @@ -21,42 +21,41 @@ datadog.trace.agent_test_session_token=tests/ext/crashtracker_segfault_disabled. include __DIR__ . '/includes/request_replayer.inc'; $rr = new RequestReplayer(); -$rr->replayRequest(); // cleanup possible leftover +$rr->clearDumpedData(); // ensure clean state usleep(100000); // Let time to the sidecar to open the crashtracker socket $php = getenv('TEST_PHP_EXECUTABLE'); $args = getenv('TEST_PHP_ARGS')." ".getenv("TEST_PHP_EXTRA_ARGS"); -$cmd = $php." ".$args." -r 'posix_kill(posix_getpid(), 11);'"; +$cmd = $php." ".$args." -r 'posix_kill(posix_getpid(), 11);' 2>/dev/null"; system($cmd); -$rr->waitForRequest(function ($request) { - if ($request["uri"] != "/telemetry/proxy/api/v2/apmtelemetry") { - return false; - } - $body = json_decode($request["body"], true); - $batch = $body["request_type"] == "message-batch" ? $body["payload"] : [$body]; - - foreach ($batch as $json) { - if ($json["request_type"] != "logs" || !isset($json["payload"]["logs"])) { +// Poll up to 5s to confirm no crash report (is_crash:true) arrives. +$crashReportFound = false; +for ($i = 0; $i < 10 && !$crashReportFound; $i++) { + usleep(500000); + foreach ($rr->replayAllRequests() ?: [] as $request) { + if ($request["uri"] != "/telemetry/proxy/api/v2/apmtelemetry") { continue; } - - foreach ($json["payload"]["logs"] as $payload) { - $payload["message"] = json_decode($payload["message"], true); - $output = json_encode($payload, JSON_PRETTY_PRINT); - - echo $output; - - return true; + $body = json_decode($request["body"], true); + $batch = $body["request_type"] == "message-batch" ? $body["payload"] : [$body]; + foreach ($batch as $json) { + if ($json["request_type"] != "logs" || !isset($json["payload"]["logs"])) { + continue; + } + foreach ($json["payload"]["logs"] as $payload) { + if ($payload["is_crash"] ?? false) { + $crashReportFound = true; + break 3; + } + } } } +} - return false; -}); +echo $crashReportFound ? "FAIL: unexpected crash report sent\n" : "OK\n"; ?> ---EXPECTF-- -%A -Fatal error: Uncaught Exception: wait for replay timeout in %s -%A +--EXPECT-- +OK diff --git a/tests/ext/includes/request_replayer.inc b/tests/ext/includes/request_replayer.inc index 609a0c075af..0e0d8113362 100644 --- a/tests/ext/includes/request_replayer.inc +++ b/tests/ext/includes/request_replayer.inc @@ -104,6 +104,15 @@ class RequestReplayer ])), true); } + public function clearDumpedData() + { + file_get_contents($this->endpoint . '/clear-dumped-data', false, stream_context_create([ + "http" => [ + "header" => "X-Datadog-Test-Session-Token: " . ini_get("datadog.trace.agent_test_session_token"), + ], + ])); + } + public function replayHeaders($showOnly = []) { $request = $this->waitForDataAndReplay();