Skip to content

Add native OTLP export marker to trace chunks - #4240

Merged
mhlidd merged 2 commits into
masterfrom
matthew.li/otlp-adoption-markers
Sep 30, 2026
Merged

mhlidd merged 2 commits into
masterfrom
matthew.li/otlp-adoption-markers

Conversation

@mhlidd

@mhlidd mhlidd commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Description

This adds _dd.sdk.otlp_export: "false" to the meta of the first span of each trace chunk. It's set at the start of the is_first_span block in ddtrace_serialize_span_to_rust_span (tracer/serializer.c), right before _dd.tags.process, using the existing ddog_add_str_span_meta_str FFI call. No libdatadog change is needed.

This is part of the "Measuring Adoption of Datadog SDKs in OTel Mode (Traces)" RFC. Today the backend infers which spans came from Datadog SDKs exporting OTLP at ingest time, using telemetry.sdk.name and span_source. That's unreliable: the OpenTelemetry Collector's datadogreceiver hardcodes telemetry.sdk.name:Datadog on native payloads it converts. So tracers now declare their export mode on the wire. "true" goes on the OTLP resource when exporting over OTLP, and "false" goes on the first span of each chunk for native export. An absent marker means an older tracer.

PHP has no OTLP trace export (otlp_traces_export_enabled is hardcoded false), so the value is always "false". The OTLP-only datadog.sdk.semantics resource attribute doesn't apply.

Details:

  • Send paths: the sidecar sender, the in-process curl sender and dd_trace_serialize_closed_spans all serialize through this function. No other path writes chunk-level tags.
  • Unconditional: the marker isn't gated like process tags, and doesn't guard against a user tag with the same key. That matches the other tracers.
  • Dropped spans: is_first_span is true when the trace is still empty, so if stats computation drops a span, the next serialized span gets the marker.

Tests:

  • New: tests/ext/sdk_otlp_export_marker.phpt builds two traces of three spans and checks the marker is 'false' on each chunk's first span only.
  • Helpers: SpanChecker, SnapshotTestTrait (test-agent ignore list) and dd_dumper.inc ignore the marker the same way they already ignore _dd.tags.process / _dd.svc_src. So existing tag and snapshot assertions don't need to list it.
  • Updated expectations: 13 .phpt files under tests/ext/ and 7 under appsec/tests/extension/ that print first-span meta.
  • Not run locally: the Docker build environment ran out of disk, so nothing was built or run. CI is the first run. The FFI call matches the existing ddog_add_str_span_meta_str(rust_span, "track_error", "false") usage in the same file. Affected tests were found by grepping, so CI may surface a missed expectation.

Related changes:

This change was written with AI assistance and reviewed before submission.

Reviewer checklist

  • Test coverage seems ok.
  • Appropriate labels assigned.

🤖 Generated with Claude Code

Tag the first span of each chunk with _dd.sdk.otlp_export=false, next to
_dd.tags.process, so the backend can tell native-exported spans from spans
that reached it through the datadogreceiver instead of inferring it at
ingest time. PHP has no OTLP trace export, so the value is always false.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mhlidd mhlidd added the AI Generated Largely based on code generated by an AI or LLM. This label is the same across all dd-trace-* repos label Sep 25, 2026
@datadog-official

datadog-official Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
• Patch Coverage: 100.00%
• Overall Coverage: 68.26% (-0.04%)

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟢 Approval recommended

The shared serialization path correctly applies the marker once per chunk and the behavior has focused coverage.

Review effort: Balanced
Findings: None

What changed in this PR

Adds the native OTLP export marker to the first serialized span of every trace chunk.

Changes:

  • Emits _dd.sdk.otlp_export: "false" during native serialization.
  • Adds focused multi-chunk coverage.
  • Updates test helpers and affected expectations.
File Description
tracer/​serializer.c Adds the marker to each chunk’s first span.
tests/​ext/​sdk_otlp_export_marker.phpt Verifies marker placement across two chunks.
tests/​ext/​sandbox/​safe_to_string_metadata.phpt Excludes the new generated marker.
tests/​ext/​sandbox/​dd_dumper.inc Filters the marker from generic dumps.
tests/​ext/​root_span_url_with_post_no_param.phpt Updates expected metadata.
tests/​ext/​root_span_url_with_post_no_param_set.phpt Updates expected metadata.
tests/​ext/​root_span_url_as_resource_names.phpt Updates expected metadata.
tests/​ext/​root_span_url_as_resource_names_no_host.phpt Updates expected metadata.
tests/​ext/​referrer_extraction_05.phpt Updates expected metadata.
tests/​ext/​referrer_extraction_04.phpt Updates expected metadata.
tests/​ext/​referrer_extraction_03.phpt Updates expected metadata.
tests/​ext/​referrer_extraction_02.phpt Updates expected metadata.
tests/​ext/​referrer_extraction_01.phpt Updates expected metadata.
tests/​ext/​extract_server_values.phpt Updates expected metadata.
tests/​ext/​distributed_tracing/​distributed_trace_overwrite_active_span.phpt Filters the generated marker.
tests/​Common/​SpanChecker.php Ignores the marker unless explicitly asserted.
tests/​Common/​SnapshotTestTrait.php Excludes the marker from snapshots.
appsec/​tests/​extension/​root_span_add_tag.phpt Updates expected metadata.
appsec/​tests/​extension/​root_span_add_tag_with_intermediate_spans.phpt Updates expected metadata.
appsec/​tests/​extension/​rinit_root_span_add_tag.phpt Updates expected metadata.
appsec/​tests/​extension/​rinit_record_span_tags.phpt Updates expected metadata.
appsec/​tests/​extension/​rinit_record_span_tags_fail.phpt Updates expected metadata.
appsec/​tests/​extension/​ddtrace_basic.phpt Updates expected metadata.
appsec/​tests/​extension/​client_init_record_span_tags.phpt Updates expected metadata.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@bwoebi bwoebi left a comment

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.

Simple enough, approving it.

Question though: we're in the middle of moving to the v1 protocol in #4046. Will it be a payload-level attribute there?

@mhlidd

mhlidd commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor Author

@bwoebi Yup that's what we've done for repos that support V1! Additionally, if OTLP is ever supported in PHP, we would also add it as a Resource Attribute there.

@mhlidd
mhlidd merged commit 457aa53 into master Sep 30, 2026
2198 checks passed
@mhlidd
mhlidd deleted the matthew.li/otlp-adoption-markers branch September 30, 2026 13:43
@github-actions github-actions Bot added this to the 1.26.0 milestone Sep 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI Generated Largely based on code generated by an AI or LLM. This label is the same across all dd-trace-* repos

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants