Skip to content

feat(tracer): send traces as V1 payloads through the libdatadog builder FFI - #4046

Draft
Leiyks wants to merge 5 commits into
masterfrom
leiyks/dd-trace-php-v2
Draft

Leiyks wants to merge 5 commits into
masterfrom
leiyks/dd-trace-php-v2

Conversation

@Leiyks

@Leiyks Leiyks commented Jul 17, 2026 •

Copy link
Copy Markdown
Contributor

Migrate the tracer to the V1 Efficient Trace Payload protocol (APMLP-1197). Depends on DataDog/libdatadog#2311: the libdatadog submodule is pinned to that PR's head and must be re-pinned to the merge commit once it lands.

  • Sidecar sender: closed spans are serialized into a libdatadog V1 payload builder (Box-per-node pointer handles) and sent to /v1.0/traces. The sidecar negotiates /info and downgrades to v0.4 when the agent does not advertise /v1.0/traces. The new DD_TRACE_AGENT_PROTOCOL_VERSION=0.4 forces v0.4.
  • Top-level: as the V1 implementation guide requires, the tracer marks top-level spans with _dd.top_level and sends client_computed_top_level; the snapshots now include it.
  • In-process sender: keeps the v0.4 wire, downgraded from the same builder.
  • Span tags: one typed attributes store. SpanData::$meta and $metrics are views onto the new $attributes, with promoted $env/$version/$component/$spanKind properties, native nested attributes for span links and events, and meta_struct as bytes. Process tags (_dd.tags.process) and the OTLP export marker (_dd.sdk.otlp_export) are payload attributes; _dd.git.* is set on the payload and on root spans.
  • Introspection: dd_trace_serialize_closed_spans() returns the V1 shape on every PHP version and the tests are migrated to it. dd_trace_serialize_msgpack() and dd_trace_send_traces_via_thread() are removed, along with their tests and the background-sender tests built on them.
  • Request-replayer gets a V1 decoder and advertises /v1.0/traces.

Behaviour changes users will notice:

  • The sidecar is now the default trace sender on all PHP versions (it was 8.3+/Windows only); DD_TRACE_SIDECAR_TRACE_SENDER=0 opts back into the in-process sender.
  • Web root spans default component to the SAPI name (frameworks still override it).
  • App Analytics is dropped from the userland integrations: TraceAnalyticsProcessor::normalizeAnalyticsValue is a deprecated no-op, Tag::ANALYTICS_KEY is deprecated, an analytics.event tag is still mapped to _dd1.sr.eausr, and the TraceSearch config tests are removed.
  • DD_TRACE_WARN_LEGACY_DD_TRACE is removed.

For reviewers:

@datadog-datadog-prod-us1-2

datadog-datadog-prod-us1-2 Bot commented Jul 17, 2026 •

Copy link
Copy Markdown

Pipelines  Tests

✨ Unblock PR with BitsAI

❌ Errors

Your PR has failed checks. Please review the issues below and take necessary action before merging.

🚦 5 Pipeline jobs failed

DataDog/apm-reliability/dd-trace-php | System Tests: [parametric] — ❌ 81 tests failed

View more details · View in GitLab

❌ tests.parametric.test_otel_api_interoperability.Test_Otel_API_Interoperability.test_concurrent_traces_in_order[library_env0, parametric-php] from system_tests_suite
ValueError: Number (2) of traces not available from test agent, got None:
[]

self = <tests.parametric.test_otel_api_interoperability.Test_Otel_API_Interoperability object at 0x7fa86215d3a0>
test_agent = <utils.docker_fixtures._test_agent.TestAgentAPI object at 0x7fa860ede150>
test_library = <utils.docker_fixtures._test_clients._test_client_parametric.ParametricTestClientApi object at 0x7fa8611ea300>

    def test_concurrent_traces_in_order(self, test_agent: TestAgentAPI, test_library: APMLibrary):
        """- Basic concurrent traces and spans"""
        with (
...
❌ tests.parametric.test_otel_api_interoperability.Test_Otel_API_Interoperability.test_concurrent_traces_nested_dd_root[library_env0, parametric-php] from system_tests_suite
ValueError: Number (2) of traces not available from test agent, got None:
[]

self = <tests.parametric.test_otel_api_interoperability.Test_Otel_API_Interoperability object at 0x7fa8620a4950>
test_agent = <utils.docker_fixtures._test_agent.TestAgentAPI object at 0x7fa860ede150>
test_library = <utils.docker_fixtures._test_clients._test_client_parametric.ParametricTestClientApi object at 0x7fa8611d7e60>

    def test_concurrent_traces_nested_dd_root(self, test_agent: TestAgentAPI, test_library: APMLibrary):
        """- Concurrent traces with nested start/end, with the first trace being opened with the Datadog API"""
        with (
...
❌ tests.parametric.test_otel_api_interoperability.Test_Otel_API_Interoperability.test_concurrent_traces_nested_otel_root[library_env0, parametric-php] from system_tests_suite
ValueError: Number (2) of traces not available from test agent, got None:
[]

self = <tests.parametric.test_otel_api_interoperability.Test_Otel_API_Interoperability object at 0x7fa86215d7f0>
test_agent = <utils.docker_fixtures._test_agent.TestAgentAPI object at 0x7fa860ede150>
test_library = <utils.docker_fixtures._test_clients._test_client_parametric.ParametricTestClientApi object at 0x7fa86120dc40>

    def test_concurrent_traces_nested_otel_root(self, test_agent: TestAgentAPI, test_library: APMLibrary):
        """- Concurrent traces with nested start/end, with the first trace being opened with the OTel API"""
        with (
...
❌ tests.parametric.test_otel_api_interoperability.Test_Otel_API_Interoperability.test_datadog_start_after_otel_span[library_env0, parametric-php] from system_tests_suite
ValueError: Number (1) of traces not available from test agent, got None:
[]

self = <tests.parametric.test_otel_api_interoperability.Test_Otel_API_Interoperability object at 0x7fa8620ebb60>
test_agent = <utils.docker_fixtures._test_agent.TestAgentAPI object at 0x7fa860ede150>
test_library = <utils.docker_fixtures._test_clients._test_client_parametric.ParametricTestClientApi object at 0x7fa8611dc500>

    def test_datadog_start_after_otel_span(self, test_agent: TestAgentAPI, test_library: APMLibrary):
        """- Start a span using the Datadog API while a span created using the OTel API already exists"""
        with test_library, test_library.otel_start_span(name="otel_span", span_kind=SpanKind.INTERNAL) as otel_span:
...
❌ tests.parametric.test_otel_api_interoperability.Test_Otel_API_Interoperability.test_distributed_headers_are_propagated_tracecontext[library_env0, parametric-... from system_tests_suite
KeyError: '_dd.p.dm'

self = <tests.parametric.test_otel_api_interoperability.Test_Otel_API_Interoperability object at 0x7fa8620a7170>
test_agent = <utils.docker_fixtures._test_agent.TestAgentAPI object at 0x7fa860ede150>
test_library = <utils.docker_fixtures._test_clients._test_client_parametric.ParametricTestClientApi object at 0x7fa8611d5e20>

    def test_distributed_headers_are_propagated_tracecontext(self, test_agent: TestAgentAPI, test_library: APMLibrary):
        """- Test that distributed tracecontext headers are propagated across APIs"""
        trace_id = "0000000000000000000000000000002a"  # 42
        parent_id = "0000000000000003"  # 3
...
↳ and 76 more — View all
DataDog/apm-reliability/dd-trace-php | benchmarks-tracer — 🔧 Needs a code fix, caused by this PR

View more details · View in GitLab

DataDog/apm-reliability/dd-trace-php | merge-gate

View more details · View in GitLab

View all 5 failed jobs.

⚠️ Warnings

❄️ 4 New flaky tests detected

tmp/build_extension/tests/ext/request-replayer/serializer_wire_sidecar_v1.phpt (Sidecar sender + v1-capable agent serializes the v1 wire (/v1.0/traces, chunks)) from PHP.tmp.build_extension.tests.ext.request.replayer
001+ ** ERROR: process timed out **
001- uri=/v1.0/traces
002- has_chunks=yes
003- span_name=root

↳ tmp/build_extension/tests/ext/request-replayer/client_side_stats_dd_tags_env.phpt (Client-side span stats bucket by DD_TAGS env/version when DD_ENV/DD_VERSIO... from php.tmp.build_extension.tests.ext.request.replayer

View in Flaky Test Management

⌛ 5 Test performance regressions detected

Test New execution time Base Execution time Increase DataDog link
testScenario with data set "A simple GET request returning a string"
from tests/Integrations/Symfony/V5_0.DDTrace\Tests\Integrations\Symfony\V5_0\CommonScenariosTest.DDTrace\Tests\Integrations\Symfony\V5_0\CommonScenariosTest::testScenario
6.04s 559.585161ms +5.48s (+980%) View in Datadog
testScenario with data set "A simple GET request returning a string"
from tests/Integrations/Symfony/V3_0.DDTrace\Tests\Integrations\Symfony\V3_0\CommonScenariosTest.DDTrace\Tests\Integrations\Symfony\V3_0\CommonScenariosTest::testScenario
4.97s 766.453667ms +4.2s (+548%) View in Datadog
tmp/build_extension/tests/ext/pcntl/pcntl_fork_thread_mode_orphan.phpt (Thread mode sidecar: orphaned child process promotes itself to master after parent exits)
from PHP.tmp.build_extension.tests.ext.pcntl
3.97s 731.107011ms +3.24s (+443%) View in Datadog
tmp/build_extension/tests/ext/background-sender/sidecar_thread_mode_permissions.phpt (Thread mode sidecar uses abstract Unix socket)
from PHP.tmp.build_extension.tests.ext.background.sender
16.02s 1.48s +14.54s (+985%) View in Datadog
testScenario with data set "A simple GET request returning a string"
from tests/Integrations/Symfony/V5_1.DDTrace\Tests\Integrations\Symfony\V5_1\CommonScenariosTest.DDTrace\Tests\Integrations\Symfony\V5_1\CommonScenariosTest::testScenario
3.95s 565.601005ms +3.38s (+598%) View in Datadog

ℹ️ Info

🎯 Code Coverage (details)
• Patch Coverage: 86.67%
• Overall Coverage: 68.41% (+0.02%)

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 61c85ee | Docs | View more details | Give us feedback!

@pr-commenter

pr-commenter Bot commented Jul 17, 2026 •

Copy link
Copy Markdown

Benchmarks [ tracer ]

Benchmark execution time: 2026-09-30 16:10:43

Comparing candidate commit c24031b in PR branch leiyks/dd-trace-php-v2 with baseline commit d98de1e in branch master.

📊 Benchmarking dashboard

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 💥💥💥
Check Gitlab CI job log to find if any benchmark has crashed.

Scenarios present only in baseline:

  • MessagePackSerializationBench/benchMessagePackSerialization
  • MessagePackSerializationBench/benchMessagePackSerialization-opcache

Found 12 performance improvements and 23 performance regressions! Performance is the same for 154 metrics, 1 unstable metrics.

Explanation

This is an A/B test comparing a candidate commit's performance against that of a baseline commit. Performance changes are noted in the tables below as:

  • 🟩 = significantly better candidate vs. baseline
  • 🟥 = significantly worse candidate vs. baseline

We compute a confidence interval (CI) over the relative difference of means between metrics from the candidate and baseline commits, considering the baseline as the reference.

If the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD), the change is considered significant.

Feel free to reach out to #apm-benchmarking-platform on Slack if you have any questions.

More details about the CI and significant changes

You can imagine this CI as a range of values that is likely to contain the true difference of means between the candidate and baseline commits.

CIs of the difference of means are often centered around 0%, because often changes are not that big:

---------------------------------(------|---^--------)-------------------------------->
                              -0.6%    0%  0.3%     +1.2%
                                 |          |        |
         lower bound of the CI --'          |        |
sample mean (center of the CI) -------------'        |
         upper bound of the CI ----------------------'

As described above, a change is considered significant if the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD).

For instance, for an execution time metric, this confidence interval indicates a significantly worse performance:

----------------------------------------|---------|---(---------^---------)---------->
                                       0%        1%  1.3%      2.2%      3.1%
                                                  |   |         |         |
       significant impact threshold --------------'   |         |         |
                      lower bound of CI --------------'         |         |
       sample mean (center of the CI) --------------------------'         |
                      upper bound of CI ----------------------------------'

scenario:ContextPropagationBench/benchExtractHeaders128Bit-opcache

  • 🟩 execution_time [-786.090ns; -735.243ns] or [-48.444%; -45.311%]

scenario:ContextPropagationBench/benchExtractHeaders64Bit-opcache

  • 🟥 execution_time [+722.903ns; +793.097ns] or [+59.893%; +65.708%]

scenario:ContextPropagationBench/benchInject128Bit-opcache

  • 🟩 execution_time [-742.505ns; -641.495ns] or [-30.809%; -26.618%]

scenario:ContextPropagationBench/benchInject64Bit-opcache

  • 🟥 execution_time [+646.358ns; +815.642ns] or [+28.066%; +35.417%]

scenario:HookBench/benchHookOverheadTraceFunction

  • 🟥 mem_peak [+126.568KB; +126.568KB] or [+2.804%; +2.804%]

scenario:HookBench/benchHookOverheadTraceFunction-opcache

  • 🟥 mem_peak [+94.326KB; +94.329KB] or [+4.470%; +4.470%]

scenario:HookBench/benchHookOverheadTraceMethod

  • 🟥 mem_peak [+126.566KB; +126.569KB] or [+2.764%; +2.765%]

scenario:HookBench/benchHookOverheadTraceMethod-opcache

  • 🟥 mem_peak [+127.999KB; +128.002KB] or [+5.980%; +5.980%]

scenario:LogsInjectionBench/benchLogsInfoBaseline-opcache

  • 🟥 execution_time [+199.624ns; +239.576ns] or [+12.800%; +15.362%]

scenario:PDOBench/benchPDOOverhead

  • 🟥 execution_time [+7.536µs; +11.001µs] or [+2.671%; +3.899%]

scenario:PDOBench/benchPDOOverhead-opcache

  • 🟥 execution_time [+9.097µs; +12.450µs] or [+3.310%; +4.531%]

scenario:PDOBench/benchPDOOverheadWithDBM

  • 🟥 execution_time [+9.148µs; +12.909µs] or [+3.233%; +4.562%]

scenario:PDOBench/benchPDOOverheadWithDBM-opcache

  • 🟥 execution_time [+9.430µs; +12.602µs] or [+3.433%; +4.588%]

scenario:PHPRedisBench/benchRedisOverhead

  • 🟥 execution_time [+40.336µs; +57.023µs] or [+3.613%; +5.107%]

scenario:PHPRedisBench/benchRedisOverhead-opcache

  • 🟥 execution_time [+33.876µs; +48.166µs] or [+2.982%; +4.239%]

scenario:SamplingRuleMatchingBench/benchRegexMatching1-opcache

  • 🟩 execution_time [-2.375µs; -2.103µs] or [-17.885%; -15.840%]

scenario:SamplingRuleMatchingBench/benchRegexMatching2

  • 🟩 execution_time [-2.519µs; -2.271µs] or [-18.163%; -16.375%]

scenario:SamplingRuleMatchingBench/benchRegexMatching2-opcache

  • 🟩 execution_time [-2.542µs; -2.227µs] or [-19.198%; -16.820%]

scenario:SamplingRuleMatchingBench/benchRegexMatching3

  • 🟩 execution_time [-2.465µs; -2.205µs] or [-17.812%; -15.936%]

scenario:SamplingRuleMatchingBench/benchRegexMatching3-opcache

  • 🟩 execution_time [-2.455µs; -2.198µs] or [-18.428%; -16.493%]

scenario:SamplingRuleMatchingBench/benchRegexMatching4

  • 🟩 execution_time [-2.512µs; -2.193µs] or [-18.359%; -16.027%]

scenario:SamplingRuleMatchingBench/benchRegexMatching4-opcache

  • 🟩 execution_time [-2.585µs; -2.339µs] or [-19.406%; -17.563%]

scenario:SpanBench/benchDatadogAPI

  • 🟥 execution_time [+13.913µs; +17.586µs] or [+18.701%; +23.638%]

scenario:SpanBench/benchDatadogAPI-opcache

  • 🟥 execution_time [+15.034µs; +17.883µs] or [+20.691%; +24.612%]

scenario:SpanBench/benchOpenTelemetryAPI

  • 🟥 execution_time [+144.915µs; +165.518µs] or [+19.161%; +21.885%]

scenario:SpanBench/benchOpenTelemetryAPI-opcache

  • 🟥 execution_time [+153.759µs; +171.118µs] or [+22.352%; +24.876%]

scenario:SpanBench/benchOpenTelemetryInteroperability

  • 🟥 execution_time [+28.563µs; +32.499µs] or [+14.191%; +16.147%]
  • 🟩 mem_peak [-762.052KB; -762.046KB] or [-2.584%; -2.584%]

scenario:SpanBench/benchOpenTelemetryInteroperability-opcache

  • 🟥 execution_time [+28.077µs; +32.744µs] or [+15.060%; +17.563%]
  • 🟩 mem_peak [-760.733KB; -760.723KB] or [-2.866%; -2.866%]

scenario:TraceAnnotationsBench/benchTraceAnnotationOverhead

  • 🟥 mem_peak [+126.563KB; +126.568KB] or [+2.760%; +2.760%]

scenario:TraceAnnotationsBench/benchTraceAnnotationOverhead-opcache

  • 🟥 mem_peak [+127.999KB; +128.002KB] or [+5.939%; +5.940%]

scenario:TraceFlushBench/benchFlushTrace

  • 🟥 execution_time [+60.401µs; +68.399µs] or [+16.646%; +18.851%]

scenario:TraceFlushBench/benchFlushTrace-opcache

  • 🟥 execution_time [+53.059µs; +66.541µs] or [+13.094%; +16.422%]

scenario:TraceSerializationBench/benchSerializeTrace-opcache

  • 🟩 execution_time [-300.460µs; -272.140µs] or [-18.177%; -16.464%]

Unstable benchmarks

These benchmarks have a confidence interval too wide to call a change; treat them as noise rather than signal.

scenario:LaravelBench/benchLaravelDdprof-opcache

  • unstable execution_time [-431.008µs; +944.608µs] or [-3.315%; +7.265%]

@Leiyks
Leiyks force-pushed the leiyks/dd-trace-php-v2 branch from 2531886 to b29cd49 Compare July 27, 2026 15:20
@Leiyks
Leiyks force-pushed the leiyks/dd-trace-php-v2 branch 3 times, most recently from 10c7edf to 84351df Compare August 6, 2026 12:39
@Leiyks
Leiyks force-pushed the leiyks/dd-trace-php-v2 branch 2 times, most recently from 73c262e to 0d3d03d Compare August 25, 2026 15:50
@Leiyks
Leiyks marked this pull request as ready for review August 26, 2026 11:56
@Leiyks
Leiyks requested review from a team as code owners August 26, 2026 11:56
@Leiyks
Leiyks requested review from dd-oleksii, greghuels and tabgok and removed request for a team August 26, 2026 11:56

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread tracer/serializer.c Outdated
Comment thread tracer/span_stats.c Outdated
Comment thread tracer/span.c Outdated
@Leiyks
Leiyks marked this pull request as draft August 26, 2026 16:33
@Leiyks Leiyks changed the title feat(tracer): align C span code with v1-compatible stub API (v2 groundwork) WIP: feat(tracer): align C span code with v1-compatible stub API (v2 groundwork) Aug 26, 2026
Comment thread tracer/serializer.c Outdated
Comment thread tracer/serializer.c Outdated
Comment thread tracer/serializer.c Outdated
@Leiyks
Leiyks force-pushed the leiyks/dd-trace-php-v2 branch from f553cb8 to a8f30bd Compare September 15, 2026 11:45
Comment thread components-rs/bytes.rs Outdated
Comment thread tracer/serializer.c Outdated
Comment thread tracer/serializer.c Outdated
Comment thread tracer/serializer.c Outdated
Comment thread tracer/serializer.c Outdated
Comment thread tracer/ddtrace.stub.php Outdated
@Leiyks
Leiyks force-pushed the leiyks/dd-trace-php-v2 branch from c653af1 to 7b533f7 Compare September 25, 2026 13:11
@pr-commenter

pr-commenter Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Benchmarks [ appsec ]

Benchmark execution time: 2026-10-01 18:03:34

Comparing candidate commit 61c85ee in PR branch leiyks/dd-trace-php-v2 with baseline commit c6e46bc in branch master.

📊 Benchmarking dashboard

Found 0 performance improvements and 0 performance regressions! Performance is the same for 12 metrics, 0 unstable metrics.

Explanation

This is an A/B test comparing a candidate commit's performance against that of a baseline commit. Performance changes are noted in the tables below as:

  • 🟩 = significantly better candidate vs. baseline
  • 🟥 = significantly worse candidate vs. baseline

We compute a confidence interval (CI) over the relative difference of means between metrics from the candidate and baseline commits, considering the baseline as the reference.

If the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD), the change is considered significant.

Feel free to reach out to #apm-benchmarking-platform on Slack if you have any questions.

More details about the CI and significant changes

You can imagine this CI as a range of values that is likely to contain the true difference of means between the candidate and baseline commits.

CIs of the difference of means are often centered around 0%, because often changes are not that big:

---------------------------------(------|---^--------)-------------------------------->
                              -0.6%    0%  0.3%     +1.2%
                                 |          |        |
         lower bound of the CI --'          |        |
sample mean (center of the CI) -------------'        |
         upper bound of the CI ----------------------'

As described above, a change is considered significant if the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD).

For instance, for an execution time metric, this confidence interval indicates a significantly worse performance:

----------------------------------------|---------|---(---------^---------)---------->
                                       0%        1%  1.3%      2.2%      3.1%
                                                  |   |         |         |
       significant impact threshold --------------'   |         |         |
                      lower bound of CI --------------'         |         |
       sample mean (center of the CI) --------------------------'         |
                      upper bound of CI ----------------------------------'

Comment thread components-rs/bytes.rs Outdated
Comment thread tracer/serializer.c Outdated
Comment on lines +1713 to +1715
// Global tags (DD_TAGS, add_global_tag) are attribute defaults: one still at its default yields to a
// deprecated $meta value for the same key, as when the defaults lived in meta.
static void dd_yield_global_defaults_to_meta(zend_array *attributes, zend_array *meta, zend_array *globals) {

@bwoebi bwoebi Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we please discuss the exact fallback behaviour?
I'm not sure how this merges.

We have a couple choices:

  • Make meta/metrics/attributes references to each other. -> They have the same contents, are overlapping, type expectations probably violeted.
  • Do whatever you did (which is a bit off to me?) -> I don't fully understand it.
  • Just copy all values in meta and metrics into attributes at serialization time. -> if you call unset($span->meta["..."]); it'll no longer unset nor will it find any integration provided value if accessed in a custom hook.
  • Return an object quacking like an array/iterable, which actually delegates to attributes, whenever meta or metrics is accessed. -> a bit more complex, but probably most faithful?

I would tend to try the last option, and it should allow us to completely leave this concern out of the serializer. It becoming now a self-contained concern on the span.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean sure the last solution seems nice but the question to me is more: what the precedence order when attributes, meta and metrics happens to have the same key.
What I am doing now is putting priority on attributes since the other 2 will be deprecated.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last solution sidesteps this? It provides a view onto attributes, so attributes is always the source of truth. There's no precedence to respect here then.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But putting priority on attributes is exactly the wrong way round - if attributes take precedence and an user assigns to meta in his existing code ... well, his assignments will just be ignored after updating.

Comment thread tracer/serializer.c Outdated
smart_str_free(&combined);
} else {
ddog_add_str_span_meta_zstr(rust_span, "_dd.tags.process", process_tags);
dd_span_attr_zstr(rspan, "_dd.tags.process", process_tags);

@bwoebi bwoebi Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please ask around whether process tags should be chunk level spans in v1 or remain as first span.

@bwoebi

bwoebi commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

The span stats entrypoints are service names.
It's called "top_level", but actually it's not quite top_level entrypoint of the trace.

See https://github.com/DataDog/datadog-agent/blob/12897bea576e821511abcfd9dd4f2cf06cc04f1e/pkg/trace/traceutil/trace.go#L135-L158 for how the agent decides (which we mirror).

It's also related to chunking_. So technically we should not take into account already submitted spans. Please rollback these last two commits fully.

Leiyks added 2 commits October 1, 2026 18:01
…er FFI

Serialize closed spans into a libdatadog TracerPayloadV1Builder (Box-per-node pointer handles) and send them to the sidecar as /v1.0/traces, with the sidecar negotiating /info and downgrading to v0.4 for agents that lack it. The in-process sender keeps the v0.4 wire, transcoded from the same builder.

Span tags live in a single typed attributes store; SpanData::$meta and $metrics are views onto it. Process tags and the OTLP export marker are TracerPayload attributes (the v0.4 downgrade puts them on each chunk's first span), and span links and events carry native attributes. DD_TRACE_AGENT_PROTOCOL_VERSION=0.4 forces v0.4.

Bump libdatadog to the V1 FFI branch and port components-rs to the new rate limiter API.
Use typed SpanData::$attributes and the promoted env/version/component/span_kind properties instead of $meta/$metrics string conversions in the userland integrations and the OpenTelemetry bridge.

Drop the userland App Analytics plumbing (addTraceAnalyticsIfEnabled, requiresExplicitTraceAnalyticsEnabling, markForTraceAnalytics and the per-integration candidates). TraceAnalyticsProcessor::normalizeAnalyticsValue and Tag::ANALYTICS_KEY are now deprecated no-ops; the serializer still maps an analytics.event tag to _dd1.sr.eausr.
@Leiyks
Leiyks force-pushed the leiyks/dd-trace-php-v2 branch from 0a2b3fb to 24f8c4c Compare October 1, 2026 16:57
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Snapshots difference summary

The following differences have been observed in committed snapshots. It is meant to help the reviewer.
The diff is simplistic, so please check some files anyway while we improve it.

If you need to update snapshots, please refer to CONTRIBUTING.md

@Leiyks Leiyks changed the title WIP: feat(tracer): align C span code with v1-compatible stub API (v2 groundwork) feat(tracer): send traces as V1 payloads through the libdatadog builder FFI Oct 1, 2026
Leiyks added 3 commits October 1, 2026 19:18
dd_trace_serialize_closed_spans() now reports the V1 shape: a typed attributes map with promoted fields (span_kind, component, sampling_priority, ...) and native span links and events. Migrate the phpt, PHPUnit and snapshot tests to it, and add coverage for the V1 and v0.4 wires, span attributes, ignoreError and the default root component.

Remove tests for the retired userland msgpack serializer and thread sender (dd_trace_serialize_msgpack, dd_trace_send_traces_via_thread, the in-process background sender capability tests) and for the removed App Analytics trace search config.
Add a msgpack V1 decoder to the request-replayer and advertise /v1.0/traces in its /info, so the PHP test suite can inspect V1 payloads. Move the CI service to the 5.0 image and force-pull the Windows service images so a runner with a stale cached digest does not skip a rebuilt image.
…merge

Clone system-tests at SYSTEM_TESTS_REF (default leiyks/php-v1-payload,
DataDog/system-tests#7843) from SYSTEM_TESTS_REPO, and add
APM_TRACING_EFFICIENT_PAYLOAD to the System Tests matrix.
@Leiyks
Leiyks force-pushed the leiyks/dd-trace-php-v2 branch from 24f8c4c to 61c85ee Compare October 1, 2026 17:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants