Skip to content

Commit e13d9bc

Browse files
committed
tests: fix sidecar agent-info timing races in request-replayer and debugger tests
Replace unreliable dummy-flush + sleep synchronization with the dd_trace_internal_fn('await_agent_info') primitive (already used in client_side_stats.phpt) which polls ddog_is_agent_info_ready() until the sidecar has received and applied the agent /info response. - client_side_stats_peer_tags.phpt: drop dummy flush, use await_agent_info - client_side_stats_trace_filters.phpt: drop dummy flush, use await_agent_info - dd_trace_agent_env.phpt: replace broken floor(delta)*100000 sleep with await_agent_info - debugger_metric_probe.phpt: add 100ms pause after probe installation to let sidecar finish wiring the DogStatsD endpoint before foo() fires
1 parent 9a2b413 commit e13d9bc

4 files changed

Lines changed: 26 additions & 36 deletions

File tree

tests/ext/live-debugger/debugger_metric_probe.phpt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ $span = await_probe_installation(function() {
3434
return \DDTrace\start_span(); // submit span data
3535
});
3636

37+
// Give the sidecar a moment to fully wire the probe before invoking foo().
38+
// await_probe_installation() detects the hook install but the sidecar may still be
39+
// finalising the DogStatsD endpoint binding on first use.
40+
usleep(100000); // 100 ms
41+
3742
foo();
3843

3944
$server->dump(1);

tests/ext/request-replayer/client_side_stats_peer_tags.phpt

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,10 @@ include __DIR__ . '/../includes/request_replayer.inc';
3939

4040
$rr = new RequestReplayer();
4141

42-
// Flush a dummy trace and wait for the sidecar to process it. The sidecar polls the agent
43-
// /info endpoint on the same interval, so by the time we return here it will have written
44-
// the peer_tags from the agent info (set in SKIPIF) to the shared-memory segment that
45-
// ddog_apply_agent_info_concentrator_config reads.
46-
$dummy = \DDTrace\start_trace_span();
47-
$dummy->name = "dummy";
48-
$dummy->service = "dummy-service";
49-
\DDTrace\close_span();
50-
dd_trace_internal_fn('synchronous_flush');
51-
$rr->waitForDataAndReplay();
42+
// Block until the sidecar has received and applied the agent /info response (which carries
43+
// peer_tags set in SKIPIF). This ensures ddog_apply_agent_info_concentrator_config() will
44+
// pick up the peer_tags from the SHM segment before the concentrator processes our span.
45+
dd_trace_internal_fn('await_agent_info');
5246

5347
// Now create the span whose stats we want to inspect. When this span is fed to the
5448
// concentrator, ddog_apply_agent_info_concentrator_config() is called first, picks up

tests/ext/request-replayer/client_side_stats_trace_filters.phpt

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ if (PHP_VERSION_ID >= 80100) {
88
echo "nocache\n";
99
}
1010
// Configure the request-replayer to return these filter rules from the /info endpoint.
11-
// The sidecar will pick them up on its next poll cycle (triggered by the dummy flush below).
11+
// The sidecar will pick them up on its next poll cycle; await_agent_info() in --FILE--
12+
// blocks until the sidecar has applied the config before any test spans are flushed.
1213
//
1314
// Filters configured:
1415
// filter_tags.require: filter_required:yes
@@ -60,15 +61,10 @@ include __DIR__ . '/../includes/request_replayer.inc';
6061

6162
$rr = new RequestReplayer();
6263

63-
// Flush a dummy trace so the sidecar polls /info and picks up the filter config that was
64-
// written to the request-replayer in SKIPIF. By the time waitForDataAndReplay() returns
65-
// the sidecar has had at least one poll cycle.
66-
$dummy = \DDTrace\start_trace_span();
67-
$dummy->name = 'dummy';
68-
$dummy->service = 'dummy-service';
69-
\DDTrace\close_span();
70-
dd_trace_internal_fn('synchronous_flush');
71-
$rr->waitForDataAndReplay();
64+
// Block until the sidecar has received and applied the agent /info response (which carries
65+
// the filter_tags / filter_tags_regex / ignore_resources config set in SKIPIF). This
66+
// guarantees the filter rules are in place before any test spans are flushed.
67+
dd_trace_internal_fn('await_agent_info');
7268

7369
// Each test case is a separate root span (= separate trace), because trace filters are
7470
// evaluated per trace (root span properties / tags).
@@ -123,26 +119,24 @@ makeSpan('op.blocked.regex_require', 'GET /other4', [
123119

124120
dd_trace_internal_fn('synchronous_flush');
125121

126-
// Capture ALL trace requests from the second flush before consuming them.
127-
// The first flush's data was already consumed by waitForDataAndReplay() above, so only
128-
// second-flush requests remain. Poll until at least one trace request arrives, then
129-
// collect everything that arrived in that batch.
130-
$secondFlushTraces = [];
122+
// Capture ALL trace requests from this flush before consuming them.
123+
// Poll until at least one trace request arrives, then collect everything in that batch.
124+
$flushTraces = [];
131125
for ($i = 0; $i < 1000; $i++) {
132126
usleep(50000); // 50 ms (same interval as RequestReplayer::flushInterval)
133127
$reqs = $rr->replayAllRequests() ?? [];
134128
$traces = array_values(array_filter($reqs, function ($r) {
135129
return strpos($r['uri'] ?? '', 'traces') !== false;
136130
}));
137131
if (!empty($traces)) {
138-
$secondFlushTraces = $traces;
132+
$flushTraces = $traces;
139133
break;
140134
}
141135
}
142136

143137
// Extract span names from every trace request in this flush.
144138
$namesInTraces = [];
145-
foreach ($secondFlushTraces as $req) {
139+
foreach ($flushTraces as $req) {
146140
$body = json_decode($req['body'] ?? '', true);
147141
if (!is_array($body)) continue;
148142
if (isset($body['chunks'])) {
@@ -170,9 +164,8 @@ foreach (array_keys($namesInTraces) as $n) {
170164
}
171165

172166
// Wait for a stats payload that contains our service.
173-
// Stats from the second flush arrive a few seconds after waitForDataAndReplay() returns;
174-
// use a matcher so we wait for the right payload rather than returning the first one
175-
// (which contains the dummy span from the first flush).
167+
// Use a matcher to wait for the right payload rather than returning the first one
168+
// (SKIPIF may have generated earlier requests under this token).
176169
$statsRequest = $rr->waitForStats(function ($request) {
177170
$payload = json_decode($request['body'], true);
178171
foreach ($payload['Stats'] ?? [] as $bucket) {

tests/ext/request-replayer/dd_trace_agent_env.phpt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,10 @@ $rr = new RequestReplayer();
3636

3737
$span = \DDTrace\start_span();
3838

39-
// make sure sidecar keeps up with us
40-
$start = microtime(true);
41-
\DDTrace\start_trace_span();
42-
\DDTrace\close_span();
43-
$rr->waitForDataAndReplay();
44-
usleep(floor(microtime(true) - $start) * 100000);
39+
// Block until the sidecar has received and applied the agent /info response (which carries
40+
// default_env set in SKIPIF). This ensures $span->env reflects the agent-provided env
41+
// before we read it.
42+
dd_trace_internal_fn('await_agent_info');
4543

4644
\DDTrace\close_span();
4745
var_dump($span->env);

0 commit comments

Comments
 (0)