feat(tracer): align C span code with v1-compatible stub API (v2 groundwork) - #4046
feat(tracer): align C span code with v1-compatible stub API (v2 groundwork)#4046Leiyks wants to merge 19 commits into
Conversation
|
Benchmarks [ tracer ]Benchmark execution time: 2026-08-06 14:01:49 Comparing candidate commit 84351df 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 2 performance improvements and 17 performance regressions! Performance is the same for 170 metrics, 1 unstable metrics.
|
2531886 to
b29cd49
Compare
b6b5055 to
10c7edf
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.
10c7edf to
84351df
Compare
What & why
Part of APMLP-1197 (dd-trace-php v1/v2 roadmap). The v1-compatible span
stub API (tracer/ddtrace.stub.php) landed earlier on this branch; this
brings the tracer C code into consistency with it. The v04 wire
format is intentionally kept byte-identical — libdatadog's v1 span
FFI is not yet available, so no wire/protocol switch happens here.
Changes
ddtrace_span_properties / ddtrace_root_span_data / ddtrace_span_stack in
span.h to match the new stub property order (offset parity is
ABI-critical — a mismatch is silent data corruption).
relocated the serialization into serializer.c → _dd.span_links / events
meta blobs are byte-identical.
translated back to meta (component / span.kind) at serialize time, so
the wire is unchanged; new SpanKind class registered.
finished the userland integration-analytics removal (Integration.php +
call sites); deleted orphaned tests and rewrote dd_trace_reset helper
tests without weakening coverage.
Deliberate scope decisions
until libdatadog v1 FFI is ready.
slots (to keep offsets correct) but are left unwired for now.
ZEND_ACC_DEPRECATED flags current gen_stub now emits) to match the
committed convention and avoid runtime E_DEPRECATED on hot paths;
reconciling gen_stub output is a separate follow-up.
Testing
Container build clean; 22 span-shape + 26 curl integration + 30
ConfigurationTest tests passing; links/events wire proven byte-identical.
Draft: pending full CI.
Relationship to the V1 Efficient Trace Payload protocol
This change aligns the userland span API and tracer C with the approved Efficient Trace Payload Protocol RFC and the WIP Tracer Implementation Guide for V1 Trace Payloads, without changing the wire format. The v04 payload remains byte-for-byte the sender's output because the vendored libdatadog exposes the v1 types (
libdd-trace-utils/src/span/v1/mod.rs,pb.idx.rs) only internally — the PHP FFI (components-rs/bytes.rs) still bindsddog_SpanBytes = v04::SpanBytes, so there is no v1 serializer to drive yet.Implemented now (v1-shaped API, v04 wire):
env,version,component,kindexist asSpanDataproperties (RFC idx.Span fields 13–16). Internal C producers set the property; the serializer translatescomponent/spanKindback intometa["component"]/meta["span.kind"]so v04 is unchanged.DDTrace\SpanKindconstants match the OTELSpanKindenum exactly (RFC field 16:kind = otel.SpanKind): UNSPECIFIED=0, INTERNAL=1, SERVER=2, CLIENT=3, PRODUCER=4, CONSUMER=5.Deferred until the v1 FFI lands (groundwork present, unwired):
DD_TRACE_AGENT_PROTOCOL_VERSION∈ {"1.0","1"} and the agent/infoadvertises/v1.0/traces, with mandatory fallback to v04 when absent. Intentionally not added yet to avoid a no-op config key with no serializer behind it.SpanData::$attributes/SpanStack::$attributesreserved; the initial implementation will use String/Float/Bytes and foldmeta/metrics/meta_structinto a single typed map (guide L14–16).traceIDbytes (RFC idx.TraceChunk field 6 / guide L33) andsamplingMechanismas a bare uint32 replacing_dd.p.dm:-N(RFC field 7 / guide L36) —RootSpanData::$samplingMechanismreserved.hostnamepromoted to the TracerPayload (RFC field 8) —RootSpanData::$hostnamereserved; v04 keeps emitting_dd.hostname.erroras bool (RFC idx.Span field 8) and 429 /Datadog-Send-Real-Http-Statusback-off (guide L21–24) — trace sender untouched.Note for the v1 serializer work: the promoted fields have a split source of truth (property for C producers,
metafor userland integrations such as OTelSpanBuilderand Kafka). The v1 serializer must read each promoted value from property-or-meta and remove it from the attributes map, otherwise a v1 payload would carry the value both in the promoted field and in attributes (guide L19).V1 protocol now enabled (behind a flag)
With libdatadog's v1 encoder (#2145) + sidecar transport (#2156) available, this branch now emits the V1 Efficient Trace Payload end-to-end on the sidecar path, gated by
DD_TRACE_AGENT_PROTOCOL_VERSIONand negotiated via agent/info:DD_TRACE_AGENT_PROTOCOL_VERSION=1.0AND the agent/infoadvertising/v1.0/traces->POST /v1.0/traceswith v1 msgpack (proto-field-number keys, streaming string table, promoted env/version/component/span.kind, chunk-level trace_id + sampling_mechanism, typed AnyValue attributes, native span_links/span_events).0.4, or agent doesn't advertise, or info unknown) -> unchangedPOST /v0.4/traces.Depends on the libdatadog PR adding
ddog_send_traces_to_sidecar_v1(based on #2156). Not yet covered: the in-process (non-sidecar, PHP <=8.2) sender path.