WIP: feat(tracer): align C span code with v1-compatible stub API (v2 groundwork) - #4046
WIP: feat(tracer): align C span code with v1-compatible stub API (v2 groundwork)#4046Leiyks wants to merge 39 commits into
Conversation
|
Benchmarks [ tracer ]Benchmark execution time: 2026-09-03 14:30:06 Comparing candidate commit eacc054 in PR branch Some scenarios are present only in baseline or only in candidate runs. If you didn't create or remove some scenarios in your branch, this maybe a sign of crashed benchmarks 💥💥💥 Scenarios present only in baseline:
Found 1 performance improvements and 28 performance regressions! Performance is the same for 160 metrics, 1 unstable metrics.
|
2531886 to
b29cd49
Compare
10c7edf to
84351df
Compare
84351df to
73c262e
Compare
Signed-off-by: Alexandre Rulleau <alexandre.rulleau@datadoghq.com>
Signed-off-by: Alexandre Rulleau <alexandre.rulleau@datadoghq.com>
Bring the tracer C code into consistency with the already-rewritten v1-compatible span stub (tracer/ddtrace.stub.php), keeping the v04 wire format byte-identical (libdatadog v1 FFI is not yet available). - Regenerate ddtrace_arginfo.h from the stub; reorder the ddtrace_span_properties / ddtrace_root_span_data / ddtrace_span_stack structs to match the new property declaration order (PHP property offsets are bound to these C struct fields). - Drop SpanEvent/SpanLink JsonSerializable + jsonSerialize(); relocate that logic into serializer.c so the _dd.span_links / events meta blobs are produced with identical bytes. - Make component/spanKind sourced from the new SpanData properties, translated back into meta (span.kind/component) at serialize time so the v04 wire is unchanged. Register the new SpanKind class. - Remove dead code for stub-removed functions and the DD_TRACE_WARN_LEGACY_DD_TRACE config key; complete the userland integration-analytics removal (Integration.php + call sites); delete tests orphaned by removed functions and rewrite the dd_trace_reset helper tests without gutting their coverage. Refs APMLP-1197.
…DD_TRACE_WARN_LEGACY_DD_TRACE The config key DD_TRACE_WARN_LEGACY_DD_TRACE was removed from tracer/configuration.h, but metadata/supported-configurations.json was not regenerated, causing the 'Configuration Consistency' CI job to fail. Ran tooling/generate-supported-configurations.sh to sync.
RootSpanData extends SpanData, which already declares $env and $version. The v1-stub alignment accidentally re-declared them on RootSpanData (they were never on RootSpanData on master, and the ddtrace_root_span_data C struct has no separate env/version slots -- they are inherited SpanData slots). On PHP < 8.1 this redundant child redeclaration corrupts the RootSpanData property table: env/version are var_dump'd twice and propagatedTags loses its default, breaking tests/ext/active_span.phpt and span_clone.phpt on 7.0-8.0 (they passed on 8.1+). Removing the redeclaration from the stub and arginfo aligns stub=arginfo=C struct and restores consistent output across all versions; env/version remain available on RootSpanData via inheritance.
…on PHP 7
The new `attributes` property (stub default `= []`) was not materialized at
span/stack creation. On PHP < 8.0 array-typed property defaults become null
(see the ZVAL_EMPTY_ARRAY shim in functions.c) and are only lazily turned into
arrays when touched; since `attributes` is never touched during a plain span
lifecycle it var_dump'd as NULL on 7.0-7.4 (array(0){} on 8.0+), breaking
tests/ext/active_span.phpt and span_clone.phpt. Force-materialize it in
ddtrace_init_span and dd_alloc_span_stack (guarded to PHP < 8.0) so it is a
consistent empty array on every supported version, matching its stub default.
The chore that dropped integration (App Analytics) auto-tagging removed Integration::addTraceAnalyticsIfEnabled and the per-integration DD_TRACE_<integration>_ANALYTICS_* config, so the _dd1.sr.eausr metric is no longer auto-added to integration spans. Align the tests: - Delete the 25 TraceSearchConfigTest.php files (Laravel, Lumen, Symfony, ZendFramework, Custom) whose sole subject was the removed per-integration trace-analytics config. - Drop the per-integration analytics setup + _dd1.sr.eausr metric assertions from the mixed PDO and SQLSRV integration tests, preserving all other span coverage. - Remove Curl's dedicated testTraceAnalytics method + its data provider (per-integration analytics config matrix) and the stale DD_CURL_ANALYTICS_ENABLED teardown-cleanup entries in Curl/Guzzle. The user-facing App Analytics API (Span::setMetric(Tag::ANALYTICS_KEY) -> TraceAnalyticsProcessor, Tag::ANALYTICS_KEY constant) is intentionally kept by this branch, so its tests (SpanTest, TraceAnalyticsProcessorTest, UserAvailableConstantsTest, OpenTelemetry, ext/test_special_attributes) are left intact.
Comment-only cleanup of the C span-consistency changes: trim the multi-line explanatory blocks in serializer.c, span.c, handlers_httpstreams.c and tracer_telemetry.c down to concise 1-2 line comments. No behavior change.
The user-facing App Analytics API is now a deprecated no-op: it remains callable (Tag::ANALYTICS_KEY, TraceAnalyticsProcessor, DD_TRACE_ANALYTICS_ENABLED stay defined) but no longer applies any behavior nor emits the _dd1.sr.eausr metric in-process or on the wire. - serializer.c: drop the DD_TRACE_ANALYTICS_ENABLED/web-analytics emission, stop converting the analytics.event meta key to the metric (still consumed), and skip _dd1.sr.eausr in the metrics serialization loop. - TraceAnalyticsProcessor::normalizeAnalyticsValue is now an empty no-op; Tag::ANALYTICS_KEY, the processor, and the api stubs are marked @deprecated. - Tests rewritten to assert the API is callable and emits no _dd1.sr.eausr.
Bump the libdatadog submodule to PR #2156's head (938c110), which brings in the v1 sidecar span encoder/decoder (#2145, #2174) via its main base. Regenerate components-rs/{common,sidecar}.h with cbindgen (exposes the new ddog_sidecar_send_trace_v1_shm / _bytes entrypoints and the ASM_RAW_RESPONSE_BODY remote-config capability) and mirror libdatadog's consolidated [workspace.dependencies] into the root Cargo.toml so the path-dependency crates resolve their { workspace = true } inheritance. Wire format is unchanged: v04 remains the default send path.
… V1 wire Add DD_TRACE_AGENT_PROTOCOL_VERSION (default "0.4"). When set to "1"/"1.0", assemble ddog_TracerMetadataV1 and call ddog_send_traces_to_sidecar_v1; otherwise keep the unchanged V0.4 sidecar send. Hard gate; no /info negotiation.
Regenerate components-rs/*.h and Cargo.lock against the rebased libdatadog submodule (v1 send FFI branch merged with libdatadog main). Picks up the RemoteConfig DEBUG product enum, the v1 FFI comment trims, the agent_info doc-comment tightening, and the zrip/ring lockfile additions.
73c262e to
0d3d03d
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0d3d03d6f7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| static bool dd_v1_native_span_enabled(void) { | ||
| zend_string *pv = get_global_DD_TRACE_AGENT_PROTOCOL_VERSION(); | ||
| return zend_string_equals_literal(pv, "1") || zend_string_equals_literal(pv, "1.0"); |
There was a problem hiding this comment.
Gate native fields on the negotiated V1 path
When the protocol setting is 1/1.0 but agent info is unavailable or does not advertise /v1.0/traces, this helper still moves links and events exclusively into the native V1 fields, while auto_flush.c:75-100 deliberately falls back to the V0.4 sender. The V0.4 encoder expects the JSON values in _dd.span_links and events, so those spans silently lose all links and events during startup, with older agents, and whenever the non-sidecar sender is used. Base this decision on the same negotiated use_v1 condition as the sender, rather than the configuration value alone.
Useful? React with 👍 / 👎.
| zval *meta_env = pre->meta ? zend_hash_str_find(pre->meta, ZEND_STRL("env")) : NULL; | ||
| if (meta_env) { | ||
| pre->env_deprecated = true; | ||
| LOG(DEPRECATED, "Using \"env\" in meta is deprecated. Instead specify the env property directly on the span."); | ||
| zend_string *str = datadog_convert_to_str(meta_env); | ||
| pre->env_deprecated = false; | ||
| zval *prop_env = &span->property_env; |
There was a problem hiding this comment.
Preserve legacy env overrides during precomputation
When a span sets the supported legacy $span->meta['env'] override while its env property contains an inherited process environment, meta_env is now looked up but ignored. Consequently client-side stats are aggregated under the property environment via ddtrace_feed_span_to_concentrator() instead of the environment represented by the span, and the later property write in serializer.c:1914-1915 can replace the meta override on the wire. Restore the documented meta-first selection, even if it remains deprecated.
Useful? React with 👍 / 👎.
| #if PHP_VERSION_ID < 80000 | ||
| // PHP 7 array-typed properties default to null; materialize `attributes` to match its | ||
| // `= []` stub default (as on PHP 8). | ||
| ddtrace_property_array(&span->property_attributes); |
There was a problem hiding this comment.
Initialize attributes in the PHP 7 object creators
On PHP 7 this initialization only runs for spans allocated through the tracer's internal ddtrace_init_span() helper. Public direct construction such as new DDTrace\SpanData() or new DDTrace\RootSpanData() goes through the create_object callbacks in functions.c:244-269 instead, leaving the new attributes property as null because array defaults are deliberately rewritten to null on PHP 7. Directly constructed SpanStack objects have the same problem because their initialization was placed only in dd_alloc_span_stack(). Initialize these properties in the respective object creators so every construction path satisfies the declared array API.
Useful? React with 👍 / 👎.
Stages 3+4 of the v1-native migration. The sidecar sender now always builds a
native libdatadog v1 TracerPayload via the new builder FFI and sends it with
ddog_send_traces_to_sidecar_v1; the sidecar negotiates v1-vs-v0.4 with the agent
and downgrades as needed, so the tracer-side DD_TRACE_AGENT_PROTOCOL_VERSION gate
is removed.
- serializer.c: convert each fully-built v0.4 span into the v1 builder (fields
and meta/metrics/meta_struct via the v0.4 read getters, native links/events
from the still-alive PHP span). Promoted fields (env/version/component/
span.kind) use the dedicated setters and are excluded from the attribute map;
chunk-level fields (sampling priority/origin/mechanism/128-bit trace-id/
dropped) are routed to the chunk. Array/object attribute values, which have no
native v1 attribute variant, are preserved as a JSON string. The v0.4 build
stays byte-identical for the in-process sender and functions.c introspection.
- auto_flush.c: sidecar path always builds the v1 builder and sends v1; shrunk
ddog_TracerMetadataV1 {hostname,env,app_version,runtime_id,git_commit_sha}. The
in-process sender (PHP <= 8.2) stays on v0.4, unchanged.
- Remove the now-dead DD_TRACE_AGENT_PROTOCOL_VERSION config key and the
ddog_agent_info_has_endpoint getter; regenerate datadog.h and
supported-configurations.json.
- Bump libdatadog to the v1 send FFI (317c98d28) and regenerate cbindgen
headers. Add a hand-written prototypes header (sidecar_v1_macro_ffi.h) for the
macro-generated v1 setters that cbindgen cannot emit.
- Update the request-replayer span-event tests to assert native span events.
libdatadog now defines the v1 builder setters as explicit fns instead of declarative-macro-generated ones, so cbindgen emits them into the generated components-rs/sidecar.h. Bump the libdatadog submodule, regenerate sidecar.h (now carries ddog_v1_set_span_* / ddog_v1_add_span_attr_* / ddog_v1_add_event_attr_*), and remove the interim components-rs/sidecar_v1_macro_ffi.h and its include in serializer.c.
…ndgen Bump the libdatadog submodule to 594d5c2ab (LIBDD_V1ONLY branch), which adds ddog_serialize_trace_v1_into_charslice for the in-process (PHP <= 8.2) sender, and regenerate components-rs/sidecar.h via cbindgen. The v1 builder/setter symbols were already present from Stage 1; this only adds the serialize-to-bytes entry point used by the coms.c in-process path.
Port span finalization to populate the native v1 TracerPayload builder directly for the sidecar sender, with no v0.4 intermediate, and reflect the v1 model in introspection. The in-process (<=8.2) background sender keeps its v0.4 build behind an isolated, removable v0.4->v1 transcode layer. - serializer.c: route the single finalization body of ddtrace_serialize_span_to_rust_span through a dd_span_sink that targets either the v0.4 ddog_SpanBytes or the v1 builder chunk/span. Promoted fields (env/version/component/span.kind) go to dedicated v1 setters and chunk-level fields (_dd.origin/_dd.p.dm/_sampling_priority_v1) to the chunk, excluded from the attribute map; _dd.p.tid is carried by the chunk 128-bit trace id. Links/events are emitted natively on v1 (JSON-in -meta only on v0.4). The inferred->root merge uses the typed ddog_v1_transfer_span_attr. Removed dd_v1_convert_span and the removed ddog_v1_intern_string usage (setters now take CharSlice). - exception_serialize.c: error.message/type/stack and exception-replay debug meta write through the sink (v1 span attributes on the sidecar path). - functions.c/serializer.c: dd_trace_serialize_closed_spans reads the v1 builder via the new getters on the sidecar path (dd_serialize_rust_v1_to _zval), reflecting the v1 model (promoted + chunk fields, typed attributes, native links/events); v0.4 introspection unchanged. - auto_flush.c/coms.c/agent_info.c: removable v0.4->v1 bolt-on for the in-process sender: ddtrace_agent_supports_v1_traces() gates transcoding the v0.4 collection via ddog_serialize_trace_v04_as_v1_into_charslice and POSTing to /v1.0/traces; otherwise the existing v0.4 path to /v0.4/traces. - libdatadog: bump to fef26d167 (mutable v1 span-attr FFI); regenerate cbindgen headers.
Bump libdatadog to 3fb12c2c8 (adds ddog_v1_span_debug_log for the V1 builder) and regenerate components-rs/sidecar.h. On the v1 (sidecar) serialization path, emit the DD_TRACE_DEBUG "Encoding span:" diagnostic via ddog_v1_span_debug_log(builder, chunk, span) so the span-encoding log exists on both the v0.4 and v1 paths. Freed with ddog_free_charslice, mirroring the v0.4 branch.
On the v1 (sidecar) path, meta_struct entries are written to the unified V1 attribute map as bytes attributes (ddog_v1_add_span_attr_bytes) and reach the wire correctly, but dd_serialize_rust_v1_to_zval folded them into the generic "attributes" array as opaque strings, so dd_trace_serialize_closed_spans no longer exposed a "meta_struct" key (appsec data appeared missing on introspection). Route bytes-typed span attributes (the only source of bytes attrs on this path) into a dedicated "meta_struct" key, mirroring the v0.4 reader, so meta_struct is visible again with its raw msgpack bytes and meta_struct.phpt passes on both the v0.4 and v1 paths unchanged. Bumps libdatadog to include the v1 attribute-map pre-encode dedup fix.
…sandbox/exceptions, single-span_sampling, client_side_stats) Relocate meta/metrics array access to the unified attributes map introduced by the v1 introspection shape. attributes preserves insertion order (not the old alphabetical meta ordering), which required reordering safe_to_string_metadata's EXPECTF. Filtered iteration to arg.* keys in safe_to_string_metrics/metadata and accept-single-span, since attributes now also carries entrypoint-only tags (_dd.tags.process) that used to live outside meta/metrics.
…root_span_url/http/referrer, extract_*) Relocate meta -> attributes for root_span_url_*, root_span_http_*, security-headers, referrer_extraction_*, and extract_server_values / extract_ip_private_01 / ip_collection_03. span.kind moves to the top-level int span_kind field. Full-array meta dumps are replaced with targeted key/absence checks: the unified attributes map now also carries entrypoint-only telemetry (process_id, php.compilation.total_time_ms, php.memory.*) whose float values are non-deterministic across runs, so dumping the whole map would make these tests flaky. The targeted checks preserve each test's original intent (URL/referrer/post-data extraction) without asserting on unrelated telemetry noise.
…distributed_tracing) Relocate meta -> attributes for the asm_standalone _dd.p.ts checks. distributed_trace_overwrite_active_span needed more than a rename: _dd.origin and the 128-bit trace id high bits are now promoted to dedicated top-level fields (origin, trace_id_high) instead of living in meta/attributes, and trace_id_high is now populated on every span of a 128-bit trace (consistent with trace_id itself being duplicated per span), not only the root. Also filter out the newly-visible per-span telemetry noise (_dd.agent_psr, php.compilation/memory.*) that the unified attributes map now carries.
…svc_*, limiter, debug-log format, misc)
Relocate meta/metrics -> attributes across the remaining tests
(dd_trace_serialize_header_to_meta, http_endpoint_resource_renaming_*,
svc_*, process_tags, git_metadata_injection_from_valid_files).
env/version are promoted to dedicated top-level fields (not nested in
attributes), fixed in ust_precedence_over_ddtags/ust_via_ddtags and
inherit_meta_from_parent. _dd.p.tid is fully replaced by the top-level
trace_id_high field (generate_128_bit_trace_id).
Rewrote the "Encoding span: Span { ... }" debug-log EXPECTF blocks to
the new v1 shape ("Encoding span: trace_id=... kind=... attributes=
{...} links=n events=n") and "Flushing trace" -> "Flushing v1 trace"
in close_spans_until, die_in_sandbox, span_on_close, force_flush_traces,
telemetry/broken_pipe.
limiter/002-limiter-reached and limiter/003-limiter-with-asm-standalone
initially looked like a real regression (_dd.limit_psr computed ~50x
too low): isset($span["attributes"]["_sampling_priority_v1"]) was
always false because that metric is now promoted to the top-level int
"sampling_priority" field, same relocation pattern as span_kind/env/
version/origin, so the test's sample-counting loop ran to its 1000-
iteration safety cap instead of stopping at 20 samples. Verified against
git merge-base (8d9060c): unmodified test passes there 5/5, and
fails deterministically 5/5 at this branch's HEAD with the old
metrics-key access - confirming the fix is the missed relocation, not
a product regression, once sampling_priority is read from the
top-level field.
…n view
Add a PHP v1 msgpack decoder (msgpack_v1_decoder.php) so the deferred PHPUnit
integration tests can assert the v1 wire. The decoder resolves the streaming
string table, maps integer proto field-number keys back to names, and decodes
typed AnyValue values, normalizing a v1 payload back to the canonical
{"chunks":[{"spans":[...]}]} v0.4 per-span shape TracerTestTrait reads:
- un-promotes span env/version/component and span.kind (int->string) into meta;
- reconstructs per-span trace_id (chunk 128-bit low 64 decimal) + meta._dd.p.tid
(high 64 hex), meta._dd.origin, meta._dd.p.dm ("-N"), and
metrics._sampling_priority_v1 from the chunk-level fields onto the local root;
- splits the unified attributes map into meta (String), metrics (Int/Double),
meta_struct (Bytes); native span_links/span_events -> meta._dd.span_links /
meta.events JSON (the prior v0.4 contract).
index.php dispatches /v1.0/traces to the new decoder and keeps the existing
v0.4 path for /v0.4/traces; /info now advertises /v1.0/traces by default so the
sidecar (8.3+) and in-process (<=8.2) senders negotiate v1, while
/set-agent-info overrides still win.
dd_trace_serialize_closed_spans() previously read the native V1 builder only when the sidecar sender was active (PHP 8.3+) and the V0.4 model otherwise, so its output shape depended on the active sender / PHP version. Introspection is a debug view: always finalize spans into the in-memory V1 builder and read them back via the V1 getters, regardless of which sender performs the wire flush. The V1 builder needs no active sidecar, so this is version-independent; the <=8.2 wire flush stays on the V0.4 background sender.
The meta["env"]/meta["version"] deprecation path was already removed from ddtrace_precompute_span (env/version now come from the span property only), but left behind: two unused meta lookups, the env_deprecated/version_deprecated precomputed fields (permanently false), and the now always-true guards gating them in the serializer. Remove all of it. Also drop the unused AsBytes import in components-rs/agent_info.rs.
With introspection now uniformly V1-shaped, update the remaining tests/ext .phpt expectations that still asserted the V0.4 shape. Bodies read the unified attributes map (old meta + metrics merged); var_dump/JSON blocks gain top-level trace_id_high and span_kind, rename meta->attributes with real v1 insertion order, use native span_links/span_events arrays, and surface meta_struct under its own key. _dd.p.tid meta is dropped (now top-level trace_id_high) and the trace-flush debug log reads 'Flushing v1 trace'. The shared dd_dumper.inc / fake_tracer.inc helpers read attributes (string-valued only, preserving the historic meta-only view). tests/ext is fully green on the default config.
| // write through a dd_span_sink. On the in-process (<=8.2) path the sink targets a V0.4 ddog_SpanBytes | ||
| // (also read back by functions.c introspection); on the sidecar path it targets the native V1 builder | ||
| // chunk/span directly, with no V0.4 intermediate. The V1 routing promotes env/version/component/ |
There was a problem hiding this comment.
No, we want v1 only, and have libdatadog convert back from v1 to v0.4 if needed, after creating the native spans.
Completely get rid of any v04 stuff in serializer. That's for auto_flush.c.
| if (DD_CS_EQ(key, "_dd.span_links") || DD_CS_EQ(key, "events")) { return true; } | ||
| if (DD_CS_EQ(key, "_dd.origin")) { ddog_v1_set_chunk_origin(b, s->chunk, value); return true; } | ||
| if (DD_CS_EQ(key, "_dd.p.dm")) { | ||
| // v0.4 form is "-N"; the mechanism is the trailing unsigned integer. | ||
| const char *p = value.ptr; size_t n = value.len; | ||
| if (n && *p == '-') { p++; n--; } | ||
| uint32_t mech = 0; | ||
| for (size_t i = 0; i < n; i++) { if (p[i] < '0' || p[i] > '9') { mech = 0; break; } mech = mech * 10 + (uint32_t)(p[i] - '0'); } | ||
| ddog_v1_set_chunk_sampling_mechanism(b, s->chunk, mech); | ||
| return true; | ||
| } | ||
| // 128-bit trace-id high half is carried by the chunk trace id, not a span attribute. | ||
| if (DD_CS_EQ(key, "_dd.p.tid")) { return true; } |
There was a problem hiding this comment.
users aren't really supposed to touch that stuff at all. No conversion needed.
| if (DD_CS_EQ(key, "env")) { ddog_v1_set_span_env(b, s->chunk, s->span, value); return true; } | ||
| if (DD_CS_EQ(key, "version")) { ddog_v1_set_span_version(b, s->chunk, s->span, value); return true; } | ||
| if (DD_CS_EQ(key, "component")) { ddog_v1_set_span_component(b, s->chunk, s->span, value); return true; } | ||
| if (DD_CS_EQ(key, "span.kind")) { ddog_v1_set_span_kind(b, s->chunk, s->span, dd_span_kind_meta_to_otel(value)); return true; } |
There was a problem hiding this comment.
We should check the values on the meta of the PHP span directly, discard them from meta (via _find+_del) and have the actual serialization only look at taking the values from the span properties, bypassing meta fully, avoiding individual checks during iteration.
…n headers Pull in libdatadog's replacement of the per-field SpanBytes mutator FFI with direct TracerPayloadV1Builder access and the ddog_downgrade_v1_builder_to_v04_traces API. Rewrite components-rs/ bytes.rs against the new builder-based FFI surface and regenerate components-rs/datadog.h + sidecar.h via cbindgen.
Rework serializer.c/.h to fill the V1 TracerPayloadV1Builder through
the new direct-builder FFI (ddog_new_chunk/ddog_new_span/
ddog_span_set_*/ddog_add_span_attr_*) instead of the removed
per-field SpanBytes mutators, dropping ~550 lines of now-dead
hand-rolled v0.4 field plumbing. Adjust span.h/span_stats.{c,h} for
the fields the V1 builder now owns directly.
…r default
auto_flush.c/coms.{c,h}: the in-process (PHP <= 8.2) sender always
downgrades a V1 builder to v0.4 traces via
ddog_downgrade_v1_builder_to_v04_traces and frames each decoded trace
individually, matching the sidecar's own v1->v0.4 downgrade path.
generate-supported-configurations.sh: DD_SIDECAR_TRACE_SENDER_DEFAULT
is now unconditionally true (no more PHP-version gate), regenerate
metadata/supported-configurations.json to match.
DD_SIDECAR_TRACE_SENDER_DEFAULT is now true unconditionally instead of only for PHP >= 8.3/_WIN32; the in-process coms.c sender remains available via an explicit DD_TRACE_SIDECAR_TRACE_SENDER=0 opt-in. Document the pcntl_fork() caveat for forking apps on <=8.2 that relied on the old in-process default.
Update background-sender/agent_* and request-replayer span-event
.phpt expectations for the V1 payload shape. Add new coverage:
serializer_wire_{inprocess_v04,inprocess_v1,sidecar_v1} for the wire
format on each sender path, client_side_stats_dd_tags_env /
_inferred_span_sampling, and env/span-kind meta-fallback promotion
tests.
agent_info.h declares a bool-returning function but is the first include in agent_info.c; PHP 7.x zend_types.h does not pull in <stdbool.h>, so the tracer C failed to compile on 7.0-7.4 (Linux + Windows MSVC). Also bumps the libdatadog submodule to the rustfmt-clean commit.
Trim verbose comment blocks added by the V1 trace-protocol pivot to the house terse style (non-obvious WHY only); no code changes. Bump the libdatadog submodule to the matching comment-only commit.
Migrate the tracer to the V1 Efficient Trace Payload protocol.
dd_span_sinkfinalization body (no v04 intermediate): promotedenv/version/component/span.kind, chunk-level 128-bittrace_id+sampling_mechanism, unified typedattributes(incl.meta_structas bytes), nativespan_links/span_events./infodoesn't advertise/v1.0/traces, the sidecar transcodes v1→v0.4 (existing libdatadog encoder). Isolated + removable — dropping v0.4 later = delete the/infocheck + the transcode call.dd_trace_serialize_closed_spans) returns the v1 shape uniformly on all versions;DD_TRACE_AGENT_PROTOCOL_VERSIONgate removed./v1.0/traces;tests/extexpectations updated to v1 (603 passing).Depends on libdatadog #2311. Follow-ups: native array/map AnyValue attributes (currently JSON-string),
process_tagsas a payload attribute, sidecar 404 fail-closed hardening.