Skip to content

feat(otel-telemetry): scaffold libdd-otel-telemetry crate - #2292

Draft
mabdinur wants to merge 7 commits into
mainfrom
munir/otel-telemetry-libdatadog
Draft

feat(otel-telemetry): scaffold libdd-otel-telemetry crate#2292
mabdinur wants to merge 7 commits into
mainfrom
munir/otel-telemetry-libdatadog

Conversation

@mabdinur

Copy link
Copy Markdown
Contributor

Summary

First step towards centralizing OpenTelemetry metrics (and, in a follow-up, logs) aggregation + OTLP export into libdatadog, so dd-trace-xx language libraries can stop depending on the OpenTelemetry SDK package and keep only the lightweight API package.

This PR scaffolds a new libdd-otel-telemetry crate:

  • Builds on the upstream opentelemetry_sdk / opentelemetry-otlp crates internally (reuses real aggregation, temporality, and OTLP encoding — nothing hand-rolled).
  • Exposes a primitives-only public API: callers register an instrument once (register_instrument -> opaque InstrumentId), then push numeric values + string attribute pairs (record_counter, record_histogram, observe_gauge, ...). No SDK types, trait objects, or closures cross the boundary in either direction, so any consumer (Python via PyO3, eventually Node/Ruby/PHP/Rust via FFI) only ever touches primitives.
  • Sync and observable (callback-based) instruments look identical to the aggregator — it just receives "a resolved value for this instrument id." Scheduling when to evaluate a user's callback stays the host language's responsibility.
  • grpc (tonic, default) and http (reqwest/protobuf) OTLP transport features, matching the split already used elsewhere in the org (e.g. dd-trace-rs's OTel integration).
  • Misconfiguration (bad endpoint, unsupported protocol, exporter init failure) never panics or fails construction — it's captured as a BuildWarning and the aggregator falls back to a no-op exporter, since a broken OTel pipeline must never block a tracer from starting.
  • Driven by libdd-shared-runtime's BlockingRuntime for exporter construction, consistent with libdd-data-pipeline.

Scope: metrics only for now; logs support and a counting-exporter wrapper for export_counters() (currently a stub returning zeros) are explicit follow-ups. No -ffi C-ABI crate yet — deferred until there's a concrete non-Rust/non-PyO3 consumer.

Next: a companion draft PR against dd-trace-py adding a PyO3 wrapper around this crate.

Test plan

  • cargo check -p libdd-otel-telemetry (default grpc feature)
  • cargo check -p libdd-otel-telemetry --no-default-features --features http
  • cargo +stable clippy -p libdd-otel-telemetry --all-targets -- -D warnings (both feature sets)
  • cargo +nightly-2026-02-08 fmt --all -- --check
  • cargo nextest run -p libdd-otel-telemetry (both feature sets)
  • LICENSE-3rdparty.csv regenerated via ./scripts/update_license_3rdparty.sh

Adds a new crate providing shared OpenTelemetry metrics aggregation and
OTLP export, built on the upstream opentelemetry_sdk/opentelemetry-otlp
crates. The public API exposes only primitives (opaque instrument ids,
numeric values, string attributes) so any dd-trace-xx language binding
can consume it without depending on OTel SDK types itself. Logs support
and the counting-exporter wrapper for export_counters() are follow-ups.
@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

📚 Documentation Check Results

⚠️ 258 documentation warning(s) found

📦 libdd-otel-telemetry - 258 warning(s)


Updated: 2026-07-31 16:52:09 UTC | Commit: f4230b7 | missing-docs job results

@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

🔒 Cargo Deny Results

⚠️ 1 issue(s) found, showing only errors (advisories, bans, sources)

📦 libdd-otel-telemetry - 1 error(s)

Show output
error[unsound]: Rand is unsound with a custom logger using `rand::rng()`
   ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:89:1
   │
89 │ rand 0.8.5 registry+https://github.com/rust-lang/crates.io-index
   │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ unsound advisory detected
   │
   ├ ID: RUSTSEC-2026-0097
   ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0097
   ├ It has been reported (by [@lopopolo](https://github.com/lopopolo)) that the `rand` library is [unsound](https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#soundness-of-code--of-a-library) (i.e. that safe code using the public API can cause Undefined Behaviour) when all the following conditions are met:
     
     - The `log` and `thread_rng` features are enabled
     - A [custom logger](https://docs.rs/log/latest/log/#implementing-a-logger) is defined
     - The custom logger accesses `rand::rng()` (previously `rand::thread_rng()`) and calls any `TryRng` (previously `RngCore`) methods on `ThreadRng`
     - The `ThreadRng` (attempts to) reseed while called from the custom logger (this happens every 64 kB of generated data)
     - Trace-level logging is enabled or warn-level logging is enabled and the random source (the `getrandom` crate) is unable to provide a new seed
     
     `TryRng` (previously `RngCore`) methods for `ThreadRng` use `unsafe` code to cast `*mut BlockRng<ReseedingCore>` to `&mut BlockRng<ReseedingCore>`. When all the above conditions are met this results in an aliased mutable reference, violating the Stacked Borrows rules. Miri is able to detect this violation in sample code. Since construction of [aliased mutable references is Undefined Behaviour](https://doc.rust-lang.org/stable/nomicon/references.html), the behaviour of optimized builds is hard to predict.
   ├ Announcement: https://github.com/rust-random/rand/pull/1763
   ├ Solution: Upgrade to >=0.10.1 OR <0.10.0, >=0.9.3 OR <0.9.0, >=0.8.6 (try `cargo update -p rand`)
   ├ rand v0.8.5
     └── (dev) libdd-common v5.1.0
         ├── libdd-capabilities-impl v3.0.0
         │   └── libdd-shared-runtime v2.0.0
         │       └── libdd-otel-telemetry v0.1.0
         └── libdd-shared-runtime v2.0.0 (*)

advisories FAILED, bans ok, sources ok

Updated: 2026-07-31 16:54:03 UTC | Commit: f4230b7 | dependency-check job results

@datadog-datadog-prod-us1

datadog-datadog-prod-us1 Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
Patch Coverage: 50.53%
Overall Coverage: 74.75% (+0.14%)

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

The new crate's files had no owner, failing the "Not Owned File Checker".

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@dd-octo-sts

dd-octo-sts Bot commented Jul 28, 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 87.12 MB 87.12 MB 0% (0 B) 👌
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.so 8.01 MB 8.01 MB 0% (0 B) 👌
aarch64-unknown-linux-gnu
Artifact Baseline Commit Change
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.so 10.77 MB 10.77 MB 0% (0 B) 👌
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.a 98.37 MB 98.37 MB 0% (0 B) 👌
libdatadog-x64-windows
Artifact Baseline Commit Change
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.dll 25.99 MB 25.99 MB 0% (0 B) 👌
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.lib 89.18 KB 89.18 KB 0% (0 B) 👌
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.pdb 187.88 MB 187.87 MB -0% (-16.00 KB) 👌
/libdatadog-x64-windows/debug/static/datadog_profiling_ffi.lib 977.90 MB 977.90 MB 0% (0 B) 👌
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.dll 8.47 MB 8.47 MB 0% (0 B) 👌
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.lib 89.18 KB 89.18 KB 0% (0 B) 👌
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.pdb 25.05 MB 25.05 MB 0% (0 B) 👌
/libdatadog-x64-windows/release/static/datadog_profiling_ffi.lib 49.83 MB 49.83 MB 0% (0 B) 👌
libdatadog-x86-windows
Artifact Baseline Commit Change
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.dll 22.60 MB 22.60 MB 0% (0 B) 👌
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.lib 90.58 KB 90.58 KB 0% (0 B) 👌
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.pdb 192.47 MB 192.47 MB 0% (0 B) 👌
/libdatadog-x86-windows/debug/static/datadog_profiling_ffi.lib 966.88 MB 966.88 MB 0% (0 B) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.dll 6.54 MB 6.54 MB 0% (0 B) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.lib 90.58 KB 90.58 KB 0% (0 B) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.pdb 26.91 MB 26.91 MB 0% (0 B) 👌
/libdatadog-x86-windows/release/static/datadog_profiling_ffi.lib 47.42 MB 47.42 MB 0% (0 B) 👌
x86_64-alpine-linux-musl
Artifact Baseline Commit Change
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.a 77.73 MB 77.73 MB 0% (0 B) 👌
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.so 8.91 MB 8.91 MB 0% (0 B) 👌
x86_64-unknown-linux-gnu
Artifact Baseline Commit Change
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.a 93.20 MB 93.20 MB 0% (0 B) 👌
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.so 10.84 MB 10.84 MB 0% (0 B) 👌

@pr-commenter

pr-commenter Bot commented Jul 28, 2026

Copy link
Copy Markdown

Benchmarks

Comparison

Benchmark execution time: 2026-07-31 17:24:06

Comparing candidate commit 9b08d7d in PR branch munir/otel-telemetry-libdatadog with baseline commit 7b8cb2a in branch main.

Found 20 performance improvements and 9 performance regressions! Performance is the same for 113 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 ----------------------------------'

scenario:concentrator/add_spans_to_concentrator

  • 🟩 execution_time [-980.680µs; -973.507µs] or [-10.201%; -10.127%]

scenario:normalization/normalize_service/normalize_service/[empty string]

  • 🟩 execution_time [-2.664µs; -2.640µs] or [-6.977%; -6.913%]
  • 🟩 throughput [+1945293.815op/s; +1963118.270op/s] or [+7.429%; +7.497%]

scenario:vec_map/as_deduped_map/already_deduped/8

  • 🟥 execution_time [+0.828ns; +0.849ns] or [+5.575%; +5.720%]

scenario:vec_map/contains_key/16

  • 🟥 execution_time [+15.651ns; +16.036ns] or [+6.291%; +6.446%]
  • 🟥 throughput [-3897142.413op/s; -3804049.467op/s] or [-6.059%; -5.915%]

scenario:vec_map/dedup/no_duplicates/128

  • 🟩 execution_time [-1.891µs; -1.858µs] or [-27.753%; -27.256%]

scenario:vec_map/dedup/no_duplicates/16

  • 🟩 execution_time [-250.261ns; -243.056ns] or [-27.602%; -26.808%]

scenario:vec_map/dedup/no_duplicates/64

  • 🟩 execution_time [-933.868ns; -914.721ns] or [-26.927%; -26.375%]

scenario:vec_map/dedup/no_duplicates/8

  • 🟩 execution_time [-118.507ns; -114.315ns] or [-25.556%; -24.652%]

scenario:vec_map/get_hit/128

  • 🟩 execution_time [-4.067µs; -4.059µs] or [-24.642%; -24.591%]
  • 🟩 throughput [+2529752.456op/s; +2534699.281op/s] or [+32.623%; +32.686%]

scenario:vec_map/get_hit/16

  • 🟩 execution_time [-37.994ns; -37.780ns] or [-15.199%; -15.113%]
  • 🟩 throughput [+11399611.491op/s; +11467210.957op/s] or [+17.811%; +17.916%]

scenario:vec_map/get_hit/64

  • 🟩 execution_time [-948.904ns; -945.015ns] or [-21.774%; -21.685%]
  • 🟩 throughput [+4067960.632op/s; +4086558.556op/s] or [+27.700%; +27.826%]

scenario:vec_map/get_hit/8

  • 🟩 throughput [+8691503.980op/s; +10827003.747op/s] or [+7.216%; +8.989%]

scenario:vec_map/get_mut/128

  • 🟥 execution_time [+1.967µs; +2.057µs] or [+14.122%; +14.771%]
  • 🟥 throughput [-1189080.495op/s; -1135300.387op/s] or [-12.933%; -12.348%]

scenario:vec_map/get_mut/16

  • 🟥 execution_time [+21.565ns; +31.808ns] or [+7.738%; +11.414%]
  • 🟥 throughput [-6163978.083op/s; -4120072.966op/s] or [-10.640%; -7.112%]

scenario:vec_map/get_mut/64

  • 🟥 execution_time [+447.737ns; +488.730ns] or [+11.528%; +12.583%]
  • 🟥 throughput [-1856739.570op/s; -1696519.992op/s] or [-11.260%; -10.288%]

scenario:vec_map/iter/128

  • 🟩 execution_time [-8.727ns; -8.612ns] or [-7.752%; -7.651%]
  • 🟩 throughput [+94277721.288op/s; +95446944.511op/s] or [+8.291%; +8.394%]

scenario:vec_map/iter/16

  • 🟩 execution_time [-0.574ns; -0.564ns] or [-4.199%; -4.129%]
  • 🟩 throughput [+50414610.872op/s; +51272659.130op/s] or [+4.308%; +4.381%]

scenario:vec_map/iter/8

  • 🟩 execution_time [-0.557ns; -0.549ns] or [-7.689%; -7.591%]
  • 🟩 throughput [+90816677.269op/s; +92069530.225op/s] or [+8.216%; +8.330%]

Benchmark execution time: 2026-07-31 17:38:16

Comparing candidate commit 9b08d7d in PR branch munir/otel-telemetry-libdatadog with baseline commit 7b8cb2a in branch main.

Found 35 performance improvements and 11 performance regressions! Performance is the same for 96 metrics, 10 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:alloc_free/system/16

  • 🟥 execution_time [+1.115ns; +1.156ns] or [+7.786%; +8.073%]

scenario:alloc_free/system/256

  • 🟥 execution_time [+1.177ns; +1.219ns] or [+8.243%; +8.535%]

scenario:alloc_free/system/4096

  • 🟩 execution_time [-28.908ns; -28.728ns] or [-31.022%; -30.828%]

scenario:alloc_free/system/64

  • 🟥 execution_time [+1.176ns; +1.225ns] or [+8.234%; +8.576%]

scenario:credit_card/is_card_number/ 3782-8224-6310-005

  • 🟩 execution_time [-5.386µs; -5.282µs] or [-6.731%; -6.601%]
  • 🟩 throughput [+884004.438op/s; +901078.603op/s] or [+7.074%; +7.210%]

scenario:credit_card/is_card_number/ 378282246310005

  • 🟩 execution_time [-5.193µs; -5.117µs] or [-7.066%; -6.962%]
  • 🟩 throughput [+1019071.099op/s; +1033394.125op/s] or [+7.490%; +7.595%]

scenario:credit_card/is_card_number/378282246310005

  • 🟩 execution_time [-5.154µs; -5.068µs] or [-7.336%; -7.214%]
  • 🟩 throughput [+1107765.870op/s; +1125275.541op/s] or [+7.783%; +7.906%]

scenario:credit_card/is_card_number/37828224631000521389798

  • 🟩 execution_time [-6.548µs; -6.500µs] or [-12.526%; -12.435%]
  • 🟩 throughput [+2717183.471op/s; +2739626.411op/s] or [+14.203%; +14.320%]

scenario:credit_card/is_card_number/x371413321323331

  • 🟥 execution_time [+729.384ns; +746.295ns] or [+12.368%; +12.655%]
  • 🟥 throughput [-19113276.977op/s; -18631337.233op/s] or [-11.271%; -10.986%]

scenario:credit_card/is_card_number_no_luhn/ 378282246310005

  • 🟩 execution_time [-4.857µs; -4.813µs] or [-8.327%; -8.251%]
  • 🟩 throughput [+1542732.971op/s; +1556021.313op/s] or [+8.999%; +9.076%]

scenario:credit_card/is_card_number_no_luhn/378282246310005

  • 🟩 execution_time [-5.110µs; -5.054µs] or [-9.229%; -9.128%]
  • 🟩 throughput [+1815820.367op/s; +1834192.741op/s] or [+10.054%; +10.156%]

scenario:credit_card/is_card_number_no_luhn/37828224631000521389798

  • 🟩 execution_time [-6.514µs; -6.466µs] or [-12.463%; -12.371%]
  • 🟩 throughput [+2701302.128op/s; +2723814.292op/s] or [+14.120%; +14.237%]

scenario:credit_card/is_card_number_no_luhn/x371413321323331

  • 🟥 execution_time [+738.262ns; +755.316ns] or [+12.538%; +12.828%]
  • 🟥 throughput [-19376384.762op/s; -18889241.536op/s] or [-11.408%; -11.121%]

scenario:datadog_sample_span/complex_rule_partial_match/wall_time

  • 🟩 execution_time [-14.697ns; -14.520ns] or [-5.843%; -5.773%]

scenario:datadog_sample_span/many_attributes_tag_rule/wall_time

  • 🟩 execution_time [-22.976ns; -22.612ns] or [-6.230%; -6.131%]

scenario:datadog_sample_span/multiple_rules_first_match/wall_time

  • 🟩 execution_time [-14.215ns; -14.066ns] or [-8.259%; -8.173%]

scenario:datadog_sample_span/multiple_rules_last_match/wall_time

  • 🟩 execution_time [-17.213ns; -17.055ns] or [-8.086%; -8.011%]

scenario:datadog_sample_span/name_pattern_rule_not_matching/wall_time

  • 🟩 execution_time [-13.384ns; -13.272ns] or [-7.703%; -7.639%]

scenario:datadog_sample_span/resource_pattern_rule_matching/wall_time

  • 🟩 execution_time [-16.524ns; -16.275ns] or [-5.995%; -5.905%]

scenario:datadog_sample_span/resource_pattern_rule_not_matching/wall_time

  • 🟩 execution_time [-20.079ns; -19.885ns] or [-11.270%; -11.160%]

scenario:datadog_sample_span/service_rule_matching/wall_time

  • 🟩 execution_time [-16.119ns; -15.856ns] or [-6.104%; -6.004%]

scenario:datadog_sample_span/service_rule_not_matching/wall_time

  • 🟩 execution_time [-17.857ns; -17.693ns] or [-11.919%; -11.810%]

scenario:datadog_sample_span/tag_rule_matching/wall_time

  • 🟩 execution_time [-30.692ns; -30.459ns] or [-8.699%; -8.633%]

scenario:datadog_sample_span/tag_rule_not_matching/wall_time

  • 🟩 execution_time [-16.076ns; -15.832ns] or [-10.436%; -10.277%]

scenario:ddsketch_encode/encode_to_vec/clustered_near_zero

  • 🟩 execution_time [-47.888ns; -42.639ns] or [-6.419%; -5.715%]

scenario:ddsketch_encode/encode_to_vec/large_values

  • 🟩 execution_time [-69.699ns; -65.031ns] or [-7.652%; -7.139%]

scenario:ddsketch_encode/encode_to_vec/mixed

  • 🟩 execution_time [-88.955ns; -82.664ns] or [-6.777%; -6.297%]

scenario:ddsketch_read/ordered_bins/collapsing

  • 🟥 execution_time [+1.229µs; +1.239µs] or [+5.104%; +5.145%]

scenario:ddsketch_read/ordered_bins/mixed

  • 🟥 execution_time [+464.457ns; +469.780ns] or [+4.367%; +4.417%]

scenario:glob_matcher/ascii_case_insensitive_match/wall_time

  • 🟩 execution_time [-1.542ns; -1.506ns] or [-5.465%; -5.339%]

scenario:glob_matcher/ascii_exact_match/wall_time

  • 🟩 execution_time [-1.530ns; -1.501ns] or [-5.424%; -5.321%]

scenario:glob_matcher/ascii_exact_miss/wall_time

  • 🟩 execution_time [-1.702ns; -1.666ns] or [-12.798%; -12.527%]

scenario:glob_matcher/ascii_wildcard_question_match/wall_time

  • 🟩 execution_time [-23.462ns; -23.443ns] or [-38.915%; -38.884%]

scenario:glob_matcher/ascii_wildcard_star_match/wall_time

  • 🟩 execution_time [-25.352ns; -25.332ns] or [-40.527%; -40.496%]

scenario:sql/obfuscate_sql_string

  • 🟩 execution_time [-17.489µs; -17.278µs] or [-5.885%; -5.814%]

scenario:trace_buffer/4_senders/no_delay

  • 🟥 execution_time [+122.268µs; +148.258µs] or [+5.169%; +6.267%]
  • 🟥 throughput [-91186.302op/s; -74986.996op/s] or [-5.986%; -4.923%]

Candidate

Omitted due to size.

Baseline

Omitted due to size.

mabdinur added a commit to DataDog/dd-trace-py that referenced this pull request Jul 29, 2026
Adds a native module (TelemetryAggregatorBuilder / TelemetryAggregator)
wrapping libdatadog's new libdd-otel-telemetry crate, exposing OTel
metrics aggregation + OTLP export to Python over a primitives-only
boundary (opaque instrument ids, numeric values, string attr pairs).

All libdatadog deps point at the munir/otel-telemetry-libdatadog-v37
branch, which is the v37.0.0 tag plus only the additive
libdd-otel-telemetry crate (DataDog/libdatadog#2292). Every other crate
on that branch is byte-identical to v37.0.0, so no unrelated changes are
pulled in, and a single git ref avoids duplicate copies of shared crates
that would break trait bounds across the graph.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ggregator

The type is OTel-metrics-specific (SdkMeterProvider + PeriodicReader + OTLP
metric exporter), but "TelemetryAggregator" read as generic and collided with
the tracer-telemetry concept. Rename to make the scope explicit and leave room
for per-signal siblings (e.g. OtelLogs*) later:

  TelemetryAggregator        -> OtelMetricsAggregator
  TelemetryAggregatorBuilder -> OtelMetricsAggregatorBuilder
  TelemetryAggregatorError   -> OtelMetricsError

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
mabdinur added a commit to DataDog/dd-trace-py that referenced this pull request Jul 29, 2026
…tricsAggregator

Follows the libdatadog rename (DataDog/libdatadog#2292): the native classes
are OTel-metrics-specific, so make the names say so. Also drop the custom
TelemetryAggregatorInternalError exception (nothing caught it by reference) and
raise a plain RuntimeError from force_flush/shutdown instead.

  TelemetryAggregator{,Builder}  -> OtelMetricsAggregator{,Builder}
  TelemetryAggregatorInternalError -> removed (RuntimeError)

Bumps the libdatadog dep to the renamed v37-based branch commit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
mabdinur and others added 4 commits July 30, 2026 15:03
Bump opentelemetry/opentelemetry_sdk/opentelemetry-otlp from 0.31 to 0.32 so
the exporter matches dd-trace-rs's SDK version. Add DatadogMetricExporter, a
PushMetricExporter that wraps the OTLP MetricExporter and tracks export
attempts/successes/failures (centralized equivalent of dd-trace-rs's old
TelemetryTrackingExporter), plus build_datadog_metric_exporter to construct it.
Refactor the existing build_metric_exporter and Counters to be shared. The
in-process OtelMetricsAggregator is unchanged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…uild

Under --all-features the `http` feature is on, so http/protobuf is a *supported*
protocol and the aggregator builds a real reqwest-backed exporter — which, under
opentelemetry-otlp 0.32 + workspace feature unification, eagerly builds a rustls
client and panics with "No provider set". The test's scenario (unsupported
protocol -> warning, not panic) only exists without the http feature, so gate it
there. A positive http-exporter test needs a crypto provider installed (TODO).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The aggregator registered every instrument on one hardcoded meter
("libdd-otel-telemetry"), so exported OTLP metrics lost the host's
instrumentation scope — all metrics reported scope name "libdd-otel-telemetry"
and distinct meters collapsed into one scope. Carry the meter name/version/
schema_url on InstrumentDescriptor and create/cache one SDK Meter per scope so
exports keep the host's get_meter identity.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… + fix http TLS

Add canonical, pure config-parsing helpers to `config.rs` so every consumer
(dd-trace-rs, dd-trace-py via PyO3) shares one implementation instead of
hand-rolling case-sensitive matches:

- `OtlpProtocol::from_config_str` accepts `grpc`/`http/protobuf`/`http/json`
  case-insensitively (adds an `HttpJson` variant for parity with dd-trace-rs;
  it reports as an unsupported export protocol like before).
- `Temporality::from_config_str` accepts `delta`/`cumulative` case-insensitively,
  defaulting to `Delta` for empty/unknown.
- `parse_otlp_headers` parses `k1=v1,k2=v2` header strings.

Also fix the `http` exporter: reqwest+rustls 0.23 panics with no process-default
crypto provider under feature unification. Best-effort install the ring provider
before building the http exporter (ring only; aws-lc-rs stays FIPS-only).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant