Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitlab/generate-common.php
Original file line number Diff line number Diff line change
Expand Up @@ -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", "<?= $service_bind_address ?>:80", "index.php"]
variables:
Expand Down
20 changes: 17 additions & 3 deletions dockerfiles/services/request-replayer/src/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
Expand Down Expand Up @@ -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');
Expand All @@ -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':
Expand All @@ -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;
Expand Down
49 changes: 24 additions & 25 deletions tests/ext/crashtracker_segfault_disabled.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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
9 changes: 9 additions & 0 deletions tests/ext/includes/request_replayer.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Loading