Skip to content

feat(otlp)!: Export OTLP spans with attribute-level OTel compatibility#2091

Merged
gh-worker-dd-mergequeue-cf854d[bot] merged 12 commits into
mainfrom
zach.montoya/otlp-compatibility-mode
Jun 22, 2026
Merged

feat(otlp)!: Export OTLP spans with attribute-level OTel compatibility#2091
gh-worker-dd-mergequeue-cf854d[bot] merged 12 commits into
mainfrom
zach.montoya/otlp-compatibility-mode

Conversation

@zacharycmontoya

@zacharycmontoya zacharycmontoya commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

This PR adds a configuration to the Trace Exporter to export spans with purely OpenTelemetry semantics. When enabled, this configuration updates the DD Span => OTLP Span mapping to exclude the following span tags from the output:

  • service.name
  • operation.name
  • resource.name
  • span.type
  • error.msg
  • error.message
  • span.kind

This change also fixes the DD Span error message lookup to account for both the error.msg and error.message tag keys, since they are used interchangeably across Datadog SDKs.

Motivation

We want to enable OpenTelemetry SDK users to migrate to the Datadog SDK in their language ecosystem, so this change allows them to export OTLP spans from the Datadog SDK without the shape of their data changing. This is most notable when using the OpenTelemetry Tracing API and OpenTelemetry Instrumentation Libraries to generate traces -- with this new semantic mode, the OTLP span should reach the backend without its semantics changing.

Additional Notes

This may result in a breaking change since it affects the public function libdd_trace_utils::otlp_encoder::map_traces_to_otlp.

How to test the change?

This is tested through unit tests in libdd-trace-utils/src/otlp_encoder/mapper.rs that validate the Datadog-specific attributes are excluded from the OTLP span.

@datadog-prod-us1-4

datadog-prod-us1-4 Bot commented Jun 6, 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: 74.00% (+0.01%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 58af6e5 | Docs | Datadog PR Page | Give us feedback!

@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Clippy Allow Annotation Report

Comparing clippy allow annotations between branches:

  • Base Branch: origin/main
  • PR Branch: origin/zach.montoya/otlp-compatibility-mode

Summary by Rule

Rule Base Branch PR Branch Change
unwrap_used 2 2 No change (0%)
Total 2 2 No change (0%)

Annotation Counts by File

File Base Branch PR Branch Change
libdd-data-pipeline/src/trace_exporter/mod.rs 2 2 No change (0%)

Annotation Stats by Crate

Crate Base Branch PR Branch Change
clippy-annotation-reporter 5 5 No change (0%)
datadog-ffe-ffi 1 1 No change (0%)
datadog-ipc 22 22 No change (0%)
datadog-live-debugger 4 4 No change (0%)
datadog-live-debugger-ffi 10 10 No change (0%)
datadog-profiling-replayer 4 4 No change (0%)
datadog-sidecar 45 45 No change (0%)
libdd-common 13 13 No change (0%)
libdd-common-ffi 12 12 No change (0%)
libdd-data-pipeline 6 6 No change (0%)
libdd-ddsketch 2 2 No change (0%)
libdd-dogstatsd-client 1 1 No change (0%)
libdd-profiling 13 13 No change (0%)
libdd-remote-config 3 3 No change (0%)
libdd-telemetry 20 20 No change (0%)
libdd-tinybytes 4 4 No change (0%)
libdd-trace-normalization 2 2 No change (0%)
libdd-trace-obfuscation 3 3 No change (0%)
libdd-trace-stats 1 1 No change (0%)
libdd-trace-utils 11 11 No change (0%)
Total 182 182 No change (0%)

About This Report

This report tracks Clippy allow annotations for specific rules, showing how they've changed in this PR. Decreasing the number of these annotations generally improves code quality.

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.09202% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.57%. Comparing base (a1da9fc) to head (6f89fcc).
⚠️ Report is 16 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2091      +/-   ##
==========================================
+ Coverage   73.44%   73.57%   +0.12%     
==========================================
  Files         465      475      +10     
  Lines       77949    79139    +1190     
==========================================
+ Hits        57248    58223     +975     
- Misses      20701    20916     +215     
Components Coverage Δ
libdd-crashtracker 65.35% <ø> (-0.13%) ⬇️
libdd-crashtracker-ffi 37.68% <ø> (ø)
libdd-alloc 98.77% <ø> (ø)
libdd-data-pipeline 86.19% <20.00%> (-0.95%) ⬇️
libdd-data-pipeline-ffi 73.86% <ø> (-3.17%) ⬇️
libdd-common 79.93% <ø> (+0.04%) ⬆️
libdd-common-ffi 74.41% <ø> (ø)
libdd-telemetry 73.37% <ø> (ø)
libdd-telemetry-ffi 31.36% <ø> (ø)
libdd-dogstatsd-client 82.64% <ø> (ø)
datadog-ipc 76.36% <ø> (+0.14%) ⬆️
libdd-profiling 81.70% <ø> (+0.01%) ⬆️
libdd-profiling-ffi 64.79% <ø> (ø)
libdd-sampling 97.48% <ø> (+0.06%) ⬆️
datadog-sidecar 36.51% <ø> (+1.89%) ⬆️
datdog-sidecar-ffi 12.23% <ø> (+3.61%) ⬆️
spawn-worker 48.86% <ø> (ø)
libdd-tinybytes 93.80% <ø> (ø)
libdd-trace-normalization 81.71% <ø> (ø)
libdd-trace-obfuscation 87.30% <ø> (ø)
libdd-trace-protobuf 68.25% <ø> (ø)
libdd-trace-utils 89.43% <97.46%> (+0.22%) ⬆️
libdd-tracer-flare 86.57% <ø> (-0.31%) ⬇️
libdd-log 74.83% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…mode.

This is implemented by adding a new bool field enable_otel_trace_compatibility to TraceExporterBuilder with a public setter, propagating it to the OtlpTraceConfig, and using it in the OTLP trace export immediately to omit Datadog-specific attributes like "operation.name"
… 'error.message' span tags on the output OTLP span when OTel Trace Compatibility is enabled
@zacharycmontoya
zacharycmontoya force-pushed the zach.montoya/otlp-compatibility-mode branch from 6f89fcc to 2d0d234 Compare June 8, 2026 23:27
@dd-octo-sts

dd-octo-sts Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Artifact Size Benchmark Report

aarch64-alpine-linux-musl
Artifact Baseline Commit Change
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.a 84.53 MB 84.54 MB +.01% (+14.95 KB) 🔍
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.so 7.76 MB 7.76 MB 0% (0 B) 👌
aarch64-unknown-linux-gnu
Artifact Baseline Commit Change
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.a 95.67 MB 95.68 MB +.01% (+16.37 KB) 🔍
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.so 10.43 MB 10.43 MB 0% (0 B) 👌
libdatadog-x64-windows
Artifact Baseline Commit Change
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.dll 25.01 MB 25.02 MB +0% (+2.50 KB) 👌
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.lib 87.33 KB 87.33 KB 0% (0 B) 👌
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.pdb 181.74 MB 181.76 MB +.01% (+24.00 KB) 🔍
/libdatadog-x64-windows/debug/static/datadog_profiling_ffi.lib 932.35 MB 932.38 MB +0% (+30.62 KB) 👌
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.dll 8.20 MB 8.20 MB +.01% (+1.50 KB) 🔍
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.lib 87.33 KB 87.33 KB 0% (0 B) 👌
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.pdb 24.12 MB 24.13 MB +.03% (+8.00 KB) 🔍
/libdatadog-x64-windows/release/static/datadog_profiling_ffi.lib 48.20 MB 48.20 MB +.01% (+6.16 KB) 🔍
libdatadog-x86-windows
Artifact Baseline Commit Change
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.dll 21.68 MB 21.68 MB +.01% (+3.50 KB) 🔍
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.lib 88.71 KB 88.71 KB 0% (0 B) 👌
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.pdb 185.73 MB 185.75 MB +0% (+16.00 KB) 👌
/libdatadog-x86-windows/debug/static/datadog_profiling_ffi.lib 920.84 MB 920.87 MB +0% (+30.43 KB) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.dll 6.32 MB 6.32 MB +0% (+512 B) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.lib 88.71 KB 88.71 KB 0% (0 B) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.pdb 25.88 MB 25.89 MB +.03% (+8.00 KB) 🔍
/libdatadog-x86-windows/release/static/datadog_profiling_ffi.lib 45.82 MB 45.82 MB +.01% (+6.74 KB) 🔍
x86_64-alpine-linux-musl
Artifact Baseline Commit Change
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.a 75.35 MB 75.37 MB +.02% (+17.42 KB) 🔍
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.so 8.68 MB 8.68 MB 0% (0 B) 👌
x86_64-unknown-linux-gnu
Artifact Baseline Commit Change
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.a 90.80 MB 90.82 MB +.01% (+16.45 KB) 🔍
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.so 10.55 MB 10.55 MB 0% (0 B) 👌

Comment thread libdd-trace-utils/src/otlp_encoder/mapper.rs Outdated
Comment thread libdd-data-pipeline/src/trace_exporter/builder.rs Outdated
…ns in the OTel compat mode. It is already present as a first-class SpanKind field
@zacharycmontoya
zacharycmontoya marked this pull request as ready for review June 12, 2026 00:51
@zacharycmontoya
zacharycmontoya requested review from a team as code owners June 12, 2026 00:51
@zacharycmontoya
zacharycmontoya requested review from vpellan and removed request for a team June 12, 2026 00:51

@link04 link04 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.

Nothing I found with the AI could be breaking based on the expectations.

@marcotc marcotc changed the title feat(otlp): Export OTLP spans with attribute-level OTel compatibility feat(otlp)!: Export OTLP spans with attribute-level OTel compatibility Jun 12, 2026

@yannham yannham 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.

Left some nits but LGTM

Comment thread libdd-trace-utils/src/otlp_encoder/mapper.rs
Comment thread libdd-trace-utils/src/otlp_encoder/mapper.rs Outdated

@ekump ekump 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.

minor comments, LGTM.

/// This is useful when exporting to a native OTel backend that does not expect Datadog
/// semantics. The host language tracer is expected to observe this behavior by setting the
/// `DD_TRACE_OTEL_SEMANTICS_ENABLED` environment variable to `true`.
pub fn enable_otel_trace_semantics(&mut self) -> &mut Self {

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.

Do you need to add a corresponding function to the FFI API?

@zacharycmontoya zacharycmontoya Jun 22, 2026

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'll follow up and post a change to the FFI API as a separate PR, as this is only consumed in dd-trace-py for now

Comment thread libdd-data-pipeline/src/otlp/config.rs Outdated
Comment thread libdd-data-pipeline/src/trace_exporter/builder.rs Outdated
Comment thread libdd-trace-utils/src/otlp_encoder/mapper.rs Outdated
Comment thread libdd-trace-utils/src/otlp_encoder/mapper.rs Outdated
@gh-worker-dd-mergequeue-cf854d
gh-worker-dd-mergequeue-cf854d Bot merged commit c690b5e into main Jun 22, 2026
89 checks passed
@gh-worker-dd-mergequeue-cf854d
gh-worker-dd-mergequeue-cf854d Bot deleted the zach.montoya/otlp-compatibility-mode branch June 22, 2026 23:33
bm1549 added a commit that referenced this pull request Jun 23, 2026
…st mapper

main landed feat(otlp)!: attribute-level OTel compatibility (#2091), which adds
`otel_trace_semantics_enabled`: when set, the OTLP payload omits DD-specific
per-span attributes (service.name/operation.name/resource.name/span.type) and
the error.*/span.kind meta tags (that info lives in the OTLP Status and Span.kind
fields). Ported that gating into the prost mapper:

- map_traces_to_otlp / map_span / collect_span_attributes thread the flag; the
  promoted tags and the error.*/span.kind meta tags are skipped when enabled, and
  the dropped-count accounting mirrors what was emitted (promoted/excluded
  compat tags), matching #2091's behavior.
- OtlpTraceConfig gains otel_trace_semantics_enabled; the builder wires it; the
  send path passes config.otel_trace_semantics_enabled. Trace protocol stays
  protobuf-capable (config.protocol.encode), metrics stay JSON.
- Ported #2091's test as a prost-native assertion; existing OTLP/metrics tests
  unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
bm1549 added a commit that referenced this pull request Jun 23, 2026
…Status

span_status only read meta["error.msg"], but the #2091 OTel-semantics gating
drops both error.msg and error.message meta tags. For the common case
(error.message — used by every SDK except .NET), that silently lost the error
text: empty Status.message and, under OTel-semantics, no error.message attribute
either. Fall back to error.message (mirroring main's json_types mapper) so the
message is always promoted to Status. Add an OTel-semantics regression test.

Found by Codex adversarial review of the #2091 integration.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
gh-worker-dd-mergequeue-cf854d Bot pushed a commit that referenced this pull request Jun 23, 2026
# What does this PR do?

Adds OTLP HTTP/protobuf as a trace-export encoding alongside HTTP/JSON, selectable via the OTel-standard `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL` (`http/json` default, `http/protobuf`). The generated `prost` OTLP types are the single intermediate representation: the mapper builds them directly from native spans, protobuf is `prost::encode_to_vec`, and JSON is a serde serializer over the same types.

# Motivation

libdatadog's OTLP trace export only spoke HTTP/JSON. SDKs that honor `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL` need `http/protobuf` to match the OTel default and to talk to collectors that expect protobuf.

# Additional Notes

- Prost is the single IR: no parallel hand-rolled JSON model, no string round-trip. `encode_otlp_protobuf` is `encode_to_vec`; `encode_otlp_json` is a serde serializer (`json_serializer.rs`) emitting OTLP-spec JSON (hex ids, base64 bytes, int64-as-string, lowerCamelCase, proto3 defaults omitted).
- `OtlpProtocol` is `{HttpJson, HttpProtobuf}`; `grpc` is rejected at the parse boundary (`FromStr`) rather than carried as an unsupported variant. `content_type()`/`encode()` live on the type.
- Integrates with the OTLP metrics exporter already on main: the shared low-level sender takes the content-type per request, so traces use the configured protocol while metrics stay JSON.
- Carries through `otel_trace_semantics_enabled` (OTel attribute compatibility, #2091): when set, the prost mapper omits the DD-specific span attributes and promotes the error message to the OTLP `Status`.
- Span-link W3C trace flags are carried through to OTLP `Link.flags`.
- Benchmarks for the encoder hot paths, plus allocation tuning (pre-sized Vecs, allocation-free id/timestamp/int serialization).

# How to test the change?

- `cargo test -p libdd-trace-utils -p libdd-data-pipeline -p libdd-data-pipeline-ffi`, `cargo test --doc`, clippy, fmt, and `cargo ffi-test` pass. A parity test asserts the JSON and protobuf encodings carry the same span from the one prost IR; a protobuf round-trip test asserts the encoding is lossless.
- End-to-end through dd-trace-py (DataDog/dd-trace-py#18609): emitted protobuf-only OTLP traces through a local Agent to the backend. Wire was `application/x-protobuf` (HTTP 200), spans ingested with correct service/resource and a preserved 128-bit trace id.
- Benchmarks: `cargo bench -p libdd-trace-utils --bench main -- otlp/`.

BREAKING CHANGE: removes the previously public `libdd_trace_utils::otlp_encoder::json_types` module (the hand-rolled OTLP JSON model). OTLP encoding now builds prost-generated types as the single IR. libdatadog consumers pin by version, so they pick this up on the next release.


Co-authored-by: brian.marks <[email protected]>
gh-worker-dd-mergequeue-cf854d Bot pushed a commit that referenced this pull request Jun 29, 2026
## chore: release v37.0.0

Bumps the workspace version from `36.0.0` to `37.0.0` in `Cargo.toml` and regenerates `Cargo.lock`.

## Post-merge steps

1. Trigger the `create_release` job on GitLab — builds artifacts and creates a draft GitHub release.
2. Ask someone from `libdatadog-core` or `libdatadog-release` to publish the draft release.
3. Trigger the `release-proposal-dispatch` GitHub Actions workflow for per-crate crates.io publishing:
   crates: libdd-data-pipeline,libdd-trace-stats,libdd-trace-utils,libdd-ddsketch

## Notable changes since v36.0.0

- `feat(data-pipeline)`: export client-computed span stats as OTLP trace metrics (#2067)
- `feat(otel-thread-ctx)`: add self check capability (#2095)
- `fix(trace-stats)`: add `grpc_method` to aggregation key (#2151)
- `feat(data-pipeline)`: add stdout log trace exporter (#2074)
- `feat(remote-config)`: use the proto file from the agent (#2165)
- `feat(sidecar)`: expose `default_service_name` for `svc.*` process tags (#2053)
- feat(otlp)!: Export OTLP spans with attribute-level OTel compatibility (#2091)

Co-authored-by: munir.abdinur <[email protected]>
iunanua added a commit that referenced this pull request Jul 7, 2026
…ibdd-data-pipeline, libdd-li... (#2201)

# Release proposal for libdd-capabilities-impl, libdd-common,
libdd-data-pipeline, libdd-library-config, libdd-remote-config,
libdd-sampling, libdd-telemetry, libdd-tinybytes, libdd-trace-utils and
their dependencies

This PR contains version bumps based on public API changes and commits
since last release.

## libdd-capabilities
**Next version:** `2.1.0`
**Semver bump:** `minor`
**Tag:** `libdd-capabilities-v2.1.0`

### Commits

- feat(data-pipeline)!: add stdout log trace exporter (#2074)

## libdd-common
**Next version:** `5.1.0`
**Semver bump:** `minor`
**Tag:** `libdd-common-v5.1.0`

### Commits

- refactor(clippy): prefer core and alloc imports (#2196)
- fix: update rustls-webpki to 0.103.13 (#2187)
- fix: update anyhow for unsoundness (#2186)
- feat(machine id): Add helpers in ddcommon to fetch the machine UUID l…
(#2163)

## libdd-ddsketch
**Next version:** `1.1.0`
**Semver bump:** `minor`
**Tag:** `libdd-ddsketch-v1.1.0`

### Commits

- feat(data-pipeline)!: export client-computed span stats as OTLP trace
metrics (#2067)
- test(ddsketch): add microbenchmarks for add/encode/collapse (#2125)

## libdd-trace-protobuf
**Next version:** `4.0.0`
**Semver bump:** `major`
**Tag:** `libdd-trace-protobuf-v4.0.0`

### Commits

- chore!: update protobufs to be in sync with datadog-agent (#2180)
- feat(stats)!: add whole key cardinality limit (#2158)
- feat(remote-config)!: use the proto file from the agent (#2165)
- feat(data-pipeline): OTLP HTTP/protobuf trace export (#2115)

## libdd-capabilities-impl
**Next version:** `3.0.0`
**Semver bump:** `major`
**Tag:** `libdd-capabilities-impl-v3.0.0`

### ⚠️ major bump forced due to:

- `libdd-common`: ^4.1.0 → ^5.1.0

### Commits

- feat(data-pipeline)!: add stdout log trace exporter (#2074)

## libdd-library-config
**Next version:** `3.0.0`
**Semver bump:** `major`
**Tag:** `libdd-library-config-v3.0.0`

### ⚠️ major bump forced due to:

- `libdd-trace-protobuf`: ^3.0.2 → ^4.0.0

### Commits

- refactor(clippy): prefer core and alloc imports (#2196)
- feat(library-config)!: caller-supplied threadlocal schema and extra
process-context attributes (#2162)
- fix(otel-thread-ctx): put the threadlocal attributes at the right
place in the context (#2167)

## libdd-remote-config
**Next version:** `2.0.0`
**Semver bump:** `major`
**Tag:** `libdd-remote-config-v2.0.0`

### ⚠️ major bump forced due to:

- `libdd-trace-protobuf`: ^3.0.2 → ^4.0.0

### Commits

- refactor(libdd-remote-config)!: hide Target inner properties so they
are not leaked (#2182)
- feat(remote-config)!: use the proto file from the agent (#2165)
- refactor(rc): reexport Endpoint and Tag common types (#2147)

## libdd-trace-normalization
**Next version:** `3.0.0`
**Semver bump:** `major`
**Tag:** `libdd-trace-normalization-v3.0.0`

### ⚠️ major bump forced due to:

- `libdd-trace-protobuf`: ^3.0.1 → ^4.0.0

### Commits

- feat(data-pipeline)!: CSS Trace Filters (#1985)

## libdd-shared-runtime
**Next version:** `2.0.0`
**Semver bump:** `major`
**Tag:** `libdd-shared-runtime-v2.0.0`

### ⚠️ major bump forced due to:

- `libdd-common`: ^4.1.0 → ^5.1.0

### Commits

- feat(shared-runtime)!: SharedRuntime Borrowed & Owned mode (#2061)
- feat(shared-runtime)!: use weak waker in trigger [APMSP-3371] (#2050)

## libdd-trace-utils
**Next version:** `9.0.0`
**Semver bump:** `major`
**Tag:** `libdd-trace-utils-v9.0.0`

### ⚠️ major bump forced due to:

- `libdd-common`: ^4.2.0 → ^5.1.0
- `libdd-trace-protobuf`: ^3.0.2 → ^4.0.0

### Commits

- ci(miri): skip slow miri tests (#2188)
- chore!: update protobufs to be in sync with datadog-agent (#2180)
- feat(data-pipeline): add agentless export (#2081)
- feat(data-pipeline)!: add stdout log trace exporter (#2074)
- feat(data-pipeline): OTLP HTTP/protobuf trace export (#2115)
- feat(otlp)!: Export OTLP spans with attribute-level OTel compatibility
(#2091)
- test(trace-utils): add V05 msgpack decode microbenchmark (#2127)
- feat(data-pipeline)!: export client-computed span stats as OTLP trace
metrics (#2067)
- test(trace-utils): add VecMap microbenchmarks (#2126)
- chore(stats)!: submit p0 telemetry in stats (#2130)
- refactor(change-buffer)!: replace slot index with span_id, fix segment
isolation (#2105)
- feat(data-pipeline)!: CSS Trace Filters (#1985)
- feat(trace-exporter): add v1 span and its encoder (#2039)
- fix(trace-utils): mark decoded span maps as deduped (#2110)
- feat(trace-utils)!: change buffer implementation (#2055)
- feat(native-spans)!: change buffer foundation (#2046)
- refactor(span)!: use VecMap for `meta`, `metrics` and `meta_struct`
for v04 spans (#2043)
- test: fix timeouts on heavily contended scenarios (#2093)

## libdd-telemetry
**Next version:** `6.0.0`
**Semver bump:** `major`
**Tag:** `libdd-telemetry-v6.0.0`

### ⚠️ major bump forced due to:

- `libdd-common`: ^4.2.0 → ^5.1.0
- `libdd-shared-runtime`: ^1.0.0 → ^2.0.0

### Commits

- ci(miri): skip slow miri tests (#2188)
- refactor(libdd-telemetry)!: avoid leaking libdd-common types in the
public API (#2152)
- feat(shared-runtime)!: SharedRuntime Borrowed & Owned mode (#2061)

## libdd-trace-obfuscation
**Next version:** `5.0.0`
**Semver bump:** `major`
**Tag:** `libdd-trace-obfuscation-v5.0.0`

### ⚠️ major bump forced due to:

- `libdd-common`: ^4.2.0 → ^5.1.0
- `libdd-trace-protobuf`: ^3.0.2 → ^4.0.0
- `libdd-trace-utils`: ^8.0.0 → ^9.0.0

### Commits

- refactor(clippy): prefer core and alloc imports (#2196)
- ci(miri): skip slow miri tests (#2188)
- fix: update anyhow for unsoundness (#2186)

## libdd-trace-stats
**Next version:** `6.0.0`
**Semver bump:** `major`
**Tag:** `libdd-trace-stats-v6.0.0`

### ⚠️ major bump forced due to:

- `libdd-common`: ^4.2.0 → ^5.1.0
- `libdd-shared-runtime`: ^1.0.0 → ^2.0.0
- `libdd-trace-protobuf`: ^3.0.2 → ^4.0.0
- `libdd-trace-utils`: ^8.0.0 → ^9.0.0

### Commits

- chore!: update protobufs to be in sync with datadog-agent (#2180)
- feat(stats)!: send telemetry for cardinality limits (#2159)
- feat(stats)!: add whole key cardinality limit (#2158)
- fix(trace-stats)!: add grpc_method to aggregation key (#2151)
- feat(shared-runtime)!: SharedRuntime Borrowed & Owned mode (#2061)
- feat(data-pipeline)!: export client-computed span stats as OTLP trace
metrics (#2067)
- refactor(span)!: use VecMap for `meta`, `metrics` and `meta_struct`
for v04 spans (#2043)

## libdd-data-pipeline
**Next version:** `7.0.0`
**Semver bump:** `major`
**Tag:** `libdd-data-pipeline-v7.0.0`

### ⚠️ major bump forced due to:

- `libdd-common`: ^4.2.0 → ^5.1.0
- `libdd-shared-runtime`: ^1.0.0 → ^2.0.0
- `libdd-telemetry`: ^5.0.1 → ^6.0.0
- `libdd-trace-protobuf`: ^3.0.2 → ^4.0.0
- `libdd-trace-stats`: ^5.0.0 → ^6.0.0
- `libdd-trace-utils`: ^8.0.0 → ^9.0.0

### Commits

- feat(trace_exporter): enable telemetry in stats exporter (#2160)
- refactor(libdd-telemetry)!: avoid leaking libdd-common types in the
public API (#2152)
- feat(stats): emit canonical gRPC status name for OTLP
rpc.response.status_code (#2183)
- feat(data-pipeline): add agentless export (#2081)
- feat(stats)!: send telemetry for cardinality limits (#2159)
- feat(stats)!: add whole key cardinality limit (#2158)
- fix(trace-stats)!: add grpc_method to aggregation key (#2151)
- feat(data-pipeline)!: add stdout log trace exporter (#2074)
- feat(shared-runtime)!: SharedRuntime Borrowed & Owned mode (#2061)
- feat(data-pipeline): OTLP HTTP/protobuf trace export (#2115)
- feat(otlp)!: Export OTLP spans with attribute-level OTel compatibility
(#2091)
- feat(data-pipeline)!: export client-computed span stats as OTLP trace
metrics (#2067)
- chore(stats)!: submit p0 telemetry in stats (#2130)
- feat(data-pipeline)!: CSS Trace Filters (#1985)
- feat(shared-runtime)!: use weak waker in trigger [APMSP-3371] (#2050)
- refactor(span)!: use VecMap for `meta`, `metrics` and `meta_struct`
for v04 spans (#2043)
- feat(stats)!: add endpoint gating to client-side stats [APMSP-3361]
(#2040)

## libdd-dogstatsd-client
**Next version:** `4.0.0`
**Semver bump:** `major`
**Tag:** `libdd-dogstatsd-client-v4.0.0`

### ⚠️ major bump forced due to:

- `libdd-common`: ^4.1.0 → ^5.1.0


## libdd-sampling
**Next version:** `5.0.0`
**Semver bump:** `major`
**Tag:** `libdd-sampling-v5.0.0`

### ⚠️ major bump forced due to:

- `libdd-common`: ^4.2.0 → ^5.1.0
- `libdd-trace-utils`: ^8.0.0 → ^9.0.0


[APMSP-3371]:
https://datadoghq.atlassian.net/browse/APMSP-3371?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: iunanua <[email protected]>
taegyunkim pushed a commit that referenced this pull request Jul 8, 2026
#2091)

# What does this PR do?

This PR adds a configuration to the Trace Exporter to export spans with purely OpenTelemetry semantics. When enabled, this configuration updates the DD Span => OTLP Span mapping to exclude the following span tags from the output:
- `service.name`
- `operation.name`
- `resource.name`
- `span.type`
- `error.msg`
- `error.message`
- `span.kind`

This change also fixes the DD Span error message lookup to account for both the `error.msg` and `error.message` tag keys, since they are used interchangeably across Datadog SDKs.

# Motivation

We want to enable OpenTelemetry SDK users to migrate to the Datadog SDK in their language ecosystem, so this change allows them to export OTLP spans from the Datadog SDK without the shape of their data changing. This is most notable when using the OpenTelemetry Tracing API and OpenTelemetry Instrumentation Libraries to generate traces -- with this new semantic mode, the OTLP span should reach the backend without its semantics changing.

# Additional Notes

This may result in a breaking change since it affects the public function `libdd_trace_utils::otlp_encoder::map_traces_to_otlp`.

# How to test the change?

This is tested through unit tests in `libdd-trace-utils/src/otlp_encoder/mapper.rs` that validate the Datadog-specific attributes are excluded from the OTLP span.

Co-authored-by: zach.montoya <[email protected]>
Signed-off-by: Taegyun Kim <[email protected]>
taegyunkim pushed a commit that referenced this pull request Jul 8, 2026
# What does this PR do?

Adds OTLP HTTP/protobuf as a trace-export encoding alongside HTTP/JSON, selectable via the OTel-standard `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL` (`http/json` default, `http/protobuf`). The generated `prost` OTLP types are the single intermediate representation: the mapper builds them directly from native spans, protobuf is `prost::encode_to_vec`, and JSON is a serde serializer over the same types.

# Motivation

libdatadog's OTLP trace export only spoke HTTP/JSON. SDKs that honor `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL` need `http/protobuf` to match the OTel default and to talk to collectors that expect protobuf.

# Additional Notes

- Prost is the single IR: no parallel hand-rolled JSON model, no string round-trip. `encode_otlp_protobuf` is `encode_to_vec`; `encode_otlp_json` is a serde serializer (`json_serializer.rs`) emitting OTLP-spec JSON (hex ids, base64 bytes, int64-as-string, lowerCamelCase, proto3 defaults omitted).
- `OtlpProtocol` is `{HttpJson, HttpProtobuf}`; `grpc` is rejected at the parse boundary (`FromStr`) rather than carried as an unsupported variant. `content_type()`/`encode()` live on the type.
- Integrates with the OTLP metrics exporter already on main: the shared low-level sender takes the content-type per request, so traces use the configured protocol while metrics stay JSON.
- Carries through `otel_trace_semantics_enabled` (OTel attribute compatibility, #2091): when set, the prost mapper omits the DD-specific span attributes and promotes the error message to the OTLP `Status`.
- Span-link W3C trace flags are carried through to OTLP `Link.flags`.
- Benchmarks for the encoder hot paths, plus allocation tuning (pre-sized Vecs, allocation-free id/timestamp/int serialization).

# How to test the change?

- `cargo test -p libdd-trace-utils -p libdd-data-pipeline -p libdd-data-pipeline-ffi`, `cargo test --doc`, clippy, fmt, and `cargo ffi-test` pass. A parity test asserts the JSON and protobuf encodings carry the same span from the one prost IR; a protobuf round-trip test asserts the encoding is lossless.
- End-to-end through dd-trace-py (DataDog/dd-trace-py#18609): emitted protobuf-only OTLP traces through a local Agent to the backend. Wire was `application/x-protobuf` (HTTP 200), spans ingested with correct service/resource and a preserved 128-bit trace id.
- Benchmarks: `cargo bench -p libdd-trace-utils --bench main -- otlp/`.

BREAKING CHANGE: removes the previously public `libdd_trace_utils::otlp_encoder::json_types` module (the hand-rolled OTLP JSON model). OTLP encoding now builds prost-generated types as the single IR. libdatadog consumers pin by version, so they pick this up on the next release.

Co-authored-by: brian.marks <[email protected]>
Signed-off-by: Taegyun Kim <[email protected]>
taegyunkim pushed a commit that referenced this pull request Jul 8, 2026
## chore: release v37.0.0

Bumps the workspace version from `36.0.0` to `37.0.0` in `Cargo.toml` and regenerates `Cargo.lock`.

## Post-merge steps

1. Trigger the `create_release` job on GitLab — builds artifacts and creates a draft GitHub release.
2. Ask someone from `libdatadog-core` or `libdatadog-release` to publish the draft release.
3. Trigger the `release-proposal-dispatch` GitHub Actions workflow for per-crate crates.io publishing:
   crates: libdd-data-pipeline,libdd-trace-stats,libdd-trace-utils,libdd-ddsketch

## Notable changes since v36.0.0

- `feat(data-pipeline)`: export client-computed span stats as OTLP trace metrics (#2067)
- `feat(otel-thread-ctx)`: add self check capability (#2095)
- `fix(trace-stats)`: add `grpc_method` to aggregation key (#2151)
- `feat(data-pipeline)`: add stdout log trace exporter (#2074)
- `feat(remote-config)`: use the proto file from the agent (#2165)
- `feat(sidecar)`: expose `default_service_name` for `svc.*` process tags (#2053)
- feat(otlp)!: Export OTLP spans with attribute-level OTel compatibility (#2091)

Co-authored-by: munir.abdinur <[email protected]>
Signed-off-by: Taegyun Kim <[email protected]>
gh-worker-dd-mergequeue-cf854d Bot pushed a commit to DataDog/dd-trace-py that referenced this pull request Jul 21, 2026
…guration (#18495)

## Description

This PR adds ``DD_TRACE_OTEL_SEMANTICS_ENABLED`` to opt in to OpenTelemetry trace semantics for spans. The result is that using OpenTelemetry Tracing instrumentations allows DD SDKs to produce OTLP spans with nearly identical span fields.

When enabled, this updates the dd-trace-py behavior in the following ways:
- General tracing behaviors
  - Stops the library from adding the `version`, `language`, and `env` tags as span attributes
- OpenTelemetry Tracing APIs
  - `OtelSpan.set_attribute` no longer remaps span tags such as `http.response.status_code` or `service.name` so they will maintain their intended key and value type
  - `OtelSpan.record_exception` no longer sets span attributes `error.message`, `error.type`, or `error.stack`. These exist on the `exception` span event and are updated in this PR so that the `exception.stacktrace` and `exception.type` attributes on the span event match what is emitted by the OpenTelemetry SDK
  - `OtelSpan.set_status` updates the `error.message` span attribute each time a new status is registered, including recording a newer status that lacks a message

- OTLP traces export
  - Calls `enable_otel_trace_semantics()` on the libdatadog native trace exporter to remove Datadog-specific span attributes from being emitted on OTLP spans (see the related libdatadog PR for specific attribute changes)


Also makes the following fixes:
- When OTLP traces export is enabled, native span events are also enabled because OTLP spans have a first-class `events` field.

Relies on DataDog/libdatadog#2091 which implements the OTLP trace exporter changes and on #18821 which updates the libdatadog dependency.

## Testing

Unit tests are included for the updated OTel test span behavior and the native span events configuration

## Risks

Besides the native span events change, the remaining changes are opt-in so the risk is low.

## Additional Notes

Currently the libdatadog dependency is set to a development branch which contains the updated `TraceExporterBuilder::enable_otel_trace_semantics()` API 

Co-authored-by: gyuheon0h <[email protected]>
Co-authored-by: mabdinur <[email protected]>
Co-authored-by: bm1549 <[email protected]>
Co-authored-by: zach.montoya <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants